Files

213 lines
8.8 KiB
Python

# game_manager.py
import pygame
import json
import importlib
import random
from engine.scene import Scene
from engine.menu import Menu
from engine.transitions import Transition
from settings import *
from engine.sound import init_mixer, load_music, play_music, stop_music
from engine.prompt_scene import PromptScene
from engine.result_scene import ResultScene
import pygame
import random
import json
from engine.sound import play_music, stop_music, fadeout_music
from settings import FONT_MD, FONT_LG, WHITE, BLACK, SCREEN_WIDTH, SCREEN_HEIGHT, resource_path
# Import all microgame classes
from microgames.wario.spot_the_bright_one import SpotTheBrightOne
from microgames.wario.light_it_up import LightItUp
from microgames.wario.match_the_mood import MatchTheMood
from microgames.wario.hot_or_cold import HotOrCold
from microgames.wario.truth_or_lie import TruthOrLie
from microgames.ninevolt.insert_cartridge import InsertCartridge
from microgames.ninevolt.jump_plumber import JumpPlumber
from microgames.ninevolt.catch_the_disk import CatchTheDisk
from microgames.ninevolt.pixel_paint import PixelPaint
from microgames.ninevolt.retro_or_modern import RetroOrModern
MICROGAME_CLASSES = {
'microgames.wario.spot_the_bright_one': SpotTheBrightOne,
'microgames.wario.light_it_up': LightItUp,
'microgames.wario.match_the_mood': MatchTheMood,
'microgames.wario.hot_or_cold': HotOrCold,
'microgames.wario.truth_or_lie': TruthOrLie,
'microgames.ninevolt.insert_cartridge': InsertCartridge,
'microgames.ninevolt.jump_plumber': JumpPlumber,
'microgames.ninevolt.catch_the_disk': CatchTheDisk,
'microgames.ninevolt.pixel_paint': PixelPaint,
'microgames.ninevolt.retro_or_modern': RetroOrModern,
}
class GameManager:
def __init__(self, screen, game_type=None):
self.screen = screen
self.game_type = game_type # 'wario' or 'ninevolt'
self.current_microgame = None
self.microgame_start_time = 0
self.score = 0
self.lives = 3
self.game_over = False
self.speed_level = 0 # 0, 1, 2 for normal, speedup 1, speedup 2
self.max_speed_levels = 2
self.initial_microgame_time_limit = 4000 # 4 seconds
self.current_microgame_time_limit = self.initial_microgame_time_limit
self.current_music_type = None # Track currently playing music type
self.load_microgame_list()
self.load_next_microgame()
@property
def speed(self):
return 1 + (self.speed_level * 0.2) # Increase speed by 20% per level
def load_microgame_list(self):
with open(resource_path('data/microgame_list.json'), 'r') as f:
self.microgame_list = json.load(f)
def load_next_microgame(self):
if self.current_microgame:
# self.current_microgame.unload() # No unload method in Scene class
pass
available_microgames = []
for module_name in MICROGAME_CLASSES.keys():
if self.game_type == 'wario' and 'wario' in module_name:
available_microgames.append(module_name)
elif self.game_type == 'ninevolt' and 'ninevolt' in module_name:
available_microgames.append(module_name)
elif self.game_type is None: # If no specific game_type, allow all
available_microgames.append(module_name)
if not available_microgames:
print(f"No microgames found for game_type: {self.game_type}. Loading all microgames.")
available_microgames = list(MICROGAME_CLASSES.keys())
microgame_module_name = random.choice(available_microgames)
MicrogameClass = MICROGAME_CLASSES[microgame_module_name]
self.current_microgame = MicrogameClass(self)
self.current_microgame.start()
self.microgame_start_time = pygame.time.get_ticks()
# Dynamically set time limit based on microgame's timer and end_timer
# Add a small buffer (e.g., 500ms) to ensure GameManager doesn't time out prematurely
self.current_microgame_time_limit = int((self.current_microgame.timer + 0.5) * 1000)
# Load and play music based on microgame type
current_microgame_type = 'wario' if 'wario' in microgame_module_name else 'ninevolt'
if current_microgame_type != self.current_music_type:
if current_microgame_type == 'wario':
load_music(resource_path("Assets/music/wario.ogg"))
elif current_microgame_type == 'ninevolt':
load_music(resource_path("Assets/music/9volt.ogg"))
play_music()
self.current_music_type = current_microgame_type
def update(self, dt):
if self.game_over:
return
current_time = pygame.time.get_ticks()
time_left = max(0, self.current_microgame_time_limit - (current_time - self.microgame_start_time))
self.current_microgame.update(dt, time_left)
def draw(self, screen):
if self.game_over:
self._draw_game_over()
else:
self.current_microgame.draw(self.screen)
self._draw_ui(screen)
def handle_event(self, event):
if self.game_over:
return
self.current_microgame.handle_event(event)
def microgame_finished(self, success, game_type=None):
if self.game_over:
return
if success:
self.score += 1
if self.score % 5 == 0 and self.speed_level < self.max_speed_levels:
self._update_game_speed()
else:
self.lives -= 1
self._check_game_over()
if not self.game_over:
self.current_microgame = ResultScene(self, success, game_type=game_type)
def _update_game_speed(self):
self.speed_level += 1
# The time limit is recalculated in load_next_microgame
def _check_game_over(self):
if self.lives <= 0:
self.game_over = True
fadeout_music(2000) # Fade out music over 2 seconds
def _draw_ui(self, screen):
score_text = FONT_MD.render(f"Score: {self.score}", True, WHITE)
lives_text = FONT_MD.render(f"Lives: {self.lives}", True, WHITE)
screen.blit(score_text, (10, 10))
screen.blit(lives_text, (SCREEN_WIDTH - lives_text.get_width() - 10, 10))
# Draw microgame prompt
if self.current_microgame and hasattr(self.current_microgame, 'prompt'):
prompt_text = FONT_LG.render(self.current_microgame.prompt, True, WHITE)
prompt_rect = prompt_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 8))
screen.blit(prompt_text, prompt_rect)
# Draw time bar
time_left = max(0, self.current_microgame_time_limit - (pygame.time.get_ticks() - self.microgame_start_time))
bar_width = int((time_left / self.current_microgame_time_limit) * SCREEN_WIDTH)
pygame.draw.rect(screen, WHITE, (0, SCREEN_HEIGHT - 20, bar_width, 10))
def _draw_game_over(self):
game_over_text = FONT_LG.render("GAME OVER", True, WHITE)
restart_text = FONT_MD.render("Press R to Restart", True, WHITE)
self.screen.blit(game_over_text, (SCREEN_WIDTH // 2 - game_over_text.get_width() // 2, SCREEN_HEIGHT // 2 - game_over_text.get_height() // 2))
self.screen.blit(restart_text, (SCREEN_WIDTH // 2 - restart_text.get_width() // 2, SCREEN_HEIGHT // 2 + restart_text.get_height()))
class GameOverScene(Scene):
def __init__(self, manager):
super().__init__(manager)
def update(self, dt):
pass # No continuous update needed for game over screen
def handle_event(self, event):
if event.type == pygame.MOUSEBUTTONDOWN:
if event.button == 1: # Left click
stop_music() # Stop music when returning to menu
self.manager.game_state = "menu"
self.manager.current_scene = Menu(self.manager)
elif event.type == pygame.KEYDOWN:
if event.key == pygame.K_r:
stop_music() # Stop music when returning to menu
self.manager.game_state = "menu"
self.manager.current_scene = Menu(self.manager)
def draw(self, screen):
screen.fill(BLACK)
font = pygame.font.Font(None, 100)
text = font.render("Game Over", True, RED)
text_rect = text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 3))
screen.blit(text, text_rect)
font = pygame.font.Font(None, 50)
score_text = font.render(f"Score: {self.manager.score}", True, WHITE)
score_rect = score_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))
screen.blit(score_text, score_rect)
font = pygame.font.Font(None, 30)
continue_text = font.render("Press R to Restart or Click to continue", True, WHITE)
continue_rect = continue_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT * 2 // 3))
screen.blit(continue_text, continue_rect)
""