Home > Net >  Sprite not rendering correctly
Sprite not rendering correctly

Time:12-21

I'm trying to implement a simple platformer, but I have a problem with the sprites. They blink and do not move. A platform appears on the left mouse button, a square appears on the right mouse button, a square moves on the left and right arrows. It should output like this

import pygame


class Square(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height):
        super().__init__(sprites)
        self.image = pygame.Surface((width, height), pygame.SRCALPHA, 32)
        self.rect = pygame.Rect(x, y, width, height)
        pygame.draw.rect(screen, pygame.Color('blue'), pygame.Rect(x, y, width, height))

    def new_rect(self, x, y, width, height):
        self.rect = pygame.Rect(x, y, width, height)
        pygame.draw.rect(screen, pygame.Color('blue'), pygame.Rect(x, y, width, height))

    def fall(self):
        if not pygame.sprite.spritecollideany(self, platforms):
            self.rect = self.rect.move(0, 1)

    def move(self, direction):
        if direction == 'left':
            self.rect = self.rect.move(-10, 0)
        elif direction == 'right':
            self.rect = self.rect.move(10, 0)


class Platform(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height):
        super().__init__(sprites)
        self.add(platforms)
        self.image = pygame.Surface((width, height), pygame.SRCALPHA, 32)
        self.rect = pygame.Rect(x, y, width, height)
        pygame.draw.rect(screen, pygame.Color('gray'), pygame.Rect(x, y, width, height))


sprites = pygame.sprite.Group()
platforms = pygame.sprite.Group()

screen = pygame.display.set_mode((500, 500))
CUBEFALL = pygame.USEREVENT   1

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                Platform(event.pos[0], event.pos[1], 50, 10)
            elif event.button == 3:
                cube = Square(event.pos[0], event.pos[1], 20, 20)
                pygame.time.set_timer(CUBEFALL, 20)
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                cube.move('left')
            elif event.key == pygame.K_RIGHT:
                cube.move('right')
        if event.type == CUBEFALL:
            screen.fill(pygame.Color('black'))
            cube.fall()
        sprites.draw(screen)
    pygame.display.flip()
pygame.quit()

I tried to fix this problem but I didn't succeed.

CodePudding user response:

A sprite consists of an image and a rect, but doesn't draw anything. The drawing is handled by the pygame.sprite.Group. See How can I add objects to a "pygame.sprite.Group()"?. You have to fill the image of the pygame.sprite.Sprite object with a color. e.g.:

class Platform(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height):
        super().__init__()
        self.add(platforms)
        self.image = pygame.Surface((width, height), pygame.SRCALPHA, 32)
        self.image.fill(pygame.Color('gray'))
        self.rect = self.image.get_rect(topleft = (x, y))

Add the Sprties to the corresponding Group:

if event.type == pygame.MOUSEBUTTONDOWN:
    if event.button == 1:
        platforms.add(Platform(event.pos[0], event.pos[1], 50, 10))
    elif event.button == 3:
        if len(sprites) == 0:
            sprites.add(Square(event.pos[0], event.pos[1], 20, 20))

Use a pygame.sprite.GroupSingle() to contain the Square:

sprites = pygame.sprite.GroupSingle()
if event.type == pygame.KEYDOWN:
    if event.key == pygame.K_LEFT and sprites.sprite:
        sprites.sprite.move('left')
    elif event.key == pygame.K_RIGHT and sprites.sprite:
        sprites.sprite.move('right')
if event.type == CUBEFALL and sprites.sprite:
        sprites.sprite.fall()

Redraw the scene in every frame:

while running:
    # [...]

    screen.fill(pygame.Color('black'))
    platforms.draw(screen)
    sprites.draw(screen)
    pygame.display.flip()

Complete example:

import pygame

class Square(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height):
        super().__init__()
        self.image = pygame.Surface((width, height), pygame.SRCALPHA, 32)
        self.image.fill('blue')
        self.rect = self.image.get_rect(topleft = (x, y))

    def fall(self):
        if not pygame.sprite.spritecollideany(self, platforms):
            self.rect = self.rect.move(0, 1)

    def move(self, direction):
        if direction == 'left':
            self.rect = self.rect.move(-10, 0)
        elif direction == 'right':
            self.rect = self.rect.move(10, 0)


class Platform(pygame.sprite.Sprite):
    def __init__(self, x, y, width, height):
        super().__init__()
        self.add(platforms)
        self.image = pygame.Surface((width, height), pygame.SRCALPHA, 32)
        self.image.fill(pygame.Color('gray'))
        self.rect = self.image.get_rect(topleft = (x, y))


sprites = pygame.sprite.GroupSingle()
platforms = pygame.sprite.Group()

screen = pygame.display.set_mode((500, 500))
CUBEFALL = pygame.USEREVENT   1

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                platforms.add(Platform(event.pos[0], event.pos[1], 50, 10))
            elif event.button == 3:
                if len(sprites) == 0:
                    sprites.add(Square(event.pos[0], event.pos[1], 20, 20))
                pygame.time.set_timer(CUBEFALL, 20)
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT and sprites.sprite:
                sprites.sprite.move('left')
            elif event.key == pygame.K_RIGHT and sprites.sprite:
                sprites.sprite.move('right')
        if event.type == CUBEFALL and sprites.sprite:
                sprites.sprite.fall()
        
    screen.fill(pygame.Color('black'))
    platforms.draw(screen)
    sprites.draw(screen)
    pygame.display.flip()
pygame.quit()
  • Related