import sys from random import randint from typing import Any from .entities.player import Player from .interfaces import Map from .settings import Settings from enum import Enum, auto from . import menus from typing import Callable class GameMode(Enum): MAINMENU = auto() PLAY = auto() SETTINGS = auto() INVENTORY = auto() class KeyValues(Enum): UP = auto() DOWN = auto() LEFT = auto() RIGHT = auto() ENTER = auto() SPACE = auto() class Game: map: Map player: Player display_refresh: Callable[[], None] def __init__(self) -> None: """ Init the game. """ self.state = GameMode.MAINMENU self.main_menu = menus.MainMenu() self.settings = Settings() self.settings.load_settings() self.settings.write_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.txt") self.map.currenty = 1 self.map.currentx = 6 self.player = Player() self.map.add_entity(self.player) self.player.move(1, 6) self.map.spawn_random_entities(randint(1, 5)) @staticmethod def load_game(filename: str) -> None: # TODO loading map from a file raise NotImplementedError() 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: screen.clear() screen.refresh() self.display_refresh() key = screen.getkey() self.handle_key_pressed(self.translate_key(key)) def translate_key(self, key: str) -> KeyValues: """ Translate the raw string key into an enum value that we can use. """ if key in (self.settings.KEY_DOWN_SECONDARY, self.settings.KEY_DOWN_PRIMARY): return KeyValues.DOWN elif key in (self.settings.KEY_LEFT_PRIMARY, self.settings.KEY_LEFT_SECONDARY): return KeyValues.LEFT elif key in (self.settings.KEY_RIGHT_PRIMARY, self.settings.KEY_RIGHT_SECONDARY): return KeyValues.RIGHT elif key in (self.settings.KEY_UP_PRIMARY, self.settings.KEY_UP_SECONDARY): return KeyValues.UP elif key == self.settings.KEY_ENTER: return KeyValues.ENTER elif key == ' ': return KeyValues.SPACE def handle_key_pressed(self, key: KeyValues) -> 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.handle_key_pressed_settings(key) self.display_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.SETTINGS: self.state = GameMode.SETTINGS elif option == menus.MainMenuValues.EXIT: sys.exit(0) def handle_key_pressed_settings(self, key: KeyValues) -> None: """ For now, in the settings mode, we can only go backwards. """ if key == KeyValues.SPACE: self.state = GameMode.MAINMENU