diff --git a/blockwars-game/blockwars.py b/blockwars-game/blockwars.py new file mode 100644 index 0000000..c20f501 --- /dev/null +++ b/blockwars-game/blockwars.py @@ -0,0 +1,321 @@ +#!/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() + diff --git a/blockwars-game/enemy_death_sound.wav b/blockwars-game/enemy_death_sound.wav new file mode 100644 index 0000000..eb5c459 Binary files /dev/null and b/blockwars-game/enemy_death_sound.wav differ diff --git a/blockwars-game/go_sound.wav b/blockwars-game/go_sound.wav new file mode 100644 index 0000000..5dc294e Binary files /dev/null and b/blockwars-game/go_sound.wav differ diff --git a/blockwars-game/level_up_sound.wav b/blockwars-game/level_up_sound.wav new file mode 100644 index 0000000..52854e2 Binary files /dev/null and b/blockwars-game/level_up_sound.wav differ diff --git a/blockwars-game/player_death_sound.wav b/blockwars-game/player_death_sound.wav new file mode 100644 index 0000000..fc09ec5 Binary files /dev/null and b/blockwars-game/player_death_sound.wav differ diff --git a/blockwars-game/player_fire_sound.wav b/blockwars-game/player_fire_sound.wav new file mode 100644 index 0000000..02cdc22 Binary files /dev/null and b/blockwars-game/player_fire_sound.wav differ