简体   繁体   中英

Pygame screen won't fill or draw text

I am new to pygame and python, and I am just making a simple "Dodger" game. I have created a main menu with some buttons.

My main menu:

# 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()

I also have a button class:

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) 

Two buttons work, but the third one is not responding.

My code looks like this:

#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

However, my "instructions" button is not working, though the other two work.

Code:

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     

The problem is that when I click the button, the screen doesn't fill( screen.fill(black ) or draw my text ( drawText('some instructions',font,screen,screen_width/2-127.5, 185) ).

In my attempts to debug it, I placed various print('hello') to see why it wasn't working:

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 

It printed but didn't fill the screen with black.

All help is appreciated!

Complete code:

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()

Problem is because you didn't use pygame.display.update()

All functions draw in buffer in RAM memory and update() / flip() sends data from buffer in memory to buffer in video card which displays it on screen. It is called "Double Buffering" and it is used as soluton for image flickering/tearing.

在此处输入图片说明


BTW: you also forgot MOUSEBUTTONDOWN so button Back is "clicked" when mouse touch button without using mouse button.

Other problem - you use done variable to exit from "instruction" but the same variable control external while loop so it exits from game. You have to use different variable. If you would use this inside function then it wouldn't make problem and code would be better organzied.

You don't have to use ==True to check it.

But you could use spaces around == and after , to make code more readable.
See: 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 

You don't have to create two functions drawText() and terminate() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM