Update game.py

main
Rihards Ševčuks 2026-02-25 06:21:55 +00:00
parent c98ab47a7e
commit e07ac205b2
1 changed files with 362 additions and 38 deletions

382
game.py
View File

@ -6,38 +6,103 @@ from player import Player
from camera import Camera from camera import Camera
from inventory import Inventory from inventory import Inventory
from enemy_manager import EnemyManager 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: class Game:
def __init__(self): def __init__(self):
pygame.init() # <-- IMPORTANT pygame.init()
self.show_inventory = False
# ---------------------------------- # ----------------------------------
# Display Setup # Display Setup
# ---------------------------------- # ----------------------------------
flags = pygame.SCALED self.setup_display()
self.screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT), flags)
pygame.display.set_caption(GAME_TITLE)
self.clock = pygame.time.Clock() self.clock = pygame.time.Clock()
self.running = True self.running = True
self.paused = False self.paused = False
# ---------------------------------- # ----------------------------------
# Core Systems # Game State Management
# ---------------------------------- # ----------------------------------
self.world = World() self.game_state = "menu"
self.player = Player(100, 100) self.show_inventory = False
self.camera = Camera(self.player) self.world_name = "Default"
self.inventory = Inventory()
self.enemy_manager = EnemyManager(self.world, self.player) # ----------------------------------
# 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 # Debug
# ----------------------------------
self.font = pygame.font.SysFont("consolas", 18) 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 # MAIN LOOP
# ========================================================== # ==========================================================
@ -45,17 +110,185 @@ class Game:
while self.running: while self.running:
dt = self.clock.tick(FPS) / 1000 dt = self.clock.tick(FPS) / 1000
self.handle_events() if self.game_state == "menu":
self.handle_menu_events()
self.update_menu()
self.draw_menu()
elif self.game_state == "settings":
self.handle_settings_events()
self.settings_menu.update(dt)
self.settings_menu.draw(self.screen)
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: if not self.paused:
self.update(dt) self.update(dt)
self.draw() 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() 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): def handle_events(self):
for event in pygame.event.get(): for event in pygame.event.get():
@ -65,44 +298,85 @@ class Game:
if event.type == pygame.KEYDOWN: if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE: 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 # Toggle inventory
if event.key == pygame.K_i: if event.key == pygame.K_i:
self.show_inventory = not self.show_inventory self.show_inventory = not self.show_inventory
# ------------------------------- # Hotbar input
# Mouse input for breaking/placing if self.hotbar:
# ------------------------------- self.hotbar.handle_input(event)
# Mouse input for attacking and placing
if event.type == pygame.MOUSEBUTTONDOWN: if event.type == pygame.MOUSEBUTTONDOWN:
if self.show_inventory:
continue
if event.button == 1: # Left click if event.button == 1: # Left click
# 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)
# 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( self.world.break_block(
pygame.mouse.get_pos(), pygame.mouse.get_pos(),
self.camera, self.camera,
self.inventory self.inventory,
self.player.rect
) )
if event.button == 3: # Right click 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( self.world.place_block(
pygame.mouse.get_pos(), pygame.mouse.get_pos(),
self.camera self.camera,
self.player.rect,
current_item.place_tile
) )
# ==========================================================
# UPDATE
# ==========================================================
def update(self, dt): def update(self, dt):
# If inventory is open, pause gameplay
if self.show_inventory: if self.show_inventory:
return return
self.player.update(dt, self.world) self.player.update(dt, self.world)
self.camera.update() self.camera.update()
self.enemy_manager.update(dt) 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): def draw(self):
self.screen.fill(BACKGROUND_COLOR) self.screen.fill(BACKGROUND_COLOR)
@ -117,6 +391,10 @@ class Game:
if self.show_inventory: if self.show_inventory:
self.inventory.draw(self.screen) self.inventory.draw(self.screen)
# Draw hotbar
if self.hotbar and not self.show_inventory:
self.hotbar.draw(self.screen)
self.draw_ui() self.draw_ui()
pygame.display.flip() pygame.display.flip()
@ -137,6 +415,52 @@ class Game:
) )
self.screen.blit(debug_text, (10, 30)) 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: if self.paused:
pause_text = self.font.render("PAUSED", True, (255, 0, 0)) pause_text = self.font.render("PAUSED", True, (255, 0, 0))
rect = pause_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2)) rect = pause_text.get_rect(center=(SCREEN_WIDTH // 2, SCREEN_HEIGHT // 2))