Space Invader Game Using Pygame



Space Invader Game is a basic 2-dimensional game that has been developed using a well-known framework for Python known as Pygame. The game involves a player controlling a spaceship, whereby he/she fires at other spaceships while at the same time avoiding the bullets that are fired at him/her by the other spaceships. Challenges are well designed to increase in this game after the score is received with increased velocities and firing rates of enemies.

How to Play Space Invader Game?

1. Starting the Game

First, press the ENTER key on your keyboard to start the game

Space Invader Game 1

2. Movement

Use the A and D keys to move the spaceship left and right. Use W to move up and S to move down.

Space Invader Game 2

3. Shooting

Press the SPACE bar to fire bullets at the enemies.

4. Objective

Shoot down as many enemy spaceships as possible while avoiding their bullets.

Space Invader Game 3

5. Game Over

The game ends if an enemy bullet hits your spaceship or an enemy reaches the bottom of the screen.

Note

Make sure to download the images for the enemy spaceships and background, otherwise, the game won't run properly.

Final Game

Space Invader Game Using Pygame

Implementation of Space Invader Game Using Pygame

1. Required Libraries

To implement this game, you need to install the following libraries −

  • math − It is used for calculating distances to detect collisions between bullets and enemies
  • random − It is used for generating random enemy positions and bullet firing times.
  • pygame − It is used for calculating distances to detect collisions between bullets and enemies.

2. Game Initialization

Set off Pygame and Setup the Display

This part initializes the Pygame library and sets up the game window's width and height. The background music and images for the game are also loaded.

Player Set off

The player's spaceship is loaded, and the initial position and movement variables are set.

Enemy Set off

Enemies are initialized with their respective positions, velocities, and movement changes.

Start Menu

Displays the start menu with a title and prompt for the player to start the game.

3. Main Game Loop

The main loop where events are processed, and player and enemy movements are updated. It also handles collision checks, bullet movements, and updating the game display.

Code to Implement Space Invader Game Using Pygame

Here is the complete code to implement the game −

import math
import random
import pygame
from pygame import mixer

# Initialize pygame
pygame.init()

# Screen dimensions
display_width, display_height = 800, 600
display = pygame.display.set_mode((display_width, display_height))

# Background image
space_bg = pygame.image.load(r"C:\Users\souvi\OneDrive\Desktop\koko\Space-Invaders-Pygame\space_background.png")
# Background music
mixer.music.load(r"C:\Users\souvi\OneDrive\Desktop\koko\Space-Invaders-Pygame\space_music.wav")
mixer.music.play(-1)

# Title and Icon
pygame.display.set_caption("Space Guardian")
game_icon = pygame.image.load(r"C:\Users\souvi\OneDrive\Desktop\koko\Space-Invaders-Pygame\alien_ship.png")
pygame.display.set_icon(game_icon)

# Fonts
text_font = pygame.font.Font('freesansbold.ttf', 32)
header_font = pygame.font.Font('freesansbold.ttf', 64)

# Player spaceship
hero_image = pygame.image.load(r"C:\Users\souvi\OneDrive\Desktop\koko\Space-Invaders-Pygame\spaceship_hero.png")
hero_x = 370
hero_y = 500
hero_x_change = 0
hero_y_change = 0

# Enemy ships
enemy_sprites = []
enemy_x_pos = []
enemy_y_pos = []
enemy_x_change = []
enemy_y_change = []
number_of_enemies = 5
base_enemy_velocity = 0.4

i = 0
while i < number_of_enemies:
   enemy_sprites.append(pygame.image.load(r"C:\Users\souvi\OneDrive\Desktop\koko\Space-Invaders-Pygame\alien_enemy.png"))
   enemy_x_pos.append(random.randint(0, 736))
   enemy_y_pos.append(random.randint(50, 150))
   enemy_x_change.append(base_enemy_velocity)
   enemy_y_change.append(20)
   i += 1

# Player bullets
bullet_sprite = pygame.image.load(r"C:\Users\souvi\OneDrive\Desktop\koko\Space-Invaders-Pygame\laser_bullet.png")
bullet_x = 0
bullet_y = 500
bullet_x_change = 0
bullet_y_change = 10
bullet_state = "ready"

# Enemy bullets
enemy_bullet_sprite = []
enemy_bullet_x = []
enemy_bullet_y = []
enemy_bullet_y_change = []
enemy_bullet_state = []
j = 0
while j < number_of_enemies:
   enemy_bullet_sprite.append(pygame.image.load(r"C:\Users\souvi\OneDrive\Desktop\koko\Space-Invaders-Pygame\laser_bullet.png"))
   enemy_bullet_x.append(0)
   enemy_bullet_y.append(enemy_y_pos[j])
   enemy_bullet_y_change.append(2)
   enemy_bullet_state.append("ready")
   j += 1

# Score and level
score = 0
game_level = 1
text_x = 10
text_y = 10

# Game Over font
game_over_font = pygame.font.Font('freesansbold.ttf', 64)

# Start Menu
def start_menu():
   display.fill((0, 0, 0))
   title_text = header_font.render("Space Guardian", True, (255, 255, 255))
   display.blit(title_text, (200, 200))

   instructions = text_font.render("Press ENTER to Start", True, (255, 255, 255))
   display.blit(instructions, (250, 300))

   pygame.display.update()
   start = False
   while not start:
      for event in pygame.event.get():
         if event.type == pygame.QUIT:
            pygame.quit()
            quit()
         if event.type == pygame.KEYDOWN and event.key == pygame.K_RETURN:
            start = True

# Display score
def display_score(x, y):
   score_text = text_font.render("Score: " + str(score), True, (255, 255, 255))
   display.blit(score_text, (x, y))

# Display level
def display_level(x, y):
   level_text = text_font.render("Level: " + str(game_level), True, (255, 255, 255))
   display.blit(level_text, (x, y + 40))

# Game Over text
def game_over():
   over_text = game_over_font.render("GAME OVER", True, (255, 255, 255))
   display.blit(over_text, (200, 250))

# Player sprite
def player(x, y):
   display.blit(hero_image, (x, y))

# Enemy sprite
def enemy(x, y, index):
   display.blit(enemy_sprites[index], (x, y))

# Fire player bullet
def fire_hero_bullet(x, y):
   global bullet_state
   bullet_state = "fire"
   display.blit(bullet_sprite, (x + 16, y + 10))

# Fire enemy bullet
def fire_enemy_bullet(x, y, index):
   global enemy_bullet_state
   enemy_bullet_state[index] = "fire"
   display.blit(enemy_bullet_sprite[index], (x + 16, y + 10))

# Collision detection (player bullet with enemy)
def collision_detected(enemy_x, enemy_y, bullet_x, bullet_y):
   distance = math.sqrt(math.pow(enemy_x - bullet_x, 2) + (math.pow(enemy_y - bullet_y, 2)))
   return distance < 27

# Collision detection (enemy bullet with player)
def player_hit(player_x, player_y, bullet_x, bullet_y):
   distance = math.sqrt(math.pow(player_x - bullet_x, 2) + (math.pow(player_y - bullet_y, 2)))
   return distance < 30

def game_loop():
   global bullet_x, bullet_y, bullet_state, score, game_level
   global hero_x, hero_y, hero_x_change, hero_y_change
   global enemy_x_pos, enemy_y_pos, enemy_x_change, enemy_y_change
   global enemy_bullet_x, enemy_bullet_y, enemy_bullet_state, enemy_bullet_y_change

   try:
      # Initialize variables
      hero_x = 368  # Example starting position
      hero_y = 480  # Example starting position
      hero_x_change = 0
      hero_y_change = 0
      bullet_x = 0
      bullet_y = 500
      bullet_state = "ready"
      score = 0
      game_level = 1

      # Example initialization for enemies and their bullets
      number_of_enemies = 5
      enemy_x_pos = [random.randint(0, 736) for _ in range(number_of_enemies)]
      enemy_y_pos = [random.randint(50, 150) for _ in range(number_of_enemies)]
      enemy_x_change = [base_enemy_velocity for _ in range(number_of_enemies)]
      enemy_y_change = [40 for _ in range(number_of_enemies)]
      enemy_bullet_x = [0 for _ in range(number_of_enemies)]
      enemy_bullet_y = [0 for _ in range(number_of_enemies)]
      enemy_bullet_state = ["ready" for _ in range(number_of_enemies)]
      enemy_bullet_y_change = [10 for _ in range(number_of_enemies)]

      running = True

      start_menu()  # Call start menu

      while running:
         display.fill((0, 0, 0))
         display.blit(space_bg, (0, 0))

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

         # Key press detection
         if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_a or event.key == pygame.K_LEFT:
               hero_x_change = -5
            if event.key == pygame.K_d or event.key == pygame.K_RIGHT:
               hero_x_change = 5
            if event.key == pygame.K_w or event.key == pygame.K_UP:
               hero_y_change = -5
            if event.key == pygame.K_s or event.key == pygame.K_DOWN:
               hero_y_change = 5
            if event.key == pygame.K_SPACE and bullet_state == "ready":
               bullet_sound = mixer.Sound(r"C:\Users\souvi\OneDrive\Desktop\koko\Space-Invaders-Pygame\laser_sound.wav")
               bullet_sound.play()
               bullet_x = hero_x
               bullet_y = hero_y  # Initialize bullet_y when firing
               bullet_state = "fire"

         # Key release detection
         if event.type == pygame.KEYUP:
            if event.key == pygame.K_a or event.key == pygame.K_d:
               hero_x_change = 0
            if event.key == pygame.K_w or event.key == pygame.K_s:
               hero_y_change = 0

         # Move player
         hero_x += hero_x_change
         hero_y += hero_y_change

         # Boundary for player
         if hero_x <= 0:
            hero_x = 0
         elif hero_x >= 736:
            hero_x = 736

         if hero_y <= 0:
            hero_y = 0
         elif hero_y >= 536:
            hero_y = 536

         # Enemy movement and collision logic
         e = 0
         while e < number_of_enemies:
            if enemy_y_pos[e] > 440 or player_hit(hero_x, hero_y, enemy_bullet_x[e], enemy_bullet_y[e]):
               for j in range(number_of_enemies):
                  enemy_y_pos[j] = 2000
               game_over()
               break

            enemy_x_pos[e] += enemy_x_change[e]
               if enemy_x_pos[e] <= 0:
                  enemy_x_change[e] = base_enemy_velocity + (game_level - 1) / 4
                  enemy_y_pos[e] += enemy_y_change[e]
               elif enemy_x_pos[e] >= 736:
                  enemy_x_change[e] = -(base_enemy_velocity + (game_level - 1) / 4)
                  enemy_y_pos[e] += enemy_y_change[e]

         # Enemy bullet firing
         if enemy_bullet_state[e] == "ready" and random.random() < 0.008:
            enemy_bullet_x[e] = enemy_x_pos[e]
            fire_enemy_bullet(enemy_bullet_x[e], enemy_bullet_y[e], e)

         if enemy_bullet_state[e] == "fire":
            fire_enemy_bullet(enemy_bullet_x[e], enemy_bullet_y[e], e)
            enemy_bullet_y[e] += enemy_bullet_y_change[e]

         if enemy_bullet_y[e] >= 600:
            enemy_bullet_y[e] = enemy_y_pos[e]
            enemy_bullet_state[e] = "ready"

         # Check for collisions
         if bullet_state == "fire":
            collision = collision_detected(enemy_x_pos[e], enemy_y_pos[e], bullet_x, bullet_y)
            if collision:
               explosion_sound = mixer.Sound(r"C:\Users\souvi\OneDrive\Desktop\koko\Space-Invaders-Pygame\explosion.wav")
               explosion_sound.play()
               bullet_y = 500
               bullet_state = "ready"
               score += 1
               enemy_x_pos[e] = random.randint(0, 736)
               enemy_y_pos[e] = random.randint(50, 150)

            enemy(enemy_x_pos[e], enemy_y_pos[e], e)
               e += 1

         # Bullet movement
         if bullet_state == "fire":
            fire_hero_bullet(bullet_x, bullet_y)
            bullet_y -= bullet_y_change

            if bullet_y <= 0:
               bullet_y = 500
               bullet_state = "ready"

         # Update score and level
         display_score(text_x, text_y)
         display_level(text_x, text_y)

         # Display player
         player(hero_x, hero_y)

         # Update the screen
         pygame.display.update()

      except Exception as e:
         print(f"An error occurred: {e}")

   finally:
      pygame.quit()

# Call game_loop() in a try-except block
if __name__ == "__main__":
   game_loop()

Code Breakdown

Import Required Libraries: These are the necessary libraries required for game functions, which include mathematics, random number generation, pygame and pygame.mixer for game music.

  • Initialize pygame − The init() function in pygame calls and initializes many modules, which are necessary to run the game.
  • Set Screen Dimensions − Variable display_width is defined for the game screen width, and display_height for the game screen’s height.
  • Create Game Window − The graphics on the screen display are developed with display.set_mode().
  • Load Background Image − The background image is loaded into the game using image module in image.load().
  • Proceed to load and play the background music − Pre-recorded music is preset and replayed on a mixer with a certain music.load() and mixer.music.play().
  • Set Title and Icon − The pygame is used for setting the game title and window icon of the display.set_caption() and pygame. display.set_icon().
  • Load Fonts − Score font, game over message font, and the title screen font are all resources that are loaded with font.Font().
  • Load Player Image − The spaceship image of the player is loaded and initial x and y coordinates of the spaceship are set.
  • Load Enemy Ships − Several targeted ships are created and placed randomly on the battlefield. The player, one has to load up the bullet image. The bullet image for the spaceship, which has to be seen by the player is also loaded.
  • Load enemy bullets Images of bullets fired by the enemy ships are created for each such ship.
  • Set the score and the level placeholders − The score of the player, as well as the current level of the game are the variables that have to be defined.
  • Game Over Font − The font for the message saying ‘game over’ is also created.
  • Define Start Menu − The first menu creates the title of the game and how to play it is shown.
  • Define Score Display − In order to use it, a function is defined in a special way to show player’s score on the screen.
  • Define Level Display − A function is used to post the game level on the screen where players can see it.
  • Define Game Over Function − Another function is developed in order to show the message where the game is over and the player has lost the game.
  • Define Player Function − The player’s spaceship is presented with the help of a function.
  • Define Enemy Function − The resources depict the enemy ships by coordinate on the screen.
  • Fire Player Bullet Function − A function is developed for handling the shooting of bullets for the player’s spaceship.
  • Fire Enemy Bullet Function − In the same way, a similar function is defined for the enemy ships, the hits which are used to shoot bullets.
  • Using collision detection for Player Bullet − A function determines whether a player’s bullet will hit an enemy by calculating distance.
  • Collision Resolution for the Enemy Bullets − Another function that checks whether the enemy bullet hits the player’s spaceship does exist.
  • Define Game Loop − All the game logic is placed into a loop; it means that the game is constantly running until they decide to stop the game.
  • Handle Player Movement − The important occurrences are supervised to manage navigational motion of the spaceship owned by the player.
  • Player Boundaries − To be precise, player mobility is limited to the area defined by the screen, either horizontally or vertically, and can either be free moving or a side-scroller.
  • Handle Enemy Movement − targets are neutral and shift horizontally and vertically and descend after impacting the side of the screen.
  • Enemy Bullet Movement − Enemy bullets are shot randomly off and are drawn moving down towards the player.
  • Update Display − It is possible to update the screen with pygame at any time in constant progression. The display.update() to all the changes that occur in the game loop.
python_reference.htm
Advertisements