squirrel-battle/dungeonbattle/game.py

157 lines
4.8 KiB
Python

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()
FIGHT = 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_FIGHT:
return KeyValues.FIGHT
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.FIGHT:
if self.player.fight():
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