Build an Alien Invasion Game with Pygame: Complete Code Walkthrough
This article walks through the complete implementation of an Alien Invasion game using Python's Pygame library, explaining the modular structure, key classes, functions, and game mechanics while providing full source code for each component.
The article demonstrates how to build a simple "Alien Invasion" shooting game with Python and Pygame, emphasizing modular design, object‑oriented programming, and reusable functions.
Main entry (alien_invasion.py)
"""该游戏主程序,尽量做到最简单"""
import pygame
from settings import Settings
from ship import Ship
from pygame.sprite import Group
from game_stats import GameStats
from button import Button
from score_board import Scoreboard
import game_function as gf
def run_game():
"""初始化背景设置"""
pygame.init()
ai_settings = Settings()
screen = pygame.display.set_mode((ai_settings.screen_width, ai_settings.screen_height))
pygame.display.set_caption('Alien Invasion')
ship = Ship(ai_settings, screen)
bullets = Group()
aliens = Group()
gf.creat_fleet(ai_settings, screen, ship, aliens)
stats = GameStats(ai_settings)
sb = Scoreboard(ai_settings, screen, stats)
play_button = Button(ai_settings, screen, "Play")
while True:
gf.check_events(ai_settings, screen, ship, aliens, bullets, stats, play_button, sb)
if stats.game_active:
ship.update()
gf.update_bullet(ai_settings, screen, ship, aliens, bullets, stats, sb)
gf.update_aliens(ai_settings, screen, ship, aliens, stats, bullets, sb)
gf.update_screen(ai_settings, screen, ship, aliens, bullets, stats, play_button, sb)
run_game()Game logic (game_function.py)
This module contains the core functions that handle events, update game objects, and render the screen.
import sys
import pygame
from random import randint
from bullet import Bullet
from alien import Alien
from time import sleep
def fire_bullet(ai_settings, screen, ship, bullets, stats):
"""Create a new bullet if limit not reached"""
for i in range(int(stats.level / 5) + 1):
if len(bullets) < ai_settings.bullet_allowed:
new_bullet = Bullet(ai_settings, screen, ship)
bullets.add(new_bullet)
def check_keydown(event, ai_settings, screen, ship, bullets, stats):
"""Respond to keypresses"""
if event.key == pygame.K_RIGHT:
ship.moving_right = True
elif event.key == pygame.K_LEFT:
ship.moving_left = True
elif event.key == pygame.K_UP:
ship.moving_up = True
elif event.key == pygame.K_DOWN:
ship.moving_down = True
elif event.key == pygame.K_SPACE:
fire_bullet(ai_settings, screen, ship, bullets, stats)
def check_keyup(event, ship):
"""Respond to key releases"""
if event.key == pygame.K_RIGHT:
ship.moving_right = False
elif event.key == pygame.K_LEFT:
ship.moving_left = False
elif event.key == pygame.K_UP:
ship.moving_up = False
elif event.key == pygame.K_DOWN:
ship.moving_down = False
def check_events(ai_settings, screen, ship, aliens, bullets, stats, play_button, sb):
"""Handle keyboard and mouse events"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
elif event.type == pygame.KEYDOWN:
check_keydown(event, ai_settings, screen, ship, bullets, stats)
elif event.type == pygame.KEYUP:
check_keyup(event, ship)
elif event.type == pygame.MOUSEBUTTONDOWN:
mouse_x, mouse_y = pygame.mouse.get_pos()
check_play_button(ai_settings, screen, ship, aliens, bullets, stats, play_button, mouse_x, mouse_y, sb)
def check_play_button(ai_settings, screen, ship, aliens, bullets, stats, play_button, mouse_x, mouse_y, sb):
"""Start a new game when Play is clicked"""
if play_button.rect.collidepoint(mouse_x, mouse_y) and not stats.game_active:
ai_settings.init_dynamic_settings()
pygame.mouse.set_visible(False)
stats.reset_stats()
stats.game_active = True
sb.prep_score()
sb.prep_high_score(screen)
sb.prep_level()
sb.prep_ships(screen)
aliens.empty()
bullets.empty()
creat_fleet(ai_settings, screen, ship, aliens)
ship.center_ship(ai_settings)
def update_screen(ai_settings, screen, ship, aliens, bullets, stats, play_button, sb):
"""Redraw the screen each frame"""
screen.fill(ai_settings.bg_color)
for bullet in bullets.sprites():
bullet.draw_bullet()
ship.blitme()
aliens.draw(screen)
sb.show_score()
if not stats.game_active:
play_button.draw_button()
pygame.display.flip()Settings (settings.py)
Defines all configurable parameters such as screen size, colors, ship limits, bullet properties, alien speed, and scaling factors.
class Settings():
def __init__(self):
self.screen_width = 800
self.screen_height = 700
self.bg_color = (255, 255, 255)
self.ship_limit = 2
# Bullet settings
self.bullet_width = 3
self.bullet_height = 15
self.bullet_color = (60, 60, 60)
self.bullet_allowed = 8
# Alien movement
self.fleet_drop_speed = 10
self.speed_up_scale = 1.1
self.init_dynamic_settings()
self.score_scale = 1.5
self.bullet_scale = 10
def init_dynamic_settings(self):
self.speed = 1.5
self.bullet_speed = 3
self.alien_speed = 0.2
self.fleet_direction = -1
self.alien_points = 10
def increase_speed(self):
self.speed *= self.speed_up_scale
self.bullet_speed *= self.speed_up_scale
self.alien_speed *= self.speed_up_scale
self.alien_points = int(self.alien_points * self.score_scale)
def increase_bullet_size(self):
self.bullet_width += self.bullet_scaleShip class (ship.py)
Represents the player’s spaceship, handles movement flags, and draws the ship on the screen.
import pygame
from pygame.sprite import Sprite
class Ship(Sprite):
def __init__(self, ai_settings, screen):
super(Ship, self).__init__()
self.screen = screen
self.image = pygame.image.load('images/ship.bmp')
self.rect = self.image.get_rect()
self.screen_rect = screen.get_rect()
self.ai_settings = ai_settings
self.rect.centerx = self.screen_rect.centerx
self.rect.bottom = self.screen_rect.bottom
self.center_x = float(self.rect.centerx)
self.center_y = float(self.rect.centery)
self.moving_right = False
self.moving_left = False
self.moving_up = False
self.moving_down = False
def update(self):
if self.moving_right and self.rect.right < self.screen_rect.right:
self.center_x += self.ai_settings.speed
if self.moving_left and self.rect.left > 0:
self.center_x -= self.ai_settings.speed
if self.moving_up and self.rect.top > 0:
self.center_y -= self.ai_settings.speed
if self.moving_down and self.rect.bottom < self.screen_rect.bottom:
self.center_y += self.ai_settings.speed
self.rect.centerx = self.center_x
self.rect.centery = self.center_y
def blitme(self):
self.screen.blit(self.image, self.rect)
def center_ship(self, ai_settings):
self.center_x = ai_settings.screen_width / 2
self.center_y = ai_settings.screen_height - 28Alien class (alien.py)
Defines the enemy alien sprite, its movement, and edge‑detection logic.
import pygame
from pygame.sprite import Sprite
class Alien(Sprite):
def __init__(self, ai_settings, screen):
super().__init__()
self.screen = screen
self.ai_settings = ai_settings
self.image = pygame.image.load('images/alien.bmp')
self.rect = self.image.get_rect()
self.rect.x = self.rect.width
self.rect.y = self.rect.height
self.x = float(self.rect.x)
def check_edges(self):
screen_rect = self.screen.get_rect()
if self.rect.right >= screen_rect.right or self.rect.left <= 0:
return True
def update(self):
self.x += self.ai_settings.alien_speed * self.ai_settings.fleet_direction
self.rect.x = self.x
def blitme(self):
self.screen.blit(self.image, self.rect)Bullet class (bullet.py)
Handles bullet creation, movement, and drawing.
import pygame
from pygame.sprite import Sprite
class Bullet(Sprite):
def __init__(self, ai_settings, screen, ship):
super(Bullet, self).__init__()
self.screen = screen
self.rect = pygame.Rect(0, 0, ai_settings.bullet_width, ai_settings.bullet_height)
self.rect.centerx = ship.rect.centerx
self.rect.top = ship.rect.top
self.y = float(self.rect.y)
self.color = ai_settings.bullet_color
self.speed = ai_settings.bullet_speed
def update(self):
self.y -= self.speed
self.rect.y = self.y
def draw_bullet(self):
pygame.draw.rect(self.screen, self.color, self.rect)Button class (button.py)
Creates a simple rectangular button with a label, used for the "Play" button.
import pygame.font
class Button():
def __init__(self, ai_settings, screen, msg):
self.screen = screen
self.screen_rect = screen.get_rect()
self.width, self.height = 200, 50
self.button_color = (0, 255, 0)
self.text_color = (60, 60, 60)
self.font = pygame.font.SysFont(None, 48)
self.rect = pygame.Rect(0, 0, self.width, self.height)
self.rect.center = self.screen_rect.center
self.prep_msg(msg)
def prep_msg(self, msg):
self.msg_image = self.font.render(msg, True, self.text_color, self.button_color)
self.msg_image_rect = self.msg_image.get_rect()
self.msg_image_rect.center = self.rect.center
def draw_button(self):
self.screen.fill(self.button_color, self.rect)
self.screen.blit(self.msg_image, self.msg_image_rect)Game statistics (game_stats.py)
Tracks mutable game data such as score, level, remaining ships, and game state.
class GameStats():
"""Track statistics for the game"""
def __init__(self, ai_settings):
self.ai_settings = ai_settings
self.game_active = False
self.high_score = 0
self.reset_stats()
def reset_stats(self):
self.ship_left = self.ai_settings.ship_limit
self.score = 0
self.level = 1
self.bullet_width = 3Scoreboard (score_board.py)
Renders the current score, high score, level, and remaining ships on the screen.
import pygame.font
from pygame.sprite import Group
from ship import Ship
class Scoreboard():
def __init__(self, ai_settings, screen, stats):
self.screen = screen
self.screen_rect = screen.get_rect()
self.ai_settings = ai_settings
self.stats = stats
self.text_color = (30, 30, 30)
self.font = pygame.font.SysFont(None, 48)
self.prep_score()
self.prep_high_score(screen)
self.prep_level()
self.prep_ships(screen)
def prep_score(self):
rounded_score = int(round(self.stats.score, -1))
score_str = "Score:" + "{:,}".format(rounded_score)
self.score_image = self.font.render(score_str, True, self.text_color, self.ai_settings.bg_color)
self.score_rect = self.score_image.get_rect()
self.score_rect.right = self.screen_rect.right - 20
self.score_rect.top = 20
def prep_high_score(self, screen):
high_score = int(round(self.stats.high_score, -1))
high_score_str = "High Score:" + "{:,}".format(high_score)
self.high_score_image = self.font.render(high_score_str, True, self.text_color, self.ai_settings.bg_color)
self.high_score_rect = self.high_score_image.get_rect()
self.high_score_rect.left = self.screen_rect.left + 20
self.high_score_rect.top = 20
def prep_level(self):
self.level_image = self.font.render("Level:" + str(self.stats.level), True, self.text_color, self.ai_settings.bg_color)
self.level_rect = self.level_image.get_rect()
self.level_rect.right = self.score_rect.right
self.level_rect.bottom = self.score_rect.bottom + 650
def show_score(self):
self.screen.blit(self.score_image, self.score_rect)
self.screen.blit(self.high_score_image, self.high_score_rect)
self.screen.blit(self.level_image, self.level_rect)
self.ships.draw(self.screen)
def prep_ships(self, screen):
self.ships = Group()
for ship_number in range(self.stats.ship_left + 1):
ship = Ship(self.ai_settings, self.screen)
ship.rect.x = 10 + ship_number * ship.rect.width
ship.rect.y = self.screen_rect.top + 640
self.ships.add(ship)The author notes that the project is still a work in progress but highlights the learning outcomes: modular thinking, class usage, and extensive function decomposition, which have already begun influencing other subjects and daily life.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
MaGe Linux Operations
Founded in 2009, MaGe Education is a top Chinese high‑end IT training brand. Its graduates earn 12K+ RMB salaries, and the school has trained tens of thousands of students. It offers high‑pay courses in Linux cloud operations, Python full‑stack, automation, data analysis, AI, and Go high‑concurrency architecture. Thanks to quality courses and a solid reputation, it has talent partnerships with numerous internet firms.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
