How to get rid of pygame surfaces?

2019-03-21 16:13发布

问题:

In the following code, there is not just one circle on the screen at any given point in time. I want to fix this to make it so that it looks like there is only one circle, instead of leaving a smudge trail where ever the mouse cursor has been.

import pygame,sys
from pygame.locals import *
pygame.init()

screen = pygame.display.set_mode((640,400),0,32)

radius = 25
circle = pygame.Surface([radius*2]*2,SRCALPHA,32)
circle = circle.convert_alpha()
pygame.draw.circle(circle,(25,46,100),[radius]*2,radius)

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

    screen.blit(circle,(pygame.mouse.get_pos()[0],100))

    pygame.display.update()
    pygame.time.delay(10)

回答1:

You need to specifically erase the circle before you blit it again. Depending on how complicated your scene is, you may have to try different methods. Generally what I do is have a "background" surface that a blit to the screen every frame and then blit the sprites/other surfaces in their new positions (blits in Pygame are very fast, so even in fairly large screens I haven't had speed issues doing this). For your code above, it's simple enough just to use surface.fill(COLOR) where COLOR is your background color; eg, (255,255,255) for white:

# ...
screen = pygame.display.set_mode((640,400),0,32)
backgroundColor = (255,255,255)
# ...
while True:
    # ...
    screen.fill(backgroundColor)
    screen.blit(circle,(pygame.mouse.get_pos()[0],100))
    pygame.display.update()
    pygame.time.delay(10)

Edit in answer to your comment: It is possible to do this in a more object-oriented way.

You will need to have a background Surface associated with your screen (I usually have a Display or Map class (depending on the type of game) that does this). Then, make your object a subclass of pygame.sprite. This requires that you have self.image and self.rect attributes (the image being your surface and the rect being a Pygame.rect with the location). Add all of your sprites to a pygame.group object. Now, every frame, you call the draw method on the group and, after you update the display (ie, with pygame.display.update()), you call the clear method on the group. This method requires that you provide both the destination surface (ie, screen above) and a background image.

For example, your main loop may look more like this:

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

    circle.rect.center = (pygame.mouse.get_pos()[0],100)
    circleGroup.draw(screen)

    pygame.display.update()
    circleGroup.clear(screen, backgroundSurface)
    pygame.time.delay(10)

See the documentation on the Sprite and Group classes for more information.