From e07ac205b2457dace981278c93520fffbd51deed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rihards=20=C5=A0ev=C4=8Duks?= Date: Wed, 25 Feb 2026 06:21:55 +0000 Subject: [PATCH] Update game.py --- game.py | 400 ++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 362 insertions(+), 38 deletions(-) diff --git a/game.py b/game.py index 25f7cf8..8fd80c5 100644 --- a/game.py +++ b/game.py @@ -6,38 +6,103 @@ from player import Player from camera import Camera from inventory import Inventory from enemy_manager import EnemyManager +from menu_system import MainMenu, PauseMenu, NewGameDialog, LoadGameDialog, SettingsMenu, DeathScreen +from save_system import SaveSystem +from weapon_system import WeaponManager +from combat_system import CombatSystem +from hotbar import Hotbar +from items import get_item class Game: def __init__(self): - pygame.init() # <-- IMPORTANT - - self.show_inventory = False + pygame.init() # ---------------------------------- # Display Setup # ---------------------------------- - flags = pygame.SCALED - self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), flags) - pygame.display.set_caption(GAME_TITLE) + self.setup_display() self.clock = pygame.time.Clock() self.running = True self.paused = False # ---------------------------------- - # Core Systems + # Game State Management # ---------------------------------- - self.world = World() - self.player = Player(100, 100) - self.camera = Camera(self.player) - self.inventory = Inventory() - self.enemy_manager = EnemyManager(self.world, self.player) + self.game_state = "menu" + self.show_inventory = False + self.world_name = "Default" + + # ---------------------------------- + # Menu Systems + # ---------------------------------- + self.main_menu = MainMenu(self) + self.new_game_dialog = None + self.load_game_dialog = None + self.pause_menu = None + self.settings_menu = None + self.death_screen = None + self.save_system = SaveSystem() + + # ---------------------------------- + # Core Systems (initialized as None) + # ---------------------------------- + self.world = None + self.player = None + self.camera = None + self.inventory = None + self.enemy_manager = None + self.weapon_manager = None + self.combat_system = None + self.hotbar = None # ---------------------------------- # Debug + # ---------------------------------- self.font = pygame.font.SysFont("consolas", 18) + def setup_display(self): + """Setup display with current resolution and fullscreen setting""" + flags = pygame.SCALED + if FULLSCREEN: + flags |= pygame.FULLSCREEN + + self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), flags) + pygame.display.set_caption(GAME_TITLE) + + def toggle_fullscreen(self): + """Toggle fullscreen mode""" + global FULLSCREEN + FULLSCREEN = not FULLSCREEN + self.setup_display() + + def init_game(self): + """Initialize game systems (called when starting new game or loading)""" + self.world = World() + self.weapon_manager = WeaponManager() + self.player = Player(100, 100, self.weapon_manager) + self.camera = Camera(self.player) + self.inventory = Inventory() + self.hotbar = Hotbar(self.inventory, self.weapon_manager) + self.enemy_manager = EnemyManager(self.world, self.player) + self.combat_system = CombatSystem(self.weapon_manager) + self.show_inventory = False + + # Add starting items and WEAPONS + self.inventory.add_item(ITEM_WOOD, 10) + self.inventory.add_item(ITEM_STONE, 5) + + # Add all weapons to inventory + self.inventory.add_item(ITEM_WOODEN_SWORD, 1) + self.inventory.add_item(ITEM_IRON_SWORD, 1) + self.inventory.add_item(ITEM_GOLD_SWORD, 1) + + # Add weapons to weapon manager + self.weapon_manager.add_weapon(ITEM_WOODEN_SWORD) + self.weapon_manager.add_weapon(ITEM_IRON_SWORD) + self.weapon_manager.add_weapon(ITEM_GOLD_SWORD) + # ========================================================== # MAIN LOOP # ========================================================== @@ -45,17 +110,185 @@ class Game: while self.running: dt = self.clock.tick(FPS) / 1000 - self.handle_events() + if self.game_state == "menu": + self.handle_menu_events() + self.update_menu() + self.draw_menu() - if not self.paused: - self.update(dt) + elif self.game_state == "settings": + self.handle_settings_events() + self.settings_menu.update(dt) + self.settings_menu.draw(self.screen) - self.draw() + elif self.game_state == "new_game_dialog": + self.handle_new_game_dialog_events() + self.new_game_dialog.update(dt) + self.new_game_dialog.draw(self.screen) + + elif self.game_state == "load_game_dialog": + self.handle_load_game_dialog_events() + self.load_game_dialog.update() + self.load_game_dialog.draw(self.screen) + + elif self.game_state == "playing": + self.handle_events() + if not self.paused: + self.update(dt) + self.draw() + + elif self.game_state == "paused": + self.handle_pause_events() + self.pause_menu.update(dt) + self.draw_paused() + + elif self.game_state == "dead": + self.handle_death_events() + self.death_screen.update(dt) + self.draw_dead() pygame.quit() # ========================================================== - # EVENTS + # MAIN MENU STATE + # ========================================================== + def handle_menu_events(self): + action = self.main_menu.handle_events() + + if action == "new_game": + self.new_game_dialog = NewGameDialog(self) + self.game_state = "new_game_dialog" + + elif action == "load_game": + self.load_game_dialog = LoadGameDialog(self, self.save_system) + self.game_state = "load_game_dialog" + + elif action == "settings": + self.settings_menu = SettingsMenu(self) + self.game_state = "settings" + + elif action == "quit": + self.running = False + + def update_menu(self): + self.main_menu.update() + + def draw_menu(self): + self.main_menu.draw(self.screen) + + # ========================================================== + # SETTINGS STATE + # ========================================================== + def handle_settings_events(self): + action = self.settings_menu.handle_events() + + if action == "back": + self.game_state = "menu" + + # ========================================================== + # NEW GAME DIALOG STATE + # ========================================================== + def handle_new_game_dialog_events(self): + action = self.new_game_dialog.handle_events() + + if action and action.startswith("create:"): + world_name = action.replace("create:", "") + self.world_name = world_name + self.init_game() + self.game_state = "playing" + print(f"New game '{world_name}' started") + + elif action == "cancel": + self.game_state = "menu" + + # ========================================================== + # LOAD GAME DIALOG STATE + # ========================================================== + def handle_load_game_dialog_events(self): + action = self.load_game_dialog.handle_events() + + if action and action.startswith("load:"): + save_index = int(action.replace("load:", "")) + saves = self.save_system.get_save_files() + + if 0 <= save_index < len(saves): + save_file = saves[save_index]["name"] + self.init_game() + + if self.save_system.load_game(self, save_file): + self.game_state = "playing" + print(f"Game loaded: {save_file}") + else: + print("Failed to load game") + self.game_state = "load_game_dialog" + + elif action and action.startswith("delete:"): + save_index = int(action.replace("delete:", "")) + saves = self.save_system.get_save_files() + + if 0 <= save_index < len(saves): + save_file = saves[save_index]["name"] + self.save_system.delete_save(save_file) + self.load_game_dialog = LoadGameDialog(self, self.save_system) + + elif action == "cancel": + self.game_state = "menu" + + # ========================================================== + # PAUSE STATE + # ========================================================== + def handle_pause_events(self): + action = self.pause_menu.handle_events() + + if action == "resume": + self.paused = False + self.game_state = "playing" + + elif action == "save": + self.save_system.save_game(self, self.world_name) + self.pause_menu.show_message("Game saved!") + + elif action == "backup": + self.save_system.backup_game(self) + self.pause_menu.show_message("Backup created!") + + elif action == "quit_to_menu": + self.paused = False + self.game_state = "menu" + + def draw_paused(self): + self.screen.fill(BACKGROUND_COLOR) + self.world.draw(self.screen, self.camera) + self.enemy_manager.draw(self.screen, self.camera) + self.player.draw(self.screen, self.camera) + self.pause_menu.draw(self.screen) + + # ========================================================== + # DEATH STATE + # ========================================================== + def handle_death_events(self): + action = self.death_screen.handle_events() + + if action == "respawn": + # Reset player health and position + self.player.health = self.player.max_health + self.player.pos = pygame.Vector2(100, 100) + self.player.rect.x = 100 + self.player.rect.y = 100 + self.player.velocity = pygame.Vector2(0, 0) + self.game_state = "playing" + + elif action == "quit_to_menu": + self.game_state = "menu" + + def draw_dead(self): + self.screen.fill(BACKGROUND_COLOR) + self.world.draw(self.screen, self.camera) + self.enemy_manager.draw(self.screen, self.camera) + self.player.draw(self.screen, self.camera) + self.death_screen.draw(self.screen) + + # ========================================================== + # GAMEPLAY STATE # ========================================================== def handle_events(self): for event in pygame.event.get(): @@ -65,44 +298,85 @@ class Game: if event.type == pygame.KEYDOWN: if event.key == pygame.K_ESCAPE: - self.paused = not self.paused + self.paused = True + self.pause_menu = PauseMenu(self) + self.game_state = "paused" # Toggle inventory if event.key == pygame.K_i: self.show_inventory = not self.show_inventory - # ------------------------------- - # Mouse input for breaking/placing - # ------------------------------- + # Hotbar input + if self.hotbar: + self.hotbar.handle_input(event) + + # Mouse input for attacking and placing if event.type == pygame.MOUSEBUTTONDOWN: + if self.show_inventory: + continue + if event.button == 1: # Left click - self.world.break_block( - pygame.mouse.get_pos(), - self.camera, - self.inventory - ) + # Get current held item + items_list = list(self.inventory.slots.items()) + current_item = None + if self.hotbar.selected_slot < len(items_list): + current_item_id, _ = items_list[self.hotbar.selected_slot] + current_item = get_item(current_item_id) - if event.button == 3: # Right click - self.world.place_block( - pygame.mouse.get_pos(), - self.camera - ) + # Check if holding a weapon + is_holding_weapon = (current_item is not None and + current_item.id in WEAPON_STATS) + + if is_holding_weapon: + # Attack with sword + print(f"DEBUG: Attempting sword attack with {current_item.name}") + self.combat_system.player_attack(self.player, self.enemy_manager.enemies) + else: + # Mine block if not holding weapon + print("DEBUG: Mining block") + self.world.break_block( + pygame.mouse.get_pos(), + self.camera, + self.inventory, + self.player.rect + ) + + if event.button == 3: # Right click - place block + # Get current held item + items_list = list(self.inventory.slots.items()) + if self.hotbar.selected_slot < len(items_list): + current_item_id, _ = items_list[self.hotbar.selected_slot] + current_item = get_item(current_item_id) + + # Only place if it's placeable + if current_item and current_item.placeable: + print(f"DEBUG: Placing {current_item.name}") + self.world.place_block( + pygame.mouse.get_pos(), + self.camera, + self.player.rect, + current_item.place_tile + ) - # ========================================================== - # UPDATE - # ========================================================== def update(self, dt): - # If inventory is open, pause gameplay if self.show_inventory: return self.player.update(dt, self.world) self.camera.update() self.enemy_manager.update(dt) + self.combat_system.update(dt) + + # Check if player is dead + if self.player.health <= 0: + self.death_screen = DeathScreen(self) + self.game_state = "dead" + return + + # Enemy AI - attack player + for enemy in self.enemy_manager.enemies: + self.combat_system.enemy_attack(enemy, self.player) - # ========================================================== - # DRAW - # ========================================================== def draw(self): self.screen.fill(BACKGROUND_COLOR) @@ -117,6 +391,10 @@ class Game: if self.show_inventory: self.inventory.draw(self.screen) + # Draw hotbar + if self.hotbar and not self.show_inventory: + self.hotbar.draw(self.screen) + self.draw_ui() pygame.display.flip() @@ -137,6 +415,52 @@ class Game: ) self.screen.blit(debug_text, (10, 30)) + world_name_text = self.font.render( + f"World: {self.world_name}", + True, + (255, 255, 255) + ) + self.screen.blit(world_name_text, (10, 50)) + + weapon = self.weapon_manager.get_current_weapon() + if weapon: + weapon_text = self.font.render( + f"Weapon: {weapon.name}", + True, + (255, 255, 255) + ) + self.screen.blit(weapon_text, (10, 70)) + + # Health display + health_text = self.font.render( + f"Health: {int(self.player.health)}/{int(self.player.max_health)}", + True, + (255, 50, 50) + ) + self.screen.blit(health_text, (10, 90)) + + # Enemy count + enemy_text = self.font.render( + f"Enemies: {len(self.enemy_manager.enemies)}", + True, + (255, 100, 100) + ) + self.screen.blit(enemy_text, (10, 110)) + + # Draw currently holding item (top right) + items_list = list(self.inventory.slots.items()) + if self.hotbar and items_list: + current_item_id, current_amount = items_list[self.hotbar.selected_slot] if self.hotbar.selected_slot < len( + items_list) else (None, 0) + if current_item_id: + item = get_item(current_item_id) + if item: + holding_text = self.font.render(f"Holding: {item.name}", True, (255, 255, 255)) + self.screen.blit(holding_text, (SCREEN_WIDTH - 250, 10)) + (255, 255, 255) + ) + self.screen.blit(debug_text, (10, 30)) + if self.paused: pause_text = self.font.render("PAUSED", True, (255, 0, 0)) rect = pause_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))