简体   繁体   中英

Why does the game lag when I load an image and when I display pygame shapes?

Just out of curiosity, why does a game lag when I load an image as well as display pygame shapes for example rectangles, circles and ellipses. I have this code where you shoot the ghosts that fall down (I'm still working on the shooting part). I made the cannon out of pygame shapes. But when I run it the images of the ghosts are prefect but the images of the cannons lag and disappears and reappear and so on. Is there any way to stop this lag or disappear and reappear thing? I'm running python 2.6 with windows vista.

import pygame, sys, random, math
from pygame.locals import *

WINDOWHEIGHT = 600
WINDOWWIDTH = 600
FPS = 30
BACKGROUNDCOLOR = (255, 255, 255)
TEXTCOLOR = (0, 0, 0)
WHITE    = (255, 255, 255)
BLACK    = (  0,   0,   0)
BROWN    = (139,  69,  19)
DARKGRAY = (128, 128, 128)
BGCOLOR = WHITE

GHOSTSPEED = 10
GHOSTSIZE = 20
ADDNEWGHOSTRATE = 8

def keyToPlayAgain():
    while True:
        for event in event.type.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == KEYDOWN:
                return

def getAngle(x1, y1, x2, y2):
    # Return value is 0 for right, 90 for up, 180 for left, and 270 for down (and all values between 0 and 360)
    rise = y1 - y2
    run = x1 - x2
    angle = math.atan2(run, rise) # get the angle in radians
    angle = angle * (180 / math.pi) # convert to degrees
    angle = (angle + 90) % 360 # adjust for a right-facing sprite
    return angle

def Text(text, font, surface, x, y):
    textobj = font.render(text, 2, TEXTCOLOR)
    textrect = textobj.get_rect()
    textrect.topleft = (x, y)
    surface.blit(textobj, textrect)

pygame.init()
mainClock = pygame.time.Clock()
DISPLAYSURF = pygame.display.set_mode((WINDOWHEIGHT, WINDOWWIDTH))
pygame.display.set_icon(pygame.image.load('s.icon'))
pygame.display.set_caption('Ghost Invasion Pacfighters')
pygame.mouse.set_visible(False)

font = pygame.font.SysFont(None, 48)

gameOverSound = pygame.mixer.Sound('gameover.wav')
pygame.mixer.music.load('background.mid')

ghostImage = pygame.image.load('ghosts.png')
dotImage = pygame.image.load('dot.png')
dotRect = dotImage.get_rect()
creditsPage = pygame.image.load('credits.png')
titlePage = pygame.image.load('title.png')

pygame.time.wait(10000)
DISPLAYSURF.blit(creditsPage, (0, 0))
pygame.time.wait(10000)
DISPLAYSURF.blit(titlePage, (0, 0))
pygame.display.update()

cannonSurf = pygame.Surface((100, 100))
cannonSurf.fill(BGCOLOR)
pygame.draw.circle(cannonSurf, DARKGRAY, (20, 50), 20) 
pygame.draw.circle(cannonSurf, DARKGRAY, (80, 50), 20) 
pygame.draw.rect(cannonSurf, DARKGRAY, (20, 30, 60, 40)) 
pygame.draw.circle(cannonSurf, BLACK, (80, 50), 15) 
pygame.draw.circle(cannonSurf, BLACK, (80, 50), 20, 1) 
pygame.draw.circle(cannonSurf, BROWN, (30, 70), 20) 
pygame.draw.circle(cannonSurf, BLACK, (30, 70), 20, 1) 

health = 100
score = 0
topScore = 0
while True:
    ghosts = []
    moveLeft = moveRight = moveUp = moveDown = False
    reverseCheat = slowCheat = False
    ghostAddCounter = 0
    pygame.mixer.music.play(-1, 0.0)

    while True:
        for event in pygame.event.get():
            if event.type == QUIT:
                pygame.quit()
                sys.exit()
            elif event.type == KEYDOWN:
                if event.key == K_x:
                    bombs()
                elif event.type == ESCAPE:
                    pygame.quit()
                    sys.exit()

        mousex, mousey = pygame.mouse.get_pos()
        for cannonx, cannony in ((100, 500), (500, 500)):

            degrees = getAngle(cannonx, cannony, mousex, mousey)

            rotatedSurf = pygame.transform.rotate(cannonSurf, degrees)
            rotatedRect = rotatedSurf.get_rect()
            rotatedRect.center = (cannonx, cannony)
            DISPLAYSURF.blit(rotatedSurf, rotatedRect)

            pygame.draw.line(DISPLAYSURF, BLACK, (mousex - 10, mousey), (mousex + 10, mousey))
            pygame.draw.line(DISPLAYSURF, BLACK, (mousex, mousey - 10), (mousex, mousey + 10))

            pygame.draw.rect(DISPLAYSURF, BLACK, (0, 0, WINDOWWIDTH, WINDOWHEIGHT), 1)

            pygame.display.update()

        if not reverseCheat and not slowCheat:
            ghostAddCounter += 1
        if ghostAddCounter == ADDNEWGHOSTRATE:
            ghostAddCounter = 0
            newGhost = {'rect': pygame.Rect(random.randint(0, WINDOWWIDTH-GHOSTSIZE), 0 - GHOSTSIZE, GHOSTSIZE, GHOSTSIZE),
                        'speed': (GHOSTSIZE),
                        'surface':pygame.transform.scale(ghostImage, (GHOSTSIZE, GHOSTSIZE)),
                        }

            ghosts.append(newGhost)

        for s in ghosts:
            if not reverseCheat and not slowCheat:
                s['rect'].move_ip(0, s['speed'])
            elif reverseCheat:
                s['rect'].move_ip(0, -5)
            elif slowCheat:
                s['rect'].move_ip(0, -1)

        for s in ghosts[:]:
            if s['rect'].top > WINDOWHEIGHT:
                health -= 10

        DISPLAYSURF.fill(BACKGROUNDCOLOR)

        Text('Score: %s' % (score), font, DISPLAYSURF, 10, 0)
        Text('Top score: %s' % (topScore), font, DISPLAYSURF, 10, 40)
        Text('Health: %s' % (health), font, DISPLAYSURF, 10, 560)

        for s in ghosts:
            DISPLAYSURF.blit(s['surface'], s['rect'])

        pygame.display.update()

        mainClock.tick(FPS)

    pygame.mixer.music.stop()
    gameOverSound.play()

    Text('GAME OVER', font, windowSurface, (WINDOWWIDTH / 3), (WINDOWHEIGHT / 3))
    pygame.display.update()
    keyToPlayAgain()
    pygame.display.update()

    gameOverSound.stop()

The problem is that you draw your cannons, update the display, then clear the display, draw the other stuff, and update the display again. You basically never see the falling ghosts and the cannons at the same time. This results in the flickering you see.

So remove pygame.display.update() from this for loop

    for cannonx, cannony in ((100, 500), (500, 500)):
        ...
        pygame.display.update()

and put DISPLAYSURF.fill(BACKGROUNDCOLOR) at the top of your while loop (or at least before you draw anything):

while True:
    for event in pygame.event.get():
        ...

    mousex, mousey = pygame.mouse.get_pos()

    DISPLAYSURF.fill(BACKGROUNDCOLOR)

    for cannonx, cannony in ((100, 500), (500, 500)):
        ...

It's best to clear the background once at the start of your code that draws everything, and call pygame.display.update() once at the end of that drawing code.

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