diff --git a/game-groguvstiefighters/audio-explode.mp3 b/game-groguvstiefighters/audio-explode.mp3 new file mode 100644 index 0000000..e0a2d9b Binary files /dev/null and b/game-groguvstiefighters/audio-explode.mp3 differ diff --git a/game-groguvstiefighters/audio-laser.mp3 b/game-groguvstiefighters/audio-laser.mp3 new file mode 100644 index 0000000..be57df2 Binary files /dev/null and b/game-groguvstiefighters/audio-laser.mp3 differ diff --git a/game-groguvstiefighters/audio-music.mp3 b/game-groguvstiefighters/audio-music.mp3 new file mode 100644 index 0000000..00bdfe4 Binary files /dev/null and b/game-groguvstiefighters/audio-music.mp3 differ diff --git a/game-groguvstiefighters/game-groguvstiefighters.py b/game-groguvstiefighters/game-groguvstiefighters.py new file mode 100644 index 0000000..358415d --- /dev/null +++ b/game-groguvstiefighters/game-groguvstiefighters.py @@ -0,0 +1,326 @@ +#!/usr/bin/python3 +# Description: Grogy vs TIE Fighters - A Star Wars-ish Pygame written in Python. +# Usage: python3 game-groguvstiefighters.py +# Author: Justin Oros +# Source: https://github.com/JustinOros + +import pygame +import random +import math + +pygame.init() +pygame.mixer.init() + +info = pygame.display.Info() +WIDTH, HEIGHT = info.current_w, info.current_h +screen = pygame.display.set_mode((WIDTH, HEIGHT), pygame.FULLSCREEN) +pygame.display.set_caption("Grogu TIE Fighters") +pygame.mouse.set_visible(False) + +try: + grogu_img = pygame.image.load("image-grogu.png") + grogu_img = pygame.transform.scale(grogu_img, (60, 60)) +except: + grogu_img = None + +try: + tiefighter_img = pygame.image.load("image-tiefighter.png") + tiefighter_img = pygame.transform.scale(tiefighter_img, (70, 70)) +except: + tiefighter_img = None + +try: + laser_sound = pygame.mixer.Sound("audio-laser.mp3") +except: + laser_sound = None + +try: + explode_sound = pygame.mixer.Sound("audio-explode.mp3") +except: + explode_sound = None + +try: + pygame.mixer.music.load("audio-music.mp3") + pygame.mixer.music.play(-1) +except: + print("audio-music.mp3 not found or failed to load") + +WHITE = (255, 255, 255) +BLACK = (0, 0, 0) +BLUE = (50, 150, 255) +RED = (255, 50, 50) +YELLOW = (255, 255, 100) +GREEN = (50, 255, 50) + +clock = pygame.time.Clock() +FPS = 60 + +font_large = pygame.font.Font(None, 100) +font_small = pygame.font.Font(None, 40) +font_default = pygame.font.Font(None, 36) + +class Player: + def __init__(self): + self.x = WIDTH // 4 + self.y = HEIGHT // 2 + self.radius = 30 + self.speed = 5 + self.color = BLUE + self.lives = 3 + def move(self, keys): + if keys[pygame.K_w] and self.y - self.radius > 0: + self.y -= self.speed + if keys[pygame.K_s] and self.y + self.radius < HEIGHT: + self.y += self.speed + if keys[pygame.K_a] and self.x - self.radius > 0: + self.x -= self.speed + if keys[pygame.K_d] and self.x + self.radius < WIDTH: + self.x += self.speed + def draw(self): + if grogu_img: + img_rect = grogu_img.get_rect(center=(int(self.x), int(self.y))) + screen.blit(grogu_img, img_rect) + else: + pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), self.radius) + +class Bullet: + def __init__(self, x, y, direction, color=YELLOW): + self.x = x + self.y = y + self.radius = 5 + self.speed = 35 + self.direction = direction + self.color = color + def update(self): + self.x += self.speed * self.direction + def draw(self): + pygame.draw.circle(screen, self.color, (int(self.x), int(self.y)), self.radius) + def off_screen(self): + return self.x < 0 or self.x > WIDTH + +class Enemy: + def __init__(self): + self.x = WIDTH + 30 + self.y = random.randint(50, HEIGHT - 50) + self.start_y = self.y + self.radius = 35 + self.speed = WIDTH * 0.005 + self.color = RED + self.shoot_cooldown = 0 + self.shoot_delay = random.randint(60, 120) + self.oscillation_offset = random.uniform(0, 2*math.pi) + def update(self): + self.x -= self.speed + self.shoot_cooldown += 1 + self.y = self.start_y + math.sin(pygame.time.get_ticks() * 0.003 + self.oscillation_offset) * 30 + def draw(self): + if tiefighter_img: + img_rect = tiefighter_img.get_rect(center=(int(self.x), int(self.y))) + screen.blit(tiefighter_img, img_rect) + else: + rect = pygame.Rect(int(self.x - self.radius), int(self.y - self.radius), self.radius * 2, self.radius * 2) + pygame.draw.rect(screen, self.color, rect) + pygame.draw.circle(screen, YELLOW, (int(self.x), int(self.y)), 5) + def can_shoot(self): + return self.shoot_cooldown >= self.shoot_delay + def shoot(self): + self.shoot_cooldown = 0 + self.shoot_delay = random.randint(60, 120) + return Bullet(self.x - self.radius, self.y, -1, RED) + def off_screen(self): + return self.x < -self.radius * 2 + +class Explosion: + def __init__(self, x, y, max_radius=50, color=YELLOW): + self.x = x + self.y = y + self.radius = 1 + self.max_radius = max_radius + self.color = color + self.life = 10 + def update(self): + self.radius += self.max_radius / self.life + self.life -= 1 + def draw(self): + alpha_surface = pygame.Surface((self.radius*2, self.radius*2), pygame.SRCALPHA) + pygame.draw.circle(alpha_surface, (*self.color, int(255 * (self.life / 10))), (int(self.radius), int(self.radius)), int(self.radius)) + screen.blit(alpha_surface, (self.x - self.radius, self.y - self.radius)) + def done(self): + return self.life <= 0 + +def show_start_screen(): + waiting = True + while waiting: + screen.fill(BLACK) + title_text = font_large.render("BABY YODA vs TIE FIGHTERS", True, YELLOW) + subtitle_text = font_small.render("Press any key to begin...", True, YELLOW) + screen.blit(title_text, (WIDTH//2 - title_text.get_width()//2, HEIGHT//2 - 80)) + screen.blit(subtitle_text, (WIDTH//2 - subtitle_text.get_width()//2, HEIGHT//2 + 40)) + pygame.display.flip() + for event in pygame.event.get(): + if event.type == pygame.QUIT: + pygame.quit() + exit() + if event.type == pygame.KEYDOWN or event.type == pygame.MOUSEBUTTONDOWN: + waiting = False + clock.tick(FPS) + +show_start_screen() + +player = Player() +player_bullets = [] +enemy_bullets = [] +enemies = [] +explosions = [] +score = 0 +enemy_spawn_timer = 0 +enemy_spawn_delay = 90 +star_offset = 0 + +running = True +while running: + clock.tick(FPS) + for event in pygame.event.get(): + if event.type == pygame.QUIT: + running = False + if event.type == pygame.KEYDOWN: + if event.key in [pygame.K_ESCAPE, pygame.K_q]: + running = False + if event.key in [pygame.K_LALT, pygame.K_RALT, pygame.K_SPACE]: + player_bullets.append(Bullet(player.x + player.radius, player.y, 1, YELLOW)) + if laser_sound: + laser_sound.play() + if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1: + player_bullets.append(Bullet(player.x + player.radius, player.y, 1, YELLOW)) + if laser_sound: + laser_sound.play() + + keys = pygame.key.get_pressed() + player.move(keys) + + enemy_spawn_timer += 1 + if enemy_spawn_timer >= enemy_spawn_delay: + enemies.append(Enemy()) + enemy_spawn_timer = 0 + enemy_spawn_delay = random.randint(60, 120) + + for bullet in player_bullets[:]: + bullet.update() + if bullet.off_screen(): + player_bullets.remove(bullet) + + for enemy in enemies[:]: + enemy.update() + if enemy.can_shoot(): + enemy_bullets.append(enemy.shoot()) + if enemy.off_screen(): + enemies.remove(enemy) + + for bullet in enemy_bullets[:]: + bullet.update() + if bullet.off_screen(): + enemy_bullets.remove(bullet) + + for bullet in player_bullets[:]: + for enemy in enemies[:]: + dist = math.sqrt((bullet.x - enemy.x)**2 + (bullet.y - enemy.y)**2) + if dist < bullet.radius + enemy.radius: + if bullet in player_bullets: + player_bullets.remove(bullet) + if enemy in enemies: + enemies.remove(enemy) + if explode_sound: + explode_sound.play() + explosions.append(Explosion(enemy.x, enemy.y, max_radius=50, color=YELLOW)) + score += 100 + break + + for bullet in enemy_bullets[:]: + dist = math.sqrt((bullet.x - player.x)**2 + (bullet.y - player.y)**2) + if dist < bullet.radius + player.radius: + if bullet in enemy_bullets: + enemy_bullets.remove(bullet) + player.lives -= 1 + if explode_sound: + explode_sound.play() + explosions.append(Explosion(player.x, player.y, max_radius=60, color=RED)) + + for enemy in enemies[:]: + dist = math.sqrt((enemy.x - player.x)**2 + (enemy.y - player.y)**2) + if dist < enemy.radius + player.radius: + player.lives -= 1 + enemies.remove(enemy) + if explode_sound: + explode_sound.play() + explosions.append(Explosion(player.x, player.y, max_radius=60, color=RED)) + + explosions = [exp for exp in explosions if not exp.done()] + for exp in explosions: + exp.update() + + if player.lives <= 0: + pygame.mixer.music.fadeout(2000) + screen.fill(BLACK) + game_over_text = font_default.render(f"GAME OVER!", True, YELLOW) + score_text_display = font_default.render(f"Final Score: {score}", True, YELLOW) + restart_text = font_default.render("Press R to Restart", True, YELLOW) + screen.blit(game_over_text, (WIDTH//2 - 120, HEIGHT//2 - 60)) + screen.blit(score_text_display, (WIDTH//2 - 140, HEIGHT//2 - 10)) + screen.blit(restart_text, (WIDTH//2 - 150, HEIGHT//2 + 40)) + pygame.display.flip() + start_time = pygame.time.get_ticks() + waiting = True + while waiting: + current_time = pygame.time.get_ticks() + if current_time - start_time > 3000: + waiting = False + running = False + for event in pygame.event.get(): + if event.type == pygame.QUIT: + waiting = False + running = False + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_r: + try: + pygame.mixer.music.play(-1) + except: + pass + player = Player() + player_bullets = [] + enemy_bullets = [] + enemies = [] + explosions = [] + score = 0 + enemy_spawn_timer = 0 + star_offset = 0 + waiting = False + elif event.key in [pygame.K_ESCAPE, pygame.K_q]: + waiting = False + running = False + + screen.fill(BLACK) + star_offset -= 2 + if star_offset <= -WIDTH: + star_offset = 0 + for i in range(100): + x = ((i * 73) + star_offset) % WIDTH + y = (i * 137) % HEIGHT + pygame.draw.circle(screen, WHITE, (x, y), 1) + + player.draw() + for bullet in player_bullets: + bullet.draw() + for bullet in enemy_bullets: + bullet.draw() + for enemy in enemies: + enemy.draw() + for exp in explosions: + exp.draw() + + score_text = font_default.render(f"Score: {score}", True, WHITE) + screen.blit(score_text, (10, HEIGHT - 50)) + lives_text = font_default.render(f"Lives: {player.lives}", True, WHITE) + screen.blit(lives_text, (WIDTH - 150, HEIGHT - 50)) + pygame.display.flip() + +pygame.quit() diff --git a/game-groguvstiefighters/image-grogu.png b/game-groguvstiefighters/image-grogu.png new file mode 100644 index 0000000..30284de Binary files /dev/null and b/game-groguvstiefighters/image-grogu.png differ diff --git a/game-groguvstiefighters/image-tiefighter.png b/game-groguvstiefighters/image-tiefighter.png new file mode 100644 index 0000000..0e655b8 Binary files /dev/null and b/game-groguvstiefighters/image-tiefighter.png differ