from enne2engine.sdl2_wrapper import SDL2Wrapper from enne2engine.controls import UserControls import sys import os import json from Entities.Units.marine import Marine class GameEngine(UserControls): def __init__(self): super().__init__() # Load map from JSON file try: with open("assets/maps/map.json", "r") as map_file: self.map = json.load(map_file) except (FileNotFoundError, json.JSONDecodeError) as e: print(f"Error loading map file: {e}") print("Exiting program.") sys.exit(0) self.graphics = SDL2Wrapper(self) self.frame_time = 0 self.cursor_pos = (0, 0) self.load_assets() self.entities = [] self.entities_positions = {} def run(self): running = True # Set a custom scale if needed self.graphics.set_scaling_factor(1.0) # 50% scale self.entities.append(Marine("knight", 0, 0, "idle", 1, 1, self)) self.entities.append(Marine("knight", 5, 5, "idle", 1, 1, self)) #5 more marines self.entities.append(Marine("knight", 0, 5, "idle", 1, 1, self)) self.entities.append(Marine("knight", 5, 5, "idle", 1, 1, self)) self.entities.append(Marine("knight", 1,1, "idle", 1, 1, self)) self.entities.append(Marine("knight", 2,2, "idle", 1, 1, self)) self.entities.append(Marine("knight", 3,3, "idle", 1, 1, self)) while running: self.cmd_sound_effects = False # Start the frame timer perf_counter = self.graphics.get_perf_counter() # Initialize the map shadow and entities positions self.map_shadow = [ [1 for _ in range(len(self.map[0]))] for _ in range(len(self.map)) ] self.entities_positions.clear() for entity in self.entities: self.entities_positions[entity.next_cell] = entity self.entities_positions[(entity.x, entity.y)] = entity # Handle events event = self.graphics.handle_events() if event: #print(f"Event detected: {event}") if event.startswith("MOUSEDOWN"): print(f"Mouse down event: {event}") print(f"Button pressed: {event[-1]}") if event[-1] == "3": print("Right mouse button pressed") for entity in self.entities: if entity.selected: entity.set_target_cell(self.cursor_pos) elif event.startswith("SELECTION"): # Handle multiple unit selection self.select_units_in_area(event) elif event.startswith("MOUSEUP"): if event[-1] == "1": self.select_entity_at_cursor() self.handle_events("keymap_game", event) running = False if event == "QUIT" else True self.graphics.clear_screen() for entity in self.entities: entity.update() # Create the map background texture with tiles self.graphics.create_background(self.map, "tiles", self.map_shadow) self.cursor_pos = self.graphics.draw_cursor() self.graphics.render_background() self.graphics.render_sprites() self.graphics.draw_selection_rectangle() self.graphics.update_status(f"Frame time: {round(self.frame_time)}ms - FPS: {round(1000/self.frame_time if self.frame_time != 0 else 1)}") self.graphics.present_renderer() self.frame_time = self.graphics.get_frame_time(perf_counter) self.graphics.delay_frame(self.frame_time,50) self.graphics.quit() def set_cursor(self, x, y): self.graphics.cursor = (x, y) def load_assets(self): self.graphics.load_tilesheet("tiles", "assets/tiles/landscapeTiles_sheet.png") for dir in os.listdir("assets/KnightBasic"): for file in os.listdir(f"assets/KnightBasic/{dir}"): if file.endswith(".json"): self.graphics.load_spritesheet(file[:-5].lower(), f"assets/KnightBasic/{dir}/{file}") def select_entity_at_cursor(self): cursor_x, cursor_y = self.cursor_pos print(f"Cursor position: {cursor_x}, {cursor_y}") # First deselect all entities for entity in self.entities: entity.selected = False # Then select the entity at cursor position, if any entity = self.entities_positions.get((cursor_x, cursor_y)) if entity: entity.select_unit() print(f"Selected entity at cursor: {entity.asset} at position {entity.x}, {entity.y}") else: print("No entity selected at cursor position.") def select_units_in_area(self, selection_event): """Select all units within the specified selection area.""" # Parse selection coordinates _, start_x, start_y, end_x, end_y = selection_event.split(":") start_x, start_y, end_x, end_y = int(start_x), int(start_y), int(end_x), int(end_y) # Calculate selection rectangle in screen coordinates min_x = min(start_x, end_x) max_x = max(start_x, end_x) min_y = min(start_y, end_y) max_y = max(start_y, end_y) # First deselect all entities for entity in self.entities: entity.selected = False # Select entities within the rectangle for entity in self.entities: # Convert entity position to screen coordinates screen_x, screen_y = self.graphics.iso_transform(entity.x, entity.y) # Check if entity is within selection rectangle if min_x <= screen_x <= max_x and min_y <= screen_y <= max_y: entity.select_unit() print(f"Selected entity in area: {entity.asset} at position {entity.x}, {entity.y}") if __name__ == "__main__": engine = GameEngine() engine.run()