【问题标题】:Pygame screen won't fill or draw textPygame 屏幕不会填充或绘制文本
【发布时间】:2018-01-02 16:59:40
【问题描述】:

我是 pygame 和 python 的新手,我只是在制作一个简单的“Dodger”游戏。我创建了一个带有一些按钮的主菜单。

我的主菜单:

# show the start screen
done=False
while not done:
    screen.fill(black)
    text_width,text_height=font.size("Dodger")
    #a function for drawing text
    drawText('Dodger', font, screen, (screen_width / 2-(text_width/2)), (screen_height / 2-200))
    font = pygame.font.SysFont(None, 45)
    start_button=button(screen_width/2-125,175,250,50,white,black,'Start')
    start_button.draw()
    instructions_button=button(screen_width/2-125,250,250,50,white,black,'Instructions')
    instructions_button.draw()
    back_button=button(screen_width/2-125,325,250,50,white,black,'Back')
    back_button.draw()
    pygame.display.flip()

我还有一个按钮类:

class button(object):
    def __init__(self,x,y,width,height,text_color,background_color,text):
        self.rect=pygame.Rect(x,y,width,height)
        self.image=pygame.draw.rect(screen, background_color,(self.rect),)
        self.x=x
        self.y=y
        self.width=width
        self.height=height
        self.text=text
        self.text_color=text_color

    def check(self):
        return self.rect.collidepoint(pygame.mouse.get_pos())

    def draw(self):
        drawText(self.text,font,screen,self.x+self.width/2,self.y+self.height/2,self.text_color)  
        pygame.draw.rect(screen,self.text_color,self.rect,3) 

两个按钮工作,但第三个没有响应。

我的代码如下所示:

#show start screen
done=False
while not done:
    screen.fill(black)
    text_width,text_height=font.size("Dodger")
    drawText('Dodger', font, screen, (screen_width / 2-(text_width/2)), (screen_height / 2-200))
    font = pygame.font.SysFont(None, 45)
    #the start button starts the game
    start_button=button(screen_width/2-125,175,250,50,white,black,'Start')
    start_button.draw()
    #my button that is not working
    instructions_button=button(screen_width/2-125,250,250,50,white,black,'Instructions')
    instructions_button.draw()
    #go back to game selection
    back_button=button(screen_width/2-125,325,250,50,white,black,'Back')
    back_button.draw()
    pygame.display.flip()
    while not done:
        for event in pygame.event.get():
                if event.type==QUIT:
                    terminate()
                elif event.type == pygame.MOUSEBUTTONDOWN:
                    if start_button.check()==True:
                            #main game code
                    if instructions_button.check()==True:
                            #show instructions
                    if back_button.check()==True:
                            #go back to game selection

但是,我的“说明”按钮不工作,虽然其他两个工作。

代码:

elif instructions_button.check()==True:
screen.fill(black)
drawText('some instructions',font,screen,screen_width/2-127.5, 185)
back_button.draw()
done=False
while not done:
for event in pygame.event.get():
    if event.type==QUIT:
        terminate()
    elif back_button.check()==True:
        done=True     

问题是当我点击按钮时,屏幕没有填满(screen.fill(black)或绘制我的文本(drawText('some instructions',font,screen,screen_width/2-127.5, 185))。

在尝试调试它时,我放置了各种print('hello') 以查看它为什么不起作用:

elif instructions_button.check()==True:
    print('hello')
    screen.fill(black)
    print('hello')
    drawText('some instructions',font,screen,screen_width/2-127.5, 185)
    back_button.draw()
    done=False
    while not done:
    for event in pygame.event.get():
        if event.type==QUIT:
            terminate()
        elif back_button.check()==True:
            done=True 

它打印但没有用黑色填充屏幕。

感谢所有帮助!

完整代码:

import pygame,sys,os,random
from pygame.locals import *
from cPickle import load
from asyncore import write

#initalize pygame
pygame.init()

#define colors
black=(0,0,0)
white=(255,255,255)

def terminate():
    pygame.quit()
    sys.exit()

def drawText(text,font,screen,x,y,color):
    textobj=font.render(text,True,color)
    textrect=textobj.get_rect(center=(x,y))
    screen.blit(textobj,textrect)

class button(object):
    def __init__(self,x,y,width,height,text_color,background_color,text):
        self.rect=pygame.Rect(x,y,width,height)
        self.image=pygame.draw.rect(screen, background_color,(self.rect),)
        self.x=x
        self.y=y
        self.width=width
        self.height=height
        self.text=text
        self.text_color=text_color

    def check(self):
        return self.rect.collidepoint(pygame.mouse.get_pos())

    def draw(self):
        drawText(self.text,font,screen,self.x+self.width/2,self.y+self.height/2,self.text_color)  
        pygame.draw.rect(screen,self.text_color,self.rect,3) 

def dodger(screen,clock):
    global button
    #define variables
    white=(255,255,255)
    black=(0,0,0)
    fps=40
    baddieminsize=10
    baddiemaxsize=40
    baddieminspeed=1
    baddiemaxspeed=8
    addnewbaddierate=6
    player_speed=5

    def terminate():
        pygame.quit()
        sys.exit()

    def waitForPlayerToPressKey():
        while True:
            for event in pygame.event.get():
                if event.type==QUIT:
                    terminate()
                if event.type==KEYDOWN:
                    if event.key==K_ESCAPE: # pressing escape quits
                        terminate()
                    return

    def playerHasHitBaddie(playerRect, baddies):
        for b in baddies:
            if playerRect.colliderect(b['rect']):
                return True
        return False

    def drawText(text, font, surface, x, y):
        textobj = font.render(text, 1, white)
        textrect = textobj.get_rect()
        textrect.topleft = (x, y)
        surface.blit(textobj, textrect)

    def load_hs():
        try:
            f = open("dodger_hs.txt","rb")
            hs = int(f.read())
            f.close()
            return hs
        except:
            return 0
    def write_hs(hs):
        f = open("dodger_hs.txt","wb")
        f.write(str(hs).encode())
        f.close()

    # set up fonts
    font = pygame.font.SysFont(None, 90)

    # set up images
    playerImage = pygame.image.load('player.png')
    playerRect = playerImage.get_rect()
    baddieImage = pygame.image.load('baddie.png')

    # show the start screen
    done=False
    while not done:
        screen.fill(black)
        text_width,text_height=font.size("Dodger")
        drawText('Dodger', font, screen, (screen_width / 2-(text_width/2)), (screen_height / 2-200))
        font = pygame.font.SysFont(None, 45)
        start_button=button(screen_width/2-125,175,250,50,white,black,'Start')
        start_button.draw()
        instructions_button=button(screen_width/2-125,250,250,50,white,black,'Instructions')
        instructions_button.draw()
        back_button=button(screen_width/2-125,325,250,50,white,black,'Back')
        back_button.draw()
        pygame.display.flip()
        while not done:
            for event in pygame.event.get():
                    if event.type==QUIT:
                        terminate()
                    elif event.type == pygame.MOUSEBUTTONDOWN:
                        if start_button.check()==True:
                                while not done:
                                    # set up the start of the game
                                    baddies = []
                                    score = 0
                                    playerRect.topleft = (screen_width / 2, screen_height- 50)
                                    moveLeft = moveRight = moveUp = moveDown = False
                                    reverseCheat = slowCheat = False
                                    baddieAddCounter = 0
                                    high_score=load_hs()

                                    while True: # the game loop runs while the game part is playing
                                        score += 1 # increase score

                                        for event in pygame.event.get():
                                            if event.type == QUIT:
                                                terminate()

                                            if event.type == KEYDOWN:
                                                if event.key == ord('z'):
                                                    reverseCheat = True
                                                if event.key == ord('x'):
                                                    slowCheat = True
                                                if event.key == K_LEFT or event.key == ord('a'):
                                                    moveRight = False
                                                    moveLeft = True
                                                if event.key == K_RIGHT or event.key == ord('d'):
                                                    moveLeft = False
                                                    moveRight = True
                                                if event.key == K_UP or event.key == ord('w'):
                                                    moveDown = False
                                                    moveUp = True
                                                if event.key == K_DOWN or event.key == ord('s'):
                                                    moveUp = False
                                                    moveDown = True

                                            if event.type == KEYUP:
                                                if event.key == ord('z'):
                                                    reverseCheat = False
                                                if event.key == ord('x'):
                                                    slowCheat = False
                                                if event.key == K_ESCAPE:
                                                        terminate()

                                                if event.key == K_LEFT or event.key == ord('a'):
                                                    moveLeft = False
                                                if event.key == K_RIGHT or event.key == ord('d'):
                                                    moveRight = False
                                                if event.key == K_UP or event.key == ord('w'):
                                                    moveUp = False
                                                if event.key == K_DOWN or event.key == ord('s'):
                                                    moveDown = False

                                        # Add new baddies at the top of the screen, if needed.
                                        if not reverseCheat and not slowCheat:
                                            baddieAddCounter += 1
                                        if baddieAddCounter == addnewbaddierate:
                                            baddieAddCounter = 0
                                            baddieSize = random.randint(baddieminsize, baddiemaxsize)
                                            newBaddie = {'rect': pygame.Rect(random.randint(0, screen_width-baddieSize), 0 - baddieSize, baddieSize, baddieSize),
                                                        'speed': random.randint(baddieminspeed, baddiemaxspeed),
                                                        'surface':pygame.transform.scale(baddieImage, (baddieSize, baddieSize)),
                                                        }

                                            baddies.append(newBaddie)

                                        # Move the player around.
                                        if moveLeft and playerRect.left > 0:
                                            playerRect.move_ip(-1 * player_speed, 0)
                                        if moveRight and playerRect.right < screen_width:
                                            playerRect.move_ip(player_speed, 0)
                                        if moveUp and playerRect.top > 0:
                                            playerRect.move_ip(0, -1 * player_speed)
                                        if moveDown and playerRect.bottom < screen_height:
                                            playerRect.move_ip(0, player_speed)

                                        # Move the baddies down.
                                        for b in baddies:
                                            if not reverseCheat and not slowCheat:
                                                b['rect'].move_ip(0, b['speed'])
                                            elif reverseCheat:
                                                b['rect'].move_ip(0, -5)
                                            elif slowCheat:
                                                b['rect'].move_ip(0, 1)

                                        # Delete baddies that have fallen past the bottom.
                                        for b in baddies[:]:
                                            if b['rect'].top > screen_height:
                                                baddies.remove(b)

                                        if score>=high_score:
                                            high_score=score

                                        # Draw the game world on the window.
                                        screen.fill(black)

                                        # Draw the player's rectangle
                                        screen.blit(playerImage, playerRect)

                                        # Draw each baddie
                                        for b in baddies:
                                            screen.blit(b['surface'], b['rect'])

                                        # Draw the score
                                        drawText('Score: %s' % (score), font, screen, 10, 0)
                                        drawText('High Score: %s' % (high_score), font, screen, 10, 30)

                                        pygame.display.update()

                                        # Check if any of the baddies have hit the player.
                                        if playerHasHitBaddie(playerRect, baddies):
                                            break

                                        clock.tick(fps)

                                    write_hs(high_score)
                                    screen.fill(black)
                                    if score<100:   
                                        drawText('Your Score: %s' % (score), font,screen,screen_width/2-107.5, 185)
                                    if score<1000 and score>99:
                                        drawText('Your Score: %s' % (score), font,screen,screen_width/2-117.5, 185)
                                    if score<10000 and score>999:
                                        drawText('Your Score: %s' % (score), font,screen,screen_width/2-127.5, 185)
                                    if score<100000 and score>9999:
                                        drawText('Your Score: %s' % (score), font,screen,screen_width/2-127.5, 185)
                                    font = pygame.font.SysFont(None, 90)
                                    text_width,text_height=font.size("Game Over")
                                    drawText('Game Over', font, screen, (screen_width / 2-(text_width/2)), (screen_height / 2-200))
                                    font = pygame.font.SysFont(None, 45)
                                    retry_button=button(screen_width/2-125,250,250,50,white,black,'Retry')
                                    retry_button.draw()
                                    back_button.draw()
                                    pygame.display.flip()
                                    back=False 
                                    while not back:
                                        for event in pygame.event.get():
                                                if event.type==QUIT:
                                                    terminate()
                                                elif event.type == pygame.MOUSEBUTTONDOWN:
                                                    if retry_button.check()==True:
                                                        back=True
                                                    if back_button.check()==True:
                                                        back=True
                                                        done=True
                        elif instructions_button.check()==True:
                            screen.fill(black)
                            drawText('Your Score:', font,screen,screen_width/2-127.5, 185)
                            back_button.draw()
                            done=False
                            while not done:
                                for event in pygame.event.get():
                                        if event.type==QUIT:
                                            terminate()
                                        elif back_button.check()==True:
                                            done=True                               
                        elif back_button.check()==True:
                            done=True


#define other varibles           
clock=pygame.time.Clock()
font=pygame.font.SysFont(None,40)
done=False

#set up screen
screen_width=600
screen_height=600
screen=pygame.display.set_mode([screen_width,screen_height])
pygame.display.set_caption('The Arcade')

#set up buttons
dodger_button=button(25,75,125,50,white,black,'Dodger')

#main loop
while not done:
    for event in pygame.event.get():
            if event.type==QUIT:
                terminate()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                if dodger_button.check():
                    dodger(screen, clock)

    #fill screen with background
    screen.fill(black)

    #draw buttons
    dodger_button.draw()

    #draw text
    drawText('The Arcade', font, screen, screen_width/2, 25, white)

    #change display
    pygame.display.flip()
    clock.tick(15)

terminate()

【问题讨论】:

  • 顺便说一句:有规则/建议使用 CamelCaseNames 进行课程 - 即。 Button 而不是 button - 它有助于识别代码中的类。甚至 Stackoverflow 也知道这个规则,并且在课堂上使用浅蓝色。更多:PEP 8 -- Style Guide for Python Code
  • 您不必使用self.xself.yself.widthself.height - 您可以使用self.rect 来保持位置和大小。而不是self.x+self.width/2 你有self.rect.centerx, self.rect.centery
  • pygame.draw.rect() 不返回图像,而是返回 pygame.Rect() 的位置和大小。所以分配给self.image 具有误导性。
  • 你检查back_button.check()==True 没有MOUSEBUTTONDOWN 所以当鼠标悬停在按钮上但你没有使用鼠标按钮时它可以被“点击”。您可以更改功能,以便您可以执行button.check(event),然后您可以在check() 中检查MOUSEBUTTONDOWN。您可以使用event.pos 获取鼠标位置。
  • 正如 furas 所提到的,您还必须在所有子 while 循环中调用 pygame.display.flip(或 display.update)(clock.tick(fps) 也是)。我认为你应该以不同的方式构建你的程序。看看这个example

标签: python pygame


【解决方案1】:

问题是因为你没有使用pygame.display.update()

所有函数都在 RAM 内存中的缓冲区中绘制,update()/flip() 将数据从内存中的缓冲区发送到视频卡中的缓冲区,然后将其显示在屏幕上。它被称为"Double Buffering",用作图像闪烁/撕裂的解决方案。


顺便说一句:你也忘记了MOUSEBUTTONDOWN 所以按钮Back 在鼠标触摸按钮而不使用鼠标按钮时被“点击”。

其他问题 - 您使用 done 变量退出“指令”,但相同的变量控制外部 while 循环,因此它退出游戏。你必须使用不同的变量。如果你会使用这个内部函数,那么它不会产生问题并且代码会更好地组织。

您不必使用==True 来检查它。

但您可以在 == 周围和 , 之后使用空格,以使代码更具可读性。
见:PEP 8 -- Style Guide for Python Code

 elif instructions_button.check():
      screen.fill(black)
      drawText('Your Score:', font, screen, screen_width/2-127.5, 185)
      back_button.draw()
      pygame.display.update() # <-- send to video card
      doneX = False # <-- use different variable
      while not doneX:
           for event in pygame.event.get():
               if event.type == QUIT:
                   terminate()
               elif event.type == pygame.MOUSEBUTTONDOWN: # <-- check mouse click
                   if back_button.check():
                       doneX = True 

您不必创建两个函数drawText()terminate()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多