AmanoSkullGZ
AmanoSkullGZ

Reputation: 141

Space Invaders bug pygame

After finally beeing able to make multiple enemies in the game I confronted myself with the most annoying bug ever. I have multiple enemies, a space ship and I can even shoot bullets, but right after I added the enemies to the game and followed the exact same steps as show in this video, the background is gone for some reason, what made the speed of the player character, of the enemies and the bullet went like crazy. Plus, the sprites are duplicating themselves and wont go away, and the only think that I can think is "What the hell am I doing wrong??" because I feel like I can't even follow the steps and copy the code from a video (btw I'm not receiving any error messages). Anyways, here's the full game code.

import pygame
import random
import math

# Initiate pygame
pygame.init()

# Display the game window
screen = pygame.display.set_mode((800, 600))

# Title and Icon
pygame.display.set_caption('Space Invaders')
icon = pygame.image.load('icon.png')
pygame.display.set_icon(icon)

# Background
background = pygame.image.load('background.png')

# Player
playerSprite = pygame.image.load('player.png')
playerX = 370
playerY = 480
playerX_change = 0

# Enemies
enemySprite = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []

num_of_enemies = 6

for i in range(num_of_enemies):
    enemySprite.append(pygame.image.load('enemy.png'))
    enemyX.append(random.randint(0, 736))
    enemyY.append(random.randint(50, 150))
    enemyX_change.append(4)
    enemyY_change.append(40)

# Bullet
bulletSprite = pygame.image.load('bullet.png')
bulletX = 0
bulletY = 480
bulletY_change = 10

# When bullet_state = 'ready', you can't see the bullet on the screen
# When bullet_state = 'fire', the bullet is currently moving
bullet_state = 'ready'

score = 0


def player(x, y):
    screen.blit(playerSprite, (x, y))


def enemy(x, y, i):
    screen.blit(enemySprite[i], (x, y))


def fire_bullet(x, y):
    global bullet_state
    bullet_state = 'fire'
    screen.blit(bulletSprite, (x + 16, y + 10))


def isCollision(enemyX, enemyY, bulletX, bulletY):
    distance = math.sqrt((math.pow(enemyX - bulletX, 2)) + (math.pow(enemyY - bulletY, 2)))
    if distance < 27:
        return True
    else:
        return False


# Game Loop
running = True
while running:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

        # If a key is pressed, check if it's the right or left arrow key
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                playerX_change = -5
            if event.key == pygame.K_RIGHT:
                playerX_change = 5
            if event.key == pygame.K_SPACE:
                if bullet_state == 'ready':
                    bulletX = playerX
                    fire_bullet(playerX, bulletY)

        if event.type == pygame.KEYUP:
            if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
                playerX_change = 0

    # Player movement
    playerX += playerX_change

    # Prevents the player from going off the border
    if playerX <= 0:
        playerX = 0
    elif playerX >= 736:
        playerX = 736

    # Enemies movement
    for i in range(num_of_enemies):
        enemyX[i] += enemyX_change[i]
        if enemyX[i] <= 0:
            enemyX_change[i] = 4
            enemyY[i] += enemyX_change[i]
        elif enemyX[i] >= 736:
            enemyX_change[i] = -4
            enemyY[i] += enemyY_change[i]

            # Collision
            collision = isCollision(enemyX[i], enemyY[i], bulletX, bulletY)
            if collision:
                bulletY = 480
                bullet_state = 'ready'
                score += 1
                print(score)
                enemyX[i] = random.randint(0, 736)
                enemyY[i] = random.randint(50, 150)

        enemy(enemyX[i], enemyY[i], i)

    # Bullet movement
    if bulletY <= 0:
        bulletY = 480
        bullet_state = 'ready'

    if bullet_state == 'fire':
        fire_bullet(bulletX, bulletY)
        bulletY -= bulletY_change

    player(playerX, playerY)
    pygame.display.update()

Upvotes: 2

Views: 232

Answers (1)

Rabbid76
Rabbid76

Reputation: 211135

the background is gone for some reason

Of course, because the background is never blit to screen.

the sprites are duplicating themselves and wont go away,

That's because you don't draw the background.

blit the background in the main application loop, before the objects of the scene are drawn:

while running:
    # [...]

    screen.blit(background, (0, 0))

    # Enemies movement
    for i in range(num_of_enemies):
        # [...]

the speed of the player character, of the enemies and the bullet went like crazy.

Use pygame.time.Clock() to control the frames per second.

clock = pygame.time.Clock()
running = True
while running:
    clock.tick(60)

    # [...]

Another (less sophisticated) possibility, which is probably use in the tutorial is to use pygame.time.delay():

running = True
while running:
    pygame.time.delay(10)

    # [...]

Upvotes: 2

Related Questions