Files
2025-11-13 12:14:18 -07:00

327 lines
11 KiB
Python

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