How to remove PyGame smudge trails left behind by moving objects

blit, pygame, python

Solution

Basically, you are right! The circles are drawn directly onto the background, and everytime new circles are drawn, the old circles remain. Resulting in the smudges/trails.

You can just change `background` to `screen` in your `draw` method. This will fix it.

But it is really worth using the `Sprite` classes as intended. I've made a few changes to your code to switch it over for you. With these changes it runs without trails :)

Here are the changes and explainations:

Add this near the top:

#Create a new `pygame.Surface`, and draw a circle on it, then set transparency:
circle = pygame.Surface((30,30))
circle = circle.convert()
pygame.draw.circle(circle, (171, 130, 255), (int(15),int(15)), 15, 0)
circle.set_colorkey(circle.get_at((0, 0)), pygame.RLEACCEL)

Add this to the `asteroid`, `__init__` method:

#Sets the asteroid image, and then the asteroids co-ords (these are in `rect`)
        self.image = circle
        self.rect = self.image.get_rect()

Add this to the end of `def move(self):`

        self.rect[0] = self.x
        self.rect[1] = self.y

change:

my_particles = []

to:

#This is a special pygame container class, it has a draw() method that tracks changed areas of the screen.
my_particles = pygame.sprite.RenderUpdates()

change:

my_particles.append(target)

to:

my_particles.add(target)

change:

while True:
    pygame.display.update()
    screen.blit(background, (0,0))
    MouseP = pygame.mouse.get_pos()
    frames = Clock.get_fps
    pygame.mouse.set_visible
    score = (pygame.time.get_ticks()/1000)
    print (score)
    print (MouseP)
    for target in my_particles:
        target.move()
        target.boundaries()
        target.display()
        pygame.display.update()

to:

#initial screen draw:
screen.blit(background, (0,0))
pygame.display.update()
while True:
    #remove previous drawn sprites and replaces with background:
    my_particles.clear(screen, background)
    MouseP = pygame.mouse.get_pos()
    frames = Clock.get_fps
    pygame.mouse.set_visible
    score = (pygame.time.get_ticks()/1000)
    print (score)
    print (MouseP)
    for target in my_particles:
        target.move()
        target.boundaries()
    #draws changed sprites to the screen:
    pygame.display.update(my_particles.draw(screen))

Remove the `display` method as it is no longer needed.

This will also run a lot faster than the your earlier code, as the time taken to draw something is proportional to the size of the drawing area, and previously it was drawing the whole background every time - now it only draws the sprites and changes to the background!

Problem

This program was created using Python 3.2.2 and the corresponding compatible version of pygame. I also realize a more efficient method would be to use sprites, sprite groups and 'dirty rect' updating but I'm unable to convert the program and so I will continue without the added benefits of such functions. Problem: Smudge trails where the 'asteroids' are moving are left behind. Hypothesis: Background is blitted onto the screen however the asteroids are blitted onto the Background. ``` import pygame import random import math pygame.init() height = 550 width = 750 screen = pygame.display.set_mode((width, height)) background = pygame.image.load("Planet.jpg") Clock = pygame.time.Clock() class asteroid(pygame.sprite.Sprite): def __init__(self, x, y, size): pygame.sprite.Sprite.__init__(self) self.x = x self.y = y self.size = 15 self.speed = 0.0 self.angle = 0 self.colour = (171, 130, 255) self.thickness = 0 def display(self): pygame.draw.circle(background, self.colour, (int(self.x),int(self.y)), self.size, self.thickness) pygame.draw.circle(background, (255, 255, 255), (int(self.x),int(self.y)), self.size, 1) def move(self): self.x += math.sin(self.angle) * self.speed self.y -= math.cos(self.angle) * self.speed def boundaries(self): if self.x > width - self.size: self.x = 0 + self.size elif self.x < self.size: self.x = width - self.size if self.y > height - self.size: self.y = 0 + self.size elif self.y <self.size: self.y = height - self.size num_target = 5 my_particles = [] num_particles = len(my_particles) while num_particles < 5: for n in range(num_target): size = 20 x = random.randint(size, height - size) y = random.randint(size, width - size) target = asteroid(x, y, size) target.speed = random.uniform(1.0, 1.0) target.angle = random.uniform(0, math.pi*2) my_particles.append(target) num_particles = num_particles + 1 def main(): pygame.display.set_caption("Anyu's Game") screen.blit(background, (0,0)) pygame.display.update() score = (pygame.time.get_ticks()/1000) print (score) while True: pygame.display.update() screen.blit(background, (0,0)) MouseP = pygame.mouse.get_pos() frames = Clock.get_fps pygame.mouse.set_visible score = (pygame.time.get_ticks()/1000) print (score) print (MouseP) for target in my_particles: target.move() target.boundaries() target.display() pygame.display.update() for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit(); if __name__=='__main__': main() ``` How can I resolve this problem?

Original source