alien.py
import pygame from settings import BULLET_SIZE from bullet import Bullet class Alien(pygame.sprite.Sprite): def __init__(self, pos, size, row_num): super().__init__() self.x = pos[0] self.y = pos[1] # alien info img_path = f'assets/aliens/{row_num}.png' self.image = pygame.image.load(img_path) self.image = pygame.transform.scale(self.image, (size, size)) self.rect = self.image.get_rect(topleft = pos) self.mask = pygame.mask.from_surface(self.image) self.move_speed = 5 self.to_direction = "right" # alien status self.bullets = pygame.sprite.GroupSingle() def move_left(self): self.rect.x -= self.move_speed def move_right(self): self.rect.x += self.move_speed def move_bottom(self): self.rect.y += self.move_speed def _shoot(self): specific_pos = (self.rect.centerx - (BULLET_SIZE // 2), self.rect.centery) self.bullets.add(Bullet(specific_pos, BULLET_SIZE, "enemy")) def update(self): self.rect = self.image.get_rect(topleft=(self.rect.x, self.rect.y))bullet.py
import pygame from settings import BULLET_SPEED, HEIGHT class Bullet(pygame.sprite.Sprite): def __init__(self, pos, size, side): super().__init__() self.x = pos[0] self.y = pos[1] # bullet info img_path = f'assets/bullet/{side}-bullet.png' self.image = pygame.image.load(img_path) self.image = pygame.transform.scale(self.image, (size, size)) self.rect = self.image.get_rect(topleft = pos) self.mask = pygame.mask.from_surface(self.image) # different bullet movement direction for both player and enemy (alien) if side == "enemy": self.move_speed = BULLET_SPEED elif side == "player": self.move_speed = (- BULLET_SPEED) def _move_bullet(self): self.rect.y += self.move_speed def update(self): self._move_bullet() self.rect = self.image.get_rect(topleft=(self.rect.x, self.rect.y)) # delete the bullet if it get through out of the screen if self.rect.bottom <= 0 or self.rect.top >= HEIGHT: self.kill()display.py
import pygame from settings import WIDTH, HEIGHT, SPACE, FONT_SIZE, EVENT_FONT_SIZE pygame.font.init() class Display: def __init__(self, screen): self.screen = screen self.score_font = pygame.font.SysFont("monospace", FONT_SIZE) self.level_font = pygame.font.SysFont("impact", FONT_SIZE) self.event_font = pygame.font.SysFont("impact", EVENT_FONT_SIZE) self.text_color = pygame.Color("blue") self.event_color = pygame.Color("red") def show_life(self, life): life_size = 30 img_path = "assets/life/life.png" life_image = pygame.image.load(img_path) life_image = pygame.transform.scale(life_image, (life_size, life_size)) life_x = SPACE // 2 if life != 0: for life in range(life): self.screen.blit(life_image, (life_x, HEIGHT + (SPACE // 2))) life_x += life_size def show_score(self, score): score_x = WIDTH // 3 score = self.score_font.render(f'score: {score}', True, self.text_color) self.screen.blit(score, (score_x, (HEIGHT + (SPACE // 2)))) def show_level(self, level): level_x = WIDTH // 3 level = self.level_font.render(f'Level {level}', True, self.text_color) self.screen.blit(level, (level_x * 2, (HEIGHT + (SPACE // 2)))) def game_over_message(self): message = self.event_font.render('GAME OVER!!', True, self.event_color) self.screen.blit(message, ((WIDTH // 3) - (EVENT_FONT_SIZE // 2), (HEIGHT // 2) - (EVENT_FONT_SIZE // 2)))main.py
import pygame, sys from settings import WIDTH, HEIGHT, NAV_THICKNESS from world import World pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT + NAV_THICKNESS)) pygame.display.set_caption("Space Invader") class Main: def __init__(self, screen): self.screen = screen self.FPS = pygame.time.Clock() def main(self): world = World(self.screen) while True: self.screen.fill("black") for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() sys.exit() if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE: world.player_move(attack = True) world.player_move() world.update() pygame.display.update() self.FPS.tick(30) if __name__ == "__main__": play = Main(screen) play.main()settings.py
WIDTH, HEIGHT = 720, 450 SPACE = 30 FONT_SIZE = 20 EVENT_FONT_SIZE = 60 NAV_THICKNESS = 50 CHARACTER_SIZE = 30 PLAYER_SPEED = 10 ENEMY_SPEED = 1 BULLET_SPEED = 15 # for both sides BULLET_SIZE = 10ship.py
import pygame from settings import PLAYER_SPEED, BULLET_SIZE from bullet import Bullet class Ship(pygame.sprite.Sprite): def __init__(self, pos, size): super().__init__() self.x = pos[0] self.y = pos[1] # ship info img_path = 'assets/ship/ship.png' self.image = pygame.image.load(img_path) self.image = pygame.transform.scale(self.image, (size, size)) self.rect = self.image.get_rect(topleft = pos) self.mask = pygame.mask.from_surface(self.image) self.ship_speed = PLAYER_SPEED # ship status self.life = 3 self.player_bullets = pygame.sprite.Group() def move_left(self): self.rect.x -= self.ship_speed def move_up(self): self.rect.y -= self.ship_speed def move_right(self): self.rect.x += self.ship_speed def move_bottom(self): self.rect.y += self.ship_speed def _shoot(self): specific_pos = (self.rect.centerx - (BULLET_SIZE // 2), self.rect.y) self.player_bullets.add(Bullet(specific_pos, BULLET_SIZE, "player")) def update(self): self.rect = self.image.get_rect(topleft=(self.rect.x, self.rect.y))world.py
import pygame from ship import Ship from alien import Alien from settings import HEIGHT, WIDTH, ENEMY_SPEED, CHARACTER_SIZE, BULLET_SIZE, NAV_THICKNESS from bullet import Bullet from display import Display class World: def __init__(self, screen): self.screen = screen self.player = pygame.sprite.GroupSingle() self.aliens = pygame.sprite.Group() self.display = Display(self.screen) self.game_over = False self.player_score = 0 self.game_level = 1 self._generate_world() def _generate_aliens(self): # generate opponents alien_cols = (WIDTH // CHARACTER_SIZE) // 2 alien_rows = 3 for y in range(alien_rows): for x in range(alien_cols): my_x = CHARACTER_SIZE * x my_y = CHARACTER_SIZE * y specific_pos = (my_x, my_y) self.aliens.add(Alien(specific_pos, CHARACTER_SIZE, y)) # create and add player to the screen def _generate_world(self): # create the player's ship player_x, player_y = WIDTH // 2, HEIGHT - CHARACTER_SIZE center_size = CHARACTER_SIZE // 2 player_pos = (player_x - center_size, player_y) self.player.add(Ship(player_pos, CHARACTER_SIZE)) self._generate_aliens() def add_additionals(self): # add nav bar nav = pygame.Rect(0, HEIGHT, WIDTH, NAV_THICKNESS) pygame.draw.rect(self.screen, pygame.Color("gray"), nav) # render player's life, score and game level self.display.show_life(self.player.sprite.life) self.display.show_score(self.player_score) self.display.show_level(self.game_level) def player_move(self, attack = False): keys = pygame.key.get_pressed() if keys[pygame.K_a] and not self.game_over or keys[pygame.K_LEFT] and not self.game_over: if self.player.sprite.rect.left > 0: self.player.sprite.move_left() if keys[pygame.K_d] and not self.game_over or keys[pygame.K_RIGHT] and not self.game_over: if self.player.sprite.rect.right < WIDTH: self.player.sprite.move_right() if keys[pygame.K_w] and not self.game_over or keys[pygame.K_UP] and not self.game_over: if self.player.sprite.rect.top > 0: self.player.sprite.move_up() if keys[pygame.K_s] and not self.game_over or keys[pygame.K_DOWN] and not self.game_over: if self.player.sprite.rect.bottom < HEIGHT: self.player.sprite.move_bottom() # game restart button if keys[pygame.K_r]: self.game_over = False self.player_score = 0 self.game_level = 1 for alien in self.aliens.sprites(): alien.kill() self._generate_world() if attack and not self.game_over: self.player.sprite._shoot() def _detect_collisions(self): # checks if player bullet hits the enemies (aliens) player_attack_collision = pygame.sprite.groupcollide(self.aliens, self.player.sprite.player_bullets, True, True) if player_attack_collision: self.player_score += 10 # checks if the aliens' bullet hit the player for alien in self.aliens.sprites(): alien_attack_collision = pygame.sprite.groupcollide(alien.bullets, self.player, True, False) if alien_attack_collision: self.player.sprite.life -= 1 break # checks if the aliens hit the player alien_to_player_collision = pygame.sprite.groupcollide(self.aliens, self.player, True, False) if alien_to_player_collision: self.player.sprite.life -= 1 def _alien_movement(self): move_sideward = False move_forward = False for alien in self.aliens.sprites(): if alien.to_direction == "right" and alien.rect.right < WIDTH or alien.to_direction == "left" and alien.rect.left > 0: move_sideward = True move_forward = False else: move_sideward = False move_forward = True alien.to_direction = "left" if alien.to_direction == "right" else "right" break for alien in self.aliens.sprites(): if move_sideward and not move_forward: if alien.to_direction == "right": alien.move_right() if alien.to_direction == "left": alien.move_left() if not move_sideward and move_forward: alien.move_bottom() def _alien_shoot(self): for alien in self.aliens.sprites(): if (WIDTH - alien.rect.x) // CHARACTER_SIZE == (WIDTH - self.player.sprite.rect.x) // CHARACTER_SIZE: alien._shoot() break def _check_game_state(self): # check if game over if self.player.sprite.life <= 0: self.game_over = True self.display.game_over_message() for alien in self.aliens.sprites(): if alien.rect.top >= HEIGHT: self.game_over = True self.display.game_over_message() break # check if next level if len(self.aliens) == 0 and self.player.sprite.life > 0: self.game_level += 1 self._generate_aliens() for alien in self.aliens.sprites(): alien.move_speed += self.game_level - 1 def update(self): # detecting if bullet, alien, and player group is colliding self._detect_collisions() # allows the aliens to move self._alien_movement() # allows alien to shoot the player self._alien_shoot() # bullets rendering self.player.sprite.player_bullets.update() self.player.sprite.player_bullets.draw(self.screen) [alien.bullets.update() for alien in self.aliens.sprites()] [alien.bullets.draw(self.screen) for alien in self.aliens.sprites()] # player ship rendering self.player.update() self.player.draw(self.screen) # alien rendering self.aliens.draw(self.screen) # add nav self.add_additionals() # checks game state self._check_game_state()Join 50,000+ Python Programmers & Enthusiasts like you!
Email address Subscribe This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.Ethical Hacking with Python EBook
Web Security with Python EBook
Cryptography with Python EBook
Practical Python PDF Processing EBook
Real-Time Traffic Monitoring System with YOLOv9 eBook
Mastering YOLO: Build an Automatic Number Plate Recognition System
© 2026 The Python Code. All rights reserved.