from random import randint from typing import Any, Optional,Generator import json import os from .entities.player import Player from .enums import GameMode, KeyValues, DisplayActions from .interfaces import Map from .settings import Settings from . import menus from typing import Callable class Game: map: Map player: Player display_actions: Callable[[DisplayActions], None] def __init__(self) -> None: """ Init the game. """ self.state = GameMode.MAINMENU self.main_menu = menus.MainMenu() self.settings_menu = menus.SettingsMenu() self.settings = Settings() self.settings.load_settings() self.settings.write_settings() self.settings_menu.update_values(self.settings) def new_game(self) -> None: """ Create a new game on the screen. """ # TODO generate a new map procedurally self.map = Map.load("resources/example_map_2.txt") self.player = Player() self.map.add_entity(self.player) self.player.move(self.map.start_y, self.map.start_x) self.map.spawn_random_entities(randint(3, 10)) def run(self, screen: Any) -> None: """ Main infinite loop. We wait for a player action, then we do what that should be done when the given key got pressed. """ while True: # pragma no cover screen.clear() screen.refresh() self.display_actions(DisplayActions.REFRESH) key = screen.getkey() self.handle_key_pressed( KeyValues.translate_key(key, self.settings), key) def handle_key_pressed(self, key: Optional[KeyValues], raw_key: str = '')\ -> None: """ Indicates what should be done when the given key is pressed, according to the current game state. """ if self.state == GameMode.PLAY: self.handle_key_pressed_play(key) elif self.state == GameMode.MAINMENU: self.handle_key_pressed_main_menu(key) elif self.state == GameMode.SETTINGS: self.settings_menu.handle_key_pressed(key, raw_key, self) self.display_actions(DisplayActions.REFRESH) def handle_key_pressed_play(self, key: KeyValues) -> None: """ In play mode, arrows or zqsd should move the main character. """ if key == KeyValues.UP: if self.player.move_up(): self.map.tick() elif key == KeyValues.DOWN: if self.player.move_down(): self.map.tick() elif key == KeyValues.LEFT: if self.player.move_left(): self.map.tick() elif key == KeyValues.RIGHT: if self.player.move_right(): self.map.tick() elif key == KeyValues.SPACE: self.state = GameMode.MAINMENU def handle_key_pressed_main_menu(self, key: KeyValues) -> None: """ In the main menu, we can navigate through options. """ if key == KeyValues.DOWN: self.main_menu.go_down() if key == KeyValues.UP: self.main_menu.go_up() if key == KeyValues.ENTER: option = self.main_menu.validate() if option == menus.MainMenuValues.START: self.state = GameMode.PLAY elif option == menus.MainMenuValues.SAVE: self.save_game() elif option == menus.MainMenuValues.LOAD: self.load_game() elif option == menus.MainMenuValues.SETTINGS: self.state = GameMode.SETTINGS elif option == menus.MainMenuValues.EXIT: sys.exit(0) def game_to_str(self) -> str: d = dict() d["Map"] = game.map d["Player"] = game.player def save_state(self) -> dict(): return self.map.save_state() def load_state(self, d: dict) -> None: self.map.load_state(d) def load_game(self) -> None: """ Loads the game from a file """ if os.path.isfile("save.json"): with open("save.json", "r") as f: self.load_state(json.loads(f.read())) def save_game(self) -> None: """ Save the game to a file """ with open("save.json", "w") as f: f.write(json.dumps(self.save_state()))