pythonpython-3.xpygamegame-developmentpygame2

Problem with Pygame Animating a Moving Sprite


I'm trying to make a game and when I want to make a moving sprite, there's trail that is behind it. When I remove it, then the sprite is not animated. When I try to fix that, it stops moving.

As far as I know the problem is to do with the group sprites not being deleted after they're added. but if I do that by using remove or reputing the group in the game loop, it stops the object from being animated

Here is the code:(would like an explanation to what I was doing wrong too)

import pygame, sys, random
pygame.init()
screen = pygame.display.set_mode((1280, 720))
pygame.display.set_caption("Game")
clock = pygame.time.Clock()
x = 100
y = 100
state_change_timer = 0
state = 0
go_back_part1 = False
go_back_part2 = False

# assets
bg = (20, 20, 20)
color_1 = (50, 10, 50)
color_2 = (70, 10, 70)
color_3 = (90, 10, 90)
color_4 = (110, 110, 10)
block_1 = pygame.Surface((100, 100))
block_2 = pygame.Surface((100, 100))
block_3 = pygame.Surface((100, 100))
block_4 = pygame.Surface((100, 100))
block_1.fill(color_1)
block_2.fill(color_2)
block_3.fill(color_3)
block_4.fill(color_4)
BG = pygame.Surface((1280, 720))
BG.fill((20, 20, 20))
# classes
class player(pygame.sprite.Sprite):
    state_change_timer = 0
    state = 0
    go_back_part1 = False
    go_back_part2 = False
    def __init__(self, pos_x, pos_y):
        super().__init__()
        self.animate = False
        self.sprites = [block_1, block_2, block_3, block_4]
        self.current_sprite = 0
        self.image = self.sprites[self.current_sprite]
        pygame.transform.smoothscale(self.image, (128,128))

        self.rect = self.image.get_rect()
        self.rect.topleft = [pos_x, pos_y]
    def is_animating(self):
        self.animate = True
    def update(self):
        player.state_change_timer += 1
        if player.state_change_timer == 5:
            if player.state == 3:
                player.state -= 1
                player.go_back_part1 = True
            if player.go_back_part1 == True:
                player.state -= 1
                player.go_back_part1 = False
                player.go_back_part2 = True
            if player.go_back_part2 == True:
                player.state -= 1
                player.go_back_part2 = False
            else:
                player.state += 1
            player.state_change_timer = 0
        self.current_sprite = player.state
        self.image = self.sprites[self.current_sprite]


# sprite groups
moving_sprites = pygame.sprite.Group()
Player = player(x, y)
moving_sprites.add(Player)

# game loop

while True:
    keys = pygame.key.get_pressed()
    Player = player(x, y)
    moving_sprites.add(Player)
    moving_sprites.remove(Player)
    pre_x = x
    pre_y = y
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        if keys[pygame.K_w]:
            y -= 1
            Player.is_animating()
        if keys[pygame.K_s]:
            y += 1
            Player.is_animating()
        if keys[pygame.K_a]:
            x -= 1
            Player.is_animating()
        if keys[pygame.K_d]:
            x += 1
            Player.is_animating()
    # drawing
    screen.blit(BG, (0, 0))
    moving_sprites.draw(screen)
    moving_sprites.update()
    pygame.display.flip()
    clock.tick(60)

Solution

  • You have to create the sprite and add it to the group before the application loop instead of continuously recreating the sprite in the loop. Also you need to modify the player attributes (Player.rect) instead of x and y:

    Player = player(x, y)
    moving_sprites.add(Player)
    run = True
    while run:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
    
        keys = pygame.key.get_pressed()
        move_x = (keys[pygame.K_d] - keys[pygame.K_a])
        move_y = (keys[pygame.K_s] - keys[pygame.K_w])
        Player.rect.x += move_x 
        Player.rect.y += move_y 
        Player.animate = move_x != 0 or move_y != 0
        moving_sprites.update()
        
        screen.blit(BG, (0, 0))
        moving_sprites.draw(screen)
        pygame.display.flip()
        clock.tick(60)
    
    pygame.quit()
    sys.exit()