In the world of game development, Python, when paired with PyGame, offers a platform that is both approachable for beginners and sufficiently robust for experienced developers.

This article takes you into the creation of a Space Shooter game, a genre loved for its simplicity and excitement.

The game comprises of several core components: the player's spaceship, enemy ships, and projectiles, each designed and integrated to create an engaging gameplay experience.

Here is the game in action:

0:00
/0:11

Check out the YouTube video, if you prefer to follow along in a video format:


Game Architecture

The Space Shooter game is structured into several modular Python files, each responsible for a distinct aspect of the game:

Game.py: The heart of our game, this file orchestrates the game loop, event handling, and the rendering process. It initializes the PyGame library, sets up the game window, and integrates other components to create a fluid gameplay experience.

Player.py: This file defines the Player class, encapsulating the player's spaceship. It includes functionalities for moving the spaceship, rendering its visual representation (Player.png), and shooting projectiles.

Enemy.py: Similar to the Player class, the Enemy class defined in this file manages the behavior of enemy ships. It handles their movement patterns, interaction with projectiles, and rendering of Enemy.png.

Projectile.py: Projectiles are crucial for the game's firing mechanics. This file contains the Projectile class, which manages the creation, movement, and rendering of projectiles (Projectile.png) shot by the player.

The Visual Elements

The game's visual appeal is delivered from the PNG files:

Player.png

The Player.png file offers distinct visual identities to the player's spaceship making it easily recognizable during gameplay.

Enemy.png

The Enemy.png file offers distinct visual identities to the enemy ships making them easily recognizable during gameplay.

Projectile.png

Projectile.png provides a visual for the bullets fired by the player, enhancing the game's immersive experience.


Excited to dive deeper into the world of Python programming? Look no further than my latest ebook, "Python Tricks - A Collection of Tips and Techniques".

Get the eBook

Inside, you'll discover a plethora of Python secrets that will guide you through a journey of learning how to write cleaner, faster, and more Pythonic code. Whether it's mastering data structures, understanding the nuances of object-oriented programming, or uncovering Python's hidden features, this ebook has something for everyone.

Developing the Game Components

With the design of the game architecture and main components explained, let's now implement the different files and logic.

Player.py: Steering the Spaceship

The Player.py script introduces the Player class, a fundamental component that controls the player's spaceship:

import pygame
from Projectile import Projectile


# Create classes for the player's spaceship
class Player(pygame.sprite.Sprite):
    def __init__(self, speed, screen_width, screen_height):
        super().__init__()
        # Load the image for the player's spaceship
        self.image = pygame.image.load("Player.png").convert_alpha()
        # Set the initial position and size of the spaceship
        self.rect = self.image.get_rect(center=(screen_width/2, screen_height-64))
        # Set the speed of the spaceship
        self.speed = speed
        # Set up shooting variables
        self.shoot_delay = 500  # Shooting delay in milliseconds
        self.last_shot = pygame.time.get_ticks()
        # Set up the player's score
        self.score = 0

    def update(self, player_projectiles):
        # Get the current keyboard state
        keys = pygame.key.get_pressed()
        # Move the spaceship based on the keyboard state
        if keys[pygame.K_LEFT] or keys[pygame.K_a]:
            self.rect.x -= self.speed
        if keys[pygame.K_RIGHT] or keys[pygame.K_d]:
            self.rect.x += self.speed
        # Shoot projectiles when the space key is pressed
        if keys[pygame.K_SPACE]:
            self.shoot(player_projectiles)
        # Keep the spaceship within the screen boundaries
        self.rect.clamp_ip(pygame.display.get_surface().get_rect())

    def shoot(self, player_projectiles):
        # Check if enough time has passed since the last shot
        current_time = pygame.time.get_ticks()
        if current_time - self.last_shot >= self.shoot_delay:
            # Create a new projectile and add it to the projectile group
            projectile = Projectile(5, self.rect.centerx, self.rect.top)
            player_projectiles.add(projectile)
            # Update the last shot time
            self.last_shot = current_time
        return player_projectiles

Here's a breakdown of its key components and functionalities:

Player Class: Inherits from pygame.sprite.Sprite, making it a subclass that can use all the sprite functionalities provided by PyGame, such as rendering images and detecting collisions.

__init__ Method: The constructor initializes the player's spaceship with several attributes:

  • Image Loading: Loads the spaceship's image from Player.png and sets it to use alpha transparency for better visual quality.
  • Positioning: The spaceship's starting position is centered horizontally (screen_width/2) and placed near the bottom (screen_height-64) of the game screen.
  • Speed and Shooting Delay: Sets the player's speed and a delay between shots (500 milliseconds) to prevent continuous firing.
  • Score Tracking: Initializes a score attribute to track the player's score.

update Method: This method updates the player's position based on keyboard inputs (left, right, and space for shooting). It ensures the player's spaceship stays within the screen boundaries.

shoot Method: Handles the shooting mechanism. It checks if the time elapsed since the last shot is greater than the shooting delay before creating a new Projectile object at the player's current position and adding it to the player_projectiles group for management and rendering. This prevents the player from shooting continuously without any delay.

The Player class is designed to encapsulate all the functionalities necessary for controlling the player's spaceship, including moving it across the screen and shooting projectiles.

Enemy.py: The Space Adversaries

The Enemy.py file hosts the Enemy class, responsible for defining the attributes and behaviors of enemy spaceships that the player must confront:

import random
import pygame


# Create classes for the enemy's spaceship
class Enemy(pygame.sprite.Sprite):
    def __init__(self, speed, screen_width, screen_height):
        super().__init__()
        # Load the enemy image
        self.image = pygame.image.load("Enemy.png").convert_alpha()
        # Set the initial position and size of the enemy
        self.rect = self.image.get_rect(center=(random.randint(64, screen_width-64), random.randint(32, 132)))
        # Set the speed of the enemy
        self.speed = speed
        # Set height
        self.screen_height = screen_height
        # Set up the timer for updating the enemy's position
        self.last_update_time = pygame.time.get_ticks()
        self.update_interval = 500  # 500ms

    def update(self):
        # Get the current time
        current_time = pygame.time.get_ticks()
        # Check if enough time has passed since the last position update
        if current_time - self.last_update_time >= self.update_interval:
            # Update the enemy's position
            self.rect.y += self.speed
            # Reset the timer for the next position update
            self.last_update_time = current_time
        # Remove the enemy if it goes off-screen
        if self.rect.bottom > self.screen_height:
            self.kill()

Let's dissect its components and functionalities:

Enemy Class: Inherits from pygame.sprite.Sprite, enabling it to use sprite-related features offered by PyGame, such as image handling and collision detection.

__init__ Method: The constructor initializes the enemy ship with several key attributes:

  • Image Loading: Loads the enemy ship's image from Enemy.png and enables alpha transparency for improved visual effects.
  • Positioning: Sets the enemy's starting position at a random location near the top of the screen. The random.randint function ensures that each enemy appears at a different horizontal position within the playable area.
  • Speed: Determines how quickly the enemy moves down the screen.
  • Movement Timing: Uses pygame.time.get_ticks() to manage the timing of the enemy's movement, along with an update_interval that defines how often (in milliseconds) the enemy's position is updated.

update Method: This method is called to update the enemy's position:

  • It checks if the current time minus the last update time is greater than the update interval. If so, the enemy moves downward by increasing its y-coordinate by the speed amount, and the last_update_time is updated to the current time.
  • If the enemy moves off the bottom of the screen (self.rect.bottom > self.screen_height), it is removed from the game using the kill method. This prevents enemies from continuing to consume resources once they are no longer visible or interactable.

The Enemy class encapsulates the functionality needed for enemy ships in the game, including their appearance, randomized starting positions, and downward movement.

Projectile.py: Managing Firepower

The Projectile.py file contains the Projectile class, which is crucial for the game's firing mechanics, allowing the player to shoot projectiles:

Tagged in: