#!/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()