python - 程序中的奇怪错误,某些对象在使用后出现 "turns off"

标签 python pygame

我正在尝试使用字体和临时按钮在窗口中创建“基于文本的游戏”。一切工作正常,但是当屏幕上有多个按钮并且只按下一个按钮时,其他按钮的碰撞会转移到下一个屏幕并弄乱一切。在进行调试时,我注意到按下下一个屏幕上的按钮会短暂起作用,但然后会转到第一个屏幕上的第二个按钮,例如。我按下第一个按钮,第二个屏幕上的按钮可以工作,但通过触发第一个屏幕上的第二个按钮会出现错误。代码如下:

import pygame, sys
from pygame.locals import *

pygame.init()

window = pygame.display.set_mode((640, 480))

starting = 0
choiceNum = 0
isReady = False
isReady2 = False

#old debug tool - hasBeenClicked = False

fList = []

FONTtitle = pygame.font.SysFont('arial black', 20)
FONT = pygame.font.SysFont('arial black', 15)

YELLOW = (255, 255, 0)
RED = (255, 0, 0)
GREEN = (0, 255, 40)
BLUE = (0, 0, 255)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)

class StoryFont():
    def __init__(self, FONT, string, x, y, window):
        self.FONT = FONT
        self.string = string
        self.x = x
        self.y = y
        self.window = window
        self.fSFont = 0

    def create(self):
        self.fSFont = self.FONT.render(self.string, False, WHITE)
        self.fSFontr = self.fSFont.get_rect()
        self.fSFontr.center = (self.x,self.y)

    def blit(self):
        self.window.blit(self.fSFont, self.fSFontr)

class Button():
    def __init__(self, FONT, string, x1, y1, x2, y2, fontx, fonty, choiceNum, window):
        self.FONT = FONT
        self.string = string
        self.x1 = x1
        self.y1 = y1
        self.x2 = x2
        self.y2 = y2
        self.fontx = fontx
        self.fonty = fonty
        self.choiceNum = choiceNum
        self.hasBeenClicked = False
        self.window = window
        self.fSFont = 0

    def create(self):
        self.fSFont = self.FONT.render(self.string, False, WHITE)
        self.fSFontr = self.fSFont.get_rect()
        self.fSFontr.center = (self.fontx, self.fonty)
        self.window.blit(self.fSFont, self.fSFontr)


        if self.hasBeenClicked == False:
            if pos[1] >= self.fonty - 17.5 and pos[1] <= self.fonty + 17.5 and pos[0] >= self.fontx - 47.5 and pos[0] <= self.fontx + 47.5:
                pygame.draw.rect(window, BLUE, ((self.x1, self.y1), (self.x2, self.y2)), 0)
                window.blit(self.fSFont, self.fSFontr)

                if pygame.mouse.get_pressed()[0] == True:
                    global starting
                    self.hasBeenClicked = True
                    starting = self.choiceNum
                    isReady2 = False
                    window.fill(BLACK)
                    return starting


            else:
                global isReady2
                isReady2 = False






def blitMenu(FONTtitle):
    pygame.display.set_caption("Text Game")
    fTITLE = StoryFont(FONTtitle, "Text Game", 320, 100, window)
    fTITLE.create()

    fBUTTON = Button(FONTtitle, "Start", 285, 285, 70, 30, 320, 300, 1, window)

    def blitMenuDraw():

        window.fill(BLACK)
        fTITLE.blit()
        fBUTTON.create()
    blitMenuDraw()


def choice1(FONT):
    fSTORY = StoryFont(FONT, "You are Mr. Stetkiewicz, a seventh grade science teacher.", 320, 50, window)
    fSTORY.create()

    fSTORY2 = StoryFont(FONT, "One day, when coming into your class room to teach about the", 320, 70, window)
    fSTORY2.create()

    fSTORY3 = StoryFont(FONT, "behavior of convection, you notice that no one is there.", 320, 90, window)
    fSTORY3.create()

    fSTORY4 = StoryFont(FONT, "Everything seems cold and somewhat dark.", 320, 140, window)
    fSTORY4.create()

    fSTORY5 = StoryFont(FONT, "Eventually you realize that there is a lack of thermal energy,", 320, 190, window)
    fSTORY5.create()

    fSTORY6 = StoryFont(FONT, "as if it has been stolen. Infuriated, you grab your trusty frying pan", 320, 210, window)
    fSTORY6.create()

    fSTORY7 = StoryFont(FONT, "engraved with '212 degree boiling point', and set out on your journey", 320, 230, window)
    fSTORY7.create()

    fSTORY8 = StoryFont(FONT, "to restore thermal energy to the school.", 320, 250, window)
    fSTORY8.create()

    fSTORY9 = StoryFont(FONT, "Good Luck!", 320, 300, window)
    fSTORY9.create()

    fBUTTON2 = Button(FONT, "Continue", 270, 385, 100, 30, 320, 400, 2, window)


    def choice1Draw():

        window.fill(BLACK)
        fSTORY.blit()
        fSTORY2.blit()
        fSTORY3.blit()
        fSTORY4.blit()
        fSTORY5.blit()
        fSTORY6.blit()
        fSTORY7.blit()
        fSTORY8.blit()
        fSTORY9.blit()
        fBUTTON2.create()

    choice1Draw()

def choice2(FONT):

    fSTORY = StoryFont(FONT, "You have just exited the doorway to your classroom.", 320, 170, window)
    fSTORY.create()

    fSTORY2 = StoryFont(FONT, "What would you like to do?", 320, 230, window)
    fSTORY2.create()

    fBUTTON3 = Button(FONT, "1.Check Inventory", 240, 300, 160, 25, 320, 310, 3, window)

    fBUTTON4 = Button(FONT, "2.Look left down the hallway.", 190, 330, 260, 25, 320, 345, 4, window)

    fBUTTON5 = Button(FONT, "3.Look right down the hallway.", 185, 365, 265, 25, 320, 380, 5, window)

    global fList
    fList = [fSTORY, fSTORY2, fBUTTON3, fBUTTON4, fBUTTON5]

    if fBUTTON3.hasBeenClicked == True:
        fBUTTON4.hasBeenClicked = True
        fBUTTON5.hasBeenClicked = True

    if fBUTTON4.hasBeenClicked == True:
        fBUTTON3.hasBeenClicked = True
        fBUTTON5.hasBeenClicked = True

    if fBUTTON5.hasBeenClicked == True:
        fBUTTON3.hasBeenClicked = True
        fBUTTON4.hasBeenClicked = True

    print(str(fBUTTON3.hasBeenClicked) + "button 3")
    print(str(fBUTTON4.hasBeenClicked) + "button 4")
    print(str(fBUTTON5.hasBeenClicked) + "button 5")


    choice2Draw(fList, window)

def choice2Draw(fList, window):
    window.fill(BLACK)
    fList[0].blit()
    fList[1].blit()
    fList[2].create()
    fList[3].create()
    fList[4].create()

    global isReady2


def choice3(FONT):
    #print("HI")

    fSTORY = StoryFont(FONT, "You are currently holding a frying pan and a pencil in your hands.", 320, 200, window)
    fSTORY.create()

    fSTORY2 = StoryFont(FONT, "You are also wearing glasses, and your work clothes.", 320, 220, window)
    fSTORY2.create()

    fBUTTON = Button(FONT, "Back", 190, 330, 260, 25, 320, 345, 2, window)

    def choice3Draw():
        window.fill(BLACK)
        fSTORY.blit()
        fSTORY2.blit()
        fBUTTON.create()

        global isReady2

    choice3Draw()

def choice4(FONT):
    print("in choice 4")

def choice5(FONT):
    print("in choice 5")

while True:
    pos = pygame.mouse.get_pos()
    if starting == 0:
        blitMenu(FONTtitle)
        print(str(starting))

    if starting == 1:
        choice1(FONT)
        print(str(starting))

    if starting == 2:
        choice2(FONT)
        print(str(starting))

    if starting == 2.5:
        choice2Draw(fList, window)
        print(str(starting))

    if starting == 3:
        choice3(FONT)
        print(str(starting))

    if starting == 4:
        choice4(FONT)
        print(str(starting))

    if starting == 5:
        choice5(FONT)
        print(str(starting))



    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()
    pygame.display.update()

问题源于选择2中的内容:

def choice2(FONT):

    fSTORY = StoryFont(FONT, "You have just exited the doorway to your classroom.", 320, 170, window)
    fSTORY.create()

    fSTORY2 = StoryFont(FONT, "What would you like to do?", 320, 230, window)
    fSTORY2.create()

    fBUTTON3 = Button(FONT, "1.Check Inventory", 240, 300, 160, 25, 320, 310, 3, window)

    fBUTTON4 = Button(FONT, "2.Look left down the hallway.", 190, 330, 260, 25, 320, 345, 4, window)

    fBUTTON5 = Button(FONT, "3.Look right down the hallway.", 185, 365, 265, 25, 320, 380, 5, window)

    global fList
    fList = [fSTORY, fSTORY2, fBUTTON3, fBUTTON4, fBUTTON5]

    if fBUTTON3.hasBeenClicked == True:
        fBUTTON4.hasBeenClicked = True
        fBUTTON5.hasBeenClicked = True

    if fBUTTON4.hasBeenClicked == True:
        fBUTTON3.hasBeenClicked = True
        fBUTTON5.hasBeenClicked = True

    if fBUTTON5.hasBeenClicked == True:
        fBUTTON3.hasBeenClicked = True
        fBUTTON4.hasBeenClicked = True

    print(str(fBUTTON3.hasBeenClicked) + "button 3")
    print(str(fBUTTON4.hasBeenClicked) + "button 4")
    print(str(fBUTTON5.hasBeenClicked) + "button 5")


    choice2Draw(fList, window)

def choice2Draw(fList, window):
    window.fill(BLACK)
    fList[0].blit()
    fList[1].blit()
    fList[2].create()
    fList[3].create()
    fList[4].create()

    global isReady2

在调试时,我发现了这个:(单个数字是选择数字)

3
3
3
3
3
True inside button class
2
False button 3
False button 4
False button 5
True inside button class
4
in choice 4
4
in choice 4
4
in choice 4
4
in choice 4
4
in choice 4
4
in choice 4

我不太确定为什么它会这样,或者为什么在这个 IDLE shell 中程序像预期的那样返回到选择 2,但随后又恢复到选择 2 中的第二个按钮声明。就像禁用 fBUTTON4 之前的所有内容一样。请尝试自己运行该程序,看看是否遇到同样的错误。感谢帮助!

最佳答案

我已经查看了您的代码,并且了解发生了什么。主要问题实际上发生在 Button 类的 create 函数中。

您有一些按钮在屏幕上渲染时的位置大致相同。例如,选择 1 中的“继续”按钮和选择 2 中的“3.向右看走廊”。

当我单击 choice1 中的继续按钮顶部时,屏幕转到 choice2,并认为我正在单击 3.向右查看 choic2 中的走廊按钮。这将立即带我做出选择5。

我们需要做的是确保用户在两次点击之间释放鼠标按钮。

为此,我在您的程序中添加了 6 行。在文件顶部,我在 isReady2 变量下添加了一个新变量:

isReady2 = False
hasBeenReleased = not pygame.mouse.get_pressed()[0]

这将检查玩家是否按住了鼠标按钮,或者在开始游戏时松开了鼠标按钮。

接下来,我添加了代码,以便他们必须释放鼠标按钮才能再次单击。我将粘贴您已有的代码,然后粘贴我的解决方案。

if self.hasBeenClicked == False:
        if pos[1] >= self.fonty - 17.5 and pos[1] <= self.fonty + 17.5 and pos[0] >= self.fontx - 47.5 and pos[0] <= self.fontx + 47.5:
            pygame.draw.rect(window, BLUE, ((self.x1, self.y1), (self.x2, self.y2)), 0)
            window.blit(self.fSFont, self.fSFontr)

            if pygame.mouse.get_pressed()[0] == True:
                global starting
                self.hasBeenClicked = True
                starting = self.choiceNum
                isReady2 = False
                window.fill(BLACK)
                return starting

这是我的修复:

if self.hasBeenClicked == False:
    if pos[1] >= self.fonty - 17.5 and pos[1] <= self.fonty + 17.5 and pos[0] >= self.fontx - 47.5 and pos[0] <= self.fontx + 47.5:
        pygame.draw.rect(window, BLUE, ((self.x1, self.y1), (self.x2, self.y2)), 0)
        window.blit(self.fSFont, self.fSFontr)

        global hasBeenReleased
        if hasBeenReleased and pygame.mouse.get_pressed()[0] == True:
            hasBeenReleased = False
            global starting
            self.hasBeenClicked = True
            starting = self.choiceNum
            isReady2 = False
            window.fill(BLACK)
            return starting
        elif not hasBeenReleased:
            hasBeenReleased = not pygame.mouse.get_pressed()[0]

该代码检查按钮之前是否已被释放。如果它已被释放,那么我们可以检查它当前是否被点击。如果它被点击,那么我们hasBeenReleased = False让我们知道他们确实点击了。

让他们再次点击的部分是:

elif not hasBeenReleased:
    hasBeenReleased = not pygame.mouse.get_pressed()[0]

如果我们检查他们最近是否单击过,然后将值设置为等于他们是否已释放按钮或是否仍按住按钮。

使用此代码,我能够在选择 2 和 3 之间来回切换。

关于python - 程序中的奇怪错误,某些对象在使用后出现 "turns off",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31715230/

相关文章:

python - 我有一个巨大的 If 语句列表,想清理我的代码

python套接字文件传输

Python字典迭代

python - 导入 xlrd 值 append 到列表

python - while 循环执行类,然后停止而不是重新开始?

python - 从导入的脚本中使用 Pygame 模块

python - OpenGL:相机 theta 和缩放

python - 无法在 conda 中安装 matplotlib

python - 在 Pygame 中将一条线作为 Sprite 并具有自己的碰撞

python - Pygame 中自上而下的运动/等距运动