pythonpygame

Pygame sprite is not visible


I am making a game in which you have to roll the blue block to the "Touch me" text. When I run the code, the blue block is not visible and there are no problems found in VS Code. How can I solve this problem and make the blue block visible?

import sys
import pygame

WIDTH, HEIGHT = 800, 600
BLUE = (0, 0, 255)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)

screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("I wanna make a game")
square_size = 50
x, y = WIDTH // 2, HEIGHT // 2
speed = 5


class Sprite(pygame.sprite.Sprite):
    def __init__(self, color, height, width):
        super().__init__()
        self.image = pygame.Surface([square_size, square_size])
        self.image.fill(BLUE)
        self.image.set_colorkey(BLUE)
        pygame.draw.rect(self.image, color, pygame.Rect(0, 0, width, height))
        self.rect = self.image.get_rect()

    def moveRight(self, pixels):
        self.rect.x += pixels

    def moveLeft(self, pixels):
        self.rect.x -= pixels

    def moveUp(self, speed):
        self.rect.y += speed * speed/10

    def moveDown(self, speed):
        self.rect.y -= speed * speed/10


pygame.init()
pygame.font.init()

player = Sprite(BLUE, 30, 30)
all_sprites_list = pygame.sprite.Group()
all_sprites_list.add(player)
player.rect.x = 50
player.rect.y = 50

running = True
while running:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
    font2 = pygame.font.SysFont('arial.ttf', 40)
    touchme = font2.render('Touch me', True, WHITE)

    keys = pygame.key.get_pressed()
    if keys[pygame.K_w]:
        player.moveUp(10)
    if keys[pygame.K_s]:
        player.moveDown(10)
    if keys[pygame.K_a]:
        player.moveLeft(10)
    if keys[pygame.K_d]:
        player.moveRight(10)

    x = max(0, min(WIDTH - square_size, x))
    y = max(0, min(HEIGHT - square_size, y))
    screen.fill((0, 0, 0))
    screen.blit(touchme, (10, 300))

    all_sprites_list.update()

    all_sprites_list.draw(screen)
    pygame.display.flip()
    pygame.time.Clock().tick(60)

pygame.quit()
sys.exit()

Solution

  • Your blue block is invisible because you're drawing and filling the sprite surface in the Sprite class, combined with set_colorkey(BLUE). Pygame makes anything blue on the sprite surface transparent. Since you fill the whole surface with blue here self.image.fill(BLUE) and then draw a rectangle of the same blue color (or even a different one, but it's drawn on a transparent surface), the entire sprite becomes invisible. So to fix, remove self.image.set_colorkey(BLUE) because it makes BLUE transparent on the Surface.

    Apart from that, the movement logic direction is swapped: In moveUp, you increase y, and in moveDown you decrease it. That’s reversed.

    def moveUp(self, speed):
        self.rect.y -= speed * speed / 10
    def moveDown(self, speed):
        self.rect.y += speed * speed / 10
    

    Your final working code should look like this:

    import pygame, sys
    pygame.init()
    pygame.font.init()
    
    WIDTH, HEIGHT = 800, 600
    BLUE = (0, 0, 255)
    WHITE = (255, 255, 255)
    GREEN = (0,255,0)
    
    screen = pygame.display.set_mode((WIDTH, HEIGHT))
    pygame.display.set_caption("I wanna make a game")
    square_size = 50
    speed = 5
    
    class Sprite(pygame.sprite.Sprite):
        def __init__(self, color, height, width):
            super().__init__()
            self.image = pygame.Surface([square_size, square_size])
            self.image.fill(color)
            self.rect = self.image.get_rect()
    
        def moveRight(self, pixels):
            self.rect.x += pixels
        def moveLeft(self, pixels):
            self.rect.x -= pixels
        def moveUp(self, speed):
            self.rect.y -= speed * speed / 10
        def moveDown(self, speed):
            self.rect.y += speed * speed / 10
    
    player = Sprite(BLUE, 30, 30)
    all_sprites_list = pygame.sprite.Group()
    all_sprites_list.add(player)
    player.rect.x = 50
    player.rect.y = 50
    
    running = True
    while running:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
    
        font2 = pygame.font.SysFont('arial', 40)
        touchme = font2.render('Touch me', True, WHITE)
    
        keys = pygame.key.get_pressed()
        if keys[pygame.K_w]:
            player.moveUp(5)
        if keys[pygame.K_s]:
            player.moveDown(5)
        if keys[pygame.K_a]:
            player.moveLeft(5)
        if keys[pygame.K_d]:
            player.moveRight(5)
    
        screen.fill((0, 0, 0))
        screen.blit(touchme, (10, 300))
        all_sprites_list.update()
        all_sprites_list.draw(screen)
        pygame.display.flip()
        pygame.time.Clock().tick(60)
    
    pygame.quit()
    sys.exit()