#!/usr/bin/python3 # Description: blockwars - A simple game written in Python. # Usage: python3 blockwars.py # Author: Justin Oros # Source: https://github.com/JustinOros import pygame import random import time import os # Initialize pygame pygame.init() # Set up full-screen mode SCREEN_WIDTH = pygame.display.Info().current_w SCREEN_HEIGHT = pygame.display.Info().current_h screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.FULLSCREEN) pygame.display.set_caption("Block Wars") # Define colors WHITE = (255, 255, 255) BLUE = (0, 0, 255) RED = (255, 0, 0) DARK_GRAY = (50, 50, 50) # Function to load sound safely def load_sound(filename): if os.path.exists(filename): return pygame.mixer.Sound(filename) else: print(f"Warning: {filename} not found. Sound will be disabled.") return None # Load sounds GO_SOUND = load_sound("go_sound.wav") FIRE_SOUND = load_sound("player_fire_sound.wav") DIE_SOUND = load_sound("player_death_sound.wav") LEVEL_UP_SOUND = load_sound("level_up_sound.wav") ENEMY_DEATH_SOUND = load_sound("enemy_death_sound.wav") EXPLOSION_SOUND = load_sound("explosion_sound.wav") # Set font for score font = pygame.font.SysFont(None, 30) # Initialize the joystick (controller) pygame.joystick.init() controller = None if pygame.joystick.get_count() > 0: controller = pygame.joystick.Joystick(0) controller.init() # Player class class Player: def __init__(self): self.x = SCREEN_WIDTH // 2 self.y = SCREEN_HEIGHT // 2 self.size = 20 self.color = BLUE self.speed = 5 self.direction = None def move(self, keys, joystick_axes): if joystick_axes[1] < -0.5: self.y -= self.speed self.direction = 'up' elif joystick_axes[1] > 0.5: self.y += self.speed self.direction = 'down' if joystick_axes[0] < -0.5: self.x -= self.speed self.direction = 'left' elif joystick_axes[0] > 0.5: self.x += self.speed self.direction = 'right' if keys[pygame.K_w]: self.y -= self.speed self.direction = 'up' if keys[pygame.K_s]: self.y += self.speed self.direction = 'down' if keys[pygame.K_a]: self.x -= self.speed self.direction = 'left' if keys[pygame.K_d]: self.x += self.speed self.direction = 'right' if self.x < 0: self.x = SCREEN_WIDTH - self.size elif self.x > SCREEN_WIDTH - self.size: self.x = 0 if self.y < 0: self.y = SCREEN_HEIGHT - self.size elif self.y > SCREEN_HEIGHT - self.size: self.y = 0 def draw(self): pygame.draw.rect(screen, self.color, (self.x, self.y, self.size, self.size)) # Projectile class class Projectile: def __init__(self, x, y, direction): self.x = x self.y = y self.size = 5 self.color = WHITE self.speed = 15 self.direction = direction def move(self): if self.direction == 'up': self.y -= self.speed elif self.direction == 'down': self.y += self.speed elif self.direction == 'left': self.x -= self.speed elif self.direction == 'right': self.x += self.speed def draw(self): pygame.draw.rect(screen, self.color, (self.x, self.y, self.size, self.size)) # Explosion class class Explosion: def __init__(self, x, y): self.x = x self.y = y self.size = 50 self.lifetime = 10 def draw(self): pygame.draw.circle(screen, (255, 165, 0), (self.x, self.y), self.size) self.lifetime -= 1 def is_alive(self): return self.lifetime > 0 # Enemy class class Enemy: def __init__(self, speed): edge = random.choice(["top", "bottom", "left", "right"]) if edge == "top": self.x = random.randint(0, SCREEN_WIDTH - 20) self.y = 0 elif edge == "bottom": self.x = random.randint(0, SCREEN_WIDTH - 20) self.y = SCREEN_HEIGHT - 20 elif edge == "left": self.x = 0 self.y = random.randint(0, SCREEN_HEIGHT - 20) else: self.x = SCREEN_WIDTH - 20 self.y = random.randint(0, SCREEN_HEIGHT - 20) self.size = 20 self.color = RED self.speed = speed def move(self, player_x, player_y): if self.x < player_x: self.x += self.speed elif self.x > player_x: self.x -= self.speed if self.y < player_y: self.y += self.speed elif self.y > player_y: self.y -= self.speed def draw(self): pygame.draw.rect(screen, self.color, (self.x, self.y, self.size, self.size)) # Draw pause screen def draw_pause_screen(): overlay = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT)) overlay.set_alpha(180) overlay.fill((0, 0, 0)) screen.blit(overlay, (0, 0)) pause_font = pygame.font.SysFont(None, 100) instruction_font = pygame.font.SysFont(None, 40) pause_text = pause_font.render("PAUSED", True, WHITE) instruction_text = instruction_font.render("Press ESC to resume or Q to Quit.", True, WHITE) screen.blit(pause_text, ( SCREEN_WIDTH // 2 - pause_text.get_width() // 2, SCREEN_HEIGHT // 2 - pause_text.get_height() // 2 - 30 )) screen.blit(instruction_text, ( SCREEN_WIDTH // 2 - instruction_text.get_width() // 2, SCREEN_HEIGHT // 2 + 30 )) # Main game loop def game(): clock = pygame.time.Clock() player = Player() projectiles = [] explosions = [] level = 1 score = 0 enemies = [Enemy(2)] running = True paused = False player_dead = False if GO_SOUND: GO_SOUND.play() while running: screen.fill(DARK_GRAY) keys = pygame.key.get_pressed() joystick_axes = [controller.get_axis(0), controller.get_axis(1)] if controller else [0, 0] for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: paused = not paused elif paused and event.key == pygame.K_q: running = False elif not paused and event.key == pygame.K_SPACE: if player.direction: projectiles.append(Projectile(player.x + player.size // 2, player.y + player.size // 2, player.direction)) if FIRE_SOUND: FIRE_SOUND.play() if event.type == pygame.JOYBUTTONDOWN: if event.button == 7 or event.button == 6: # Start or Select paused = not paused elif paused and event.button == 2: # X button running = False elif not paused and event.button == 0: # A button if player.direction: projectiles.append(Projectile(player.x + player.size // 2, player.y + player.size // 2, player.direction)) if FIRE_SOUND: FIRE_SOUND.play() if event.type == pygame.MOUSEBUTTONDOWN: if not paused and event.button == 1: if player.direction: projectiles.append(Projectile(player.x + player.size // 2, player.y + player.size // 2, player.direction)) if FIRE_SOUND: FIRE_SOUND.play() if paused: draw_pause_screen() pygame.display.flip() clock.tick(60) continue player.move(keys, joystick_axes) for projectile in projectiles[:]: projectile.move() projectile.draw() if projectile.x < 0 or projectile.x > SCREEN_WIDTH or projectile.y < 0 or projectile.y > SCREEN_HEIGHT: projectiles.remove(projectile) for enemy in enemies[:]: enemy.move(player.x, player.y) enemy.draw() if pygame.Rect(player.x, player.y, player.size, player.size).colliderect( pygame.Rect(enemy.x, enemy.y, enemy.size, enemy.size)): if not player_dead: if DIE_SOUND: DIE_SOUND.play() player_dead = True show_final_score(score) running = False for projectile in projectiles[:]: if pygame.Rect(enemy.x, enemy.y, enemy.size, enemy.size).colliderect( pygame.Rect(projectile.x, projectile.y, projectile.size, projectile.size)): explosions.append(Explosion(enemy.x + enemy.size // 2, enemy.y + enemy.size // 2)) if ENEMY_DEATH_SOUND: ENEMY_DEATH_SOUND.play() enemies.remove(enemy) projectiles.remove(projectile) score += 100 break for explosion in explosions[:]: explosion.draw() if not explosion.is_alive(): explosions.remove(explosion) if not enemies: level += 1 if LEVEL_UP_SOUND: LEVEL_UP_SOUND.play() enemy_speed = 2 + (level // 3) enemies = [Enemy(enemy_speed) for _ in range(level)] player.draw() score_text = font.render(f"Score: {score}", True, WHITE) level_text = font.render(f"Level: {level}", True, WHITE) screen.blit(score_text, (10, 10)) screen.blit(level_text, (SCREEN_WIDTH - level_text.get_width() - 10, 10)) pygame.display.flip() clock.tick(60) # Function to display the final score on death def show_final_score(score): font_large = pygame.font.SysFont(None, 80) final_score_text = font_large.render(f"Final Score: {score}", True, WHITE) screen.fill(DARK_GRAY) screen.blit(final_score_text, (SCREEN_WIDTH // 2 - final_score_text.get_width() // 2, SCREEN_HEIGHT // 2 - final_score_text.get_height() // 2)) pygame.display.flip() time.sleep(3) # Run the game if __name__ == "__main__": game() pygame.quit()