问题
I'm trying to create a "text based game" in a window, using fonts and makeshift buttons. Everything works fine, but when there are multiple buttons on the screen and only one is pressed, the others' collisions carry over to the next screen and mess everything up. While doing debugging, I noticed that pressing the button on the next screen briefly works, but then goes to the 2nd button from the first screen, ex. I press the first button, button on second screen works, but bugs out by triggering the second button on the first screen. Here's the code:
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()
The problem stems from the stuff in choice 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
And while debugging, I found this: (solitary numbers are the choice number)
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
I'm not really sure why it's behaving this way, or why in this IDLE shell the program went back to choice 2 like expected, but then reverted to the second button declaration in choice 2. It's like everything before fBUTTON4 is disabled. Please, try to run the program yourself and see if you encounter the same error. Help is appreciated!
回答1:
I have reviewed your code and I understand what is happening. The main issue is actually happening in the create function of the Button class.
You have some buttons that are is roughly the same position when they get rendered on the screen. An example of this is the continue button in choice1 and the 3.Look right down the hallway in choice2.
When I click the top of the continue button in choice1, the screen goes to choice2 and thinks I am clicking the 3.Look right down the hallway button in choic2. That will immediately take me to choice5.
What we need to do is make sure that a user releases the mouse button in between clicks.
To do this I have added 6 lines to your program. At the top of the file I added a new variable under the isReady2 variable:
isReady2 = False
hasBeenReleased = not pygame.mouse.get_pressed()[0]
That will check if the player has the mouse button held down or it is released when they start the game.
Next, I added code so they have to release the mouse button before they can click again. I am pasting the code that you already have and then pasting my solution.
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
Here is my fix:
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]
The code checks if the button has been released previously. If it has been released then we can check if it is currently being clicked. If it is being clicked then we hasBeenReleased = False to let us know they did actually click.
The section that lets them click again is:
elif not hasBeenReleased:
hasBeenReleased = not pygame.mouse.get_pressed()[0]
If we check if they recently clicked and then set the value equal to if they have released the button or if they are still holding it down.
Using this code I was able to go back and forth between choice 2 and 3.
来源:https://stackoverflow.com/questions/31715230/weird-bug-in-program-that-turns-off-certain-objects-after-they-are-used