Merge branch 'game' into 'master'
Menus See merge request ynerant/dungeon-battle!7
This commit is contained in:
commit
bee475c0dd
|
@ -1,45 +1,94 @@
|
||||||
|
import sys
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
from .entities.player import Player
|
from .entities.player import Player
|
||||||
from .interfaces import Map
|
from .interfaces import Map
|
||||||
from .mapdisplay import MapDisplay
|
from .mapdisplay import MapDisplay
|
||||||
from .settings import Settings
|
from .settings import Settings
|
||||||
from .term_manager import TermManager
|
from enum import Enum, auto
|
||||||
|
from . import menus
|
||||||
|
|
||||||
|
|
||||||
|
class GameMode(Enum):
|
||||||
|
MAINMENU = auto()
|
||||||
|
PLAY = auto()
|
||||||
|
SETTINGS = auto()
|
||||||
|
INVENTORY = auto()
|
||||||
|
|
||||||
|
|
||||||
|
class KeyValues(Enum):
|
||||||
|
UP = auto()
|
||||||
|
DOWN = auto()
|
||||||
|
LEFT = auto()
|
||||||
|
RIGHT = auto()
|
||||||
|
ENTER = auto()
|
||||||
|
|
||||||
|
|
||||||
class Game:
|
class Game:
|
||||||
INSTANCE = None
|
def __init__(self) -> None:
|
||||||
|
self.state = GameMode.MAINMENU
|
||||||
def init(self) -> None:
|
self.main_menu = menus.MainMenu()
|
||||||
Game.INSTANCE = self
|
|
||||||
self.settings = Settings()
|
self.settings = Settings()
|
||||||
self.settings.load_settings()
|
self.settings.load_settings()
|
||||||
self.settings.write_settings()
|
self.settings.write_settings()
|
||||||
with TermManager() as term_manager:
|
|
||||||
self._start_game(term_manager.screen)
|
|
||||||
|
|
||||||
def _start_game(self, screen: Any) -> None:
|
def new_game(self, init_pad: bool = True) -> None:
|
||||||
# TODO Generate map, or make the possibility to load another one
|
# TODO generate a new map procedurally
|
||||||
m = Map.load("example_map.txt")
|
self.m = Map.load("example_map.txt")
|
||||||
player = Player()
|
self.player = Player()
|
||||||
self.player = player
|
self.player.move(1, 6)
|
||||||
m.add_entity(player)
|
self.m.add_entity(self.player)
|
||||||
player.move(1, 6)
|
self.d = MapDisplay(self.m, self.player, init_pad)
|
||||||
d = MapDisplay(m, player)
|
|
||||||
|
@staticmethod
|
||||||
|
def load_game(filename: str) -> None:
|
||||||
|
# TODO loading map from a file
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
def run(self, screen: Any) -> None:
|
||||||
while True:
|
while True:
|
||||||
screen.clear()
|
screen.clear()
|
||||||
screen.refresh()
|
screen.refresh()
|
||||||
d.display(player.y, player.y)
|
self.d.display(self.player.y, self.player.x)
|
||||||
key = screen.getkey()
|
key = screen.getkey()
|
||||||
self.handle_key_pressed(key)
|
self.handle_key_pressed(self.translate_key(key))
|
||||||
|
|
||||||
def handle_key_pressed(self, key: str) -> None:
|
def translate_key(self, key: str) -> KeyValues:
|
||||||
# TODO load keys from settings
|
if key in (self.settings.KEY_DOWN_SECONDARY,
|
||||||
if key == 'z' or key == 'KEY_UP':
|
self.settings.KEY_DOWN_PRIMARY):
|
||||||
self.player.move_up()
|
return KeyValues.DOWN
|
||||||
if key == 's' or key == 'KEY_DOWN':
|
elif key in (self.settings.KEY_LEFT_PRIMARY,
|
||||||
self.player.move_down()
|
self.settings.KEY_LEFT_SECONDARY):
|
||||||
if key == 'q' or key == 'KEY_LEFT':
|
return KeyValues.LEFT
|
||||||
self.player.move_left()
|
elif key in (self.settings.KEY_RIGHT_PRIMARY,
|
||||||
if key == 'd' or key == 'KEY_RIGHT':
|
self.settings.KEY_RIGHT_SECONDARY):
|
||||||
self.player.move_right()
|
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
|
||||||
|
|
||||||
|
def handle_key_pressed(self, key: KeyValues) -> None:
|
||||||
|
if self.state == GameMode.PLAY:
|
||||||
|
if key == KeyValues.UP:
|
||||||
|
self.player.move_up()
|
||||||
|
if key == KeyValues.DOWN:
|
||||||
|
self.player.move_down()
|
||||||
|
if key == KeyValues.LEFT:
|
||||||
|
self.player.move_left()
|
||||||
|
if key == KeyValues.RIGHT:
|
||||||
|
self.player.move_right()
|
||||||
|
if self.state == GameMode.MAINMENU:
|
||||||
|
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)
|
||||||
|
|
|
@ -6,10 +6,11 @@ from dungeonbattle.interfaces import Map
|
||||||
|
|
||||||
|
|
||||||
class MapDisplay:
|
class MapDisplay:
|
||||||
def __init__(self, m: Map, player: Player):
|
def __init__(self, m: Map, player: Player, init_pad: bool = True):
|
||||||
self.map = m
|
self.map = m
|
||||||
self.pad = curses.newpad(m.height, m.width + 1)
|
|
||||||
self.player = player
|
self.player = player
|
||||||
|
if init_pad:
|
||||||
|
self.pad = curses.newpad(m.height, m.width + 1)
|
||||||
|
|
||||||
def update_pad(self) -> None:
|
def update_pad(self) -> None:
|
||||||
self.pad.addstr(0, 0, self.map.draw_string())
|
self.pad.addstr(0, 0, self.map.draw_string())
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
from enum import Enum, auto
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
class Menu:
|
||||||
|
values: list
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.position = 0
|
||||||
|
|
||||||
|
def go_up(self) -> None:
|
||||||
|
self.position = max(0, self.position - 1)
|
||||||
|
|
||||||
|
def go_down(self) -> None:
|
||||||
|
self.position = min(len(self.values) - 1, self.position + 1)
|
||||||
|
|
||||||
|
def validate(self) -> Any:
|
||||||
|
return self.values[self.position]
|
||||||
|
|
||||||
|
|
||||||
|
class MainMenuValues(Enum):
|
||||||
|
START = auto()
|
||||||
|
SETTINGS = auto()
|
||||||
|
EXIT = auto()
|
||||||
|
|
||||||
|
|
||||||
|
class MainMenu(Menu):
|
||||||
|
values = [e for e in MainMenuValues]
|
||||||
|
|
||||||
|
|
||||||
|
class ArbitraryMenu(Menu):
|
||||||
|
def __init__(self, values: list):
|
||||||
|
super().__init__()
|
||||||
|
self.values = values
|
|
@ -27,6 +27,8 @@ class Settings:
|
||||||
['d', 'Touche principale pour aller vers la droite']
|
['d', 'Touche principale pour aller vers la droite']
|
||||||
self.KEY_RIGHT_SECONDARY = \
|
self.KEY_RIGHT_SECONDARY = \
|
||||||
['KEY_RIGHT', 'Touche secondaire pour aller vers la droite']
|
['KEY_RIGHT', 'Touche secondaire pour aller vers la droite']
|
||||||
|
self.KEY_ENTER = \
|
||||||
|
['\n', 'Touche pour valider un menu']
|
||||||
self.TEXTURE_PACK = ['ASCII', 'Pack de textures utilisé']
|
self.TEXTURE_PACK = ['ASCII', 'Pack de textures utilisé']
|
||||||
|
|
||||||
def __getattribute__(self, item: str) -> Any:
|
def __getattribute__(self, item: str) -> Any:
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from dungeonbattle.game import Game, KeyValues, GameMode
|
||||||
|
from dungeonbattle.menus import MainMenuValues
|
||||||
|
|
||||||
|
|
||||||
|
class TestGame(unittest.TestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
"""
|
||||||
|
Setup game.
|
||||||
|
"""
|
||||||
|
self.game = Game()
|
||||||
|
self.game.new_game(False)
|
||||||
|
|
||||||
|
def test_load_game(self) -> None:
|
||||||
|
self.assertRaises(NotImplementedError, Game.load_game, "game.save")
|
||||||
|
|
||||||
|
def test_key_translation(self) -> None:
|
||||||
|
"""
|
||||||
|
Test key bindings.
|
||||||
|
"""
|
||||||
|
self.assertEqual(self.game.translate_key(
|
||||||
|
self.game.settings.KEY_UP_PRIMARY), KeyValues.UP)
|
||||||
|
self.assertEqual(self.game.translate_key(
|
||||||
|
self.game.settings.KEY_UP_SECONDARY), KeyValues.UP)
|
||||||
|
self.assertEqual(self.game.translate_key(
|
||||||
|
self.game.settings.KEY_DOWN_PRIMARY), KeyValues.DOWN)
|
||||||
|
self.assertEqual(self.game.translate_key(
|
||||||
|
self.game.settings.KEY_DOWN_SECONDARY), KeyValues.DOWN)
|
||||||
|
self.assertEqual(self.game.translate_key(
|
||||||
|
self.game.settings.KEY_LEFT_PRIMARY), KeyValues.LEFT)
|
||||||
|
self.assertEqual(self.game.translate_key(
|
||||||
|
self.game.settings.KEY_LEFT_SECONDARY), KeyValues.LEFT)
|
||||||
|
self.assertEqual(self.game.translate_key(
|
||||||
|
self.game.settings.KEY_RIGHT_PRIMARY), KeyValues.RIGHT)
|
||||||
|
self.assertEqual(self.game.translate_key(
|
||||||
|
self.game.settings.KEY_RIGHT_SECONDARY), KeyValues.RIGHT)
|
||||||
|
self.assertEqual(self.game.translate_key(
|
||||||
|
self.game.settings.KEY_ENTER), KeyValues.ENTER)
|
||||||
|
|
||||||
|
def test_key_press(self) -> None:
|
||||||
|
"""
|
||||||
|
Press a key and see what is done.
|
||||||
|
"""
|
||||||
|
self.assertEqual(self.game.state, GameMode.MAINMENU)
|
||||||
|
self.assertEqual(self.game.main_menu.validate(),
|
||||||
|
MainMenuValues.START)
|
||||||
|
self.game.handle_key_pressed(KeyValues.UP)
|
||||||
|
self.assertEqual(self.game.main_menu.validate(),
|
||||||
|
MainMenuValues.START)
|
||||||
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
||||||
|
self.assertEqual(self.game.main_menu.validate(),
|
||||||
|
MainMenuValues.SETTINGS)
|
||||||
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
||||||
|
self.assertEqual(self.game.state, GameMode.SETTINGS)
|
||||||
|
|
||||||
|
self.game.state = GameMode.MAINMENU
|
||||||
|
|
||||||
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
||||||
|
self.assertEqual(self.game.main_menu.validate(),
|
||||||
|
MainMenuValues.EXIT)
|
||||||
|
self.assertRaises(SystemExit, self.game.handle_key_pressed,
|
||||||
|
KeyValues.ENTER)
|
||||||
|
|
||||||
|
self.game.handle_key_pressed(KeyValues.UP)
|
||||||
|
self.assertEqual(self.game.main_menu.validate(),
|
||||||
|
MainMenuValues.SETTINGS)
|
||||||
|
self.game.handle_key_pressed(KeyValues.UP)
|
||||||
|
self.assertEqual(self.game.main_menu.validate(),
|
||||||
|
MainMenuValues.START)
|
||||||
|
|
||||||
|
self.game.handle_key_pressed(KeyValues.ENTER)
|
||||||
|
self.assertEqual(self.game.state, GameMode.PLAY)
|
||||||
|
|
||||||
|
y, x = self.game.player.y, self.game.player.x
|
||||||
|
self.game.handle_key_pressed(KeyValues.DOWN)
|
||||||
|
new_y, new_x = self.game.player.y, self.game.player.x
|
||||||
|
self.assertEqual(new_y, y + 1)
|
||||||
|
self.assertEqual(new_x, x)
|
||||||
|
|
||||||
|
y, x = new_y, new_x
|
||||||
|
self.game.handle_key_pressed(KeyValues.RIGHT)
|
||||||
|
new_y, new_x = self.game.player.y, self.game.player.x
|
||||||
|
self.assertEqual(new_y, y)
|
||||||
|
self.assertEqual(new_x, x + 1)
|
||||||
|
|
||||||
|
y, x = self.game.player.y, self.game.player.x
|
||||||
|
self.game.handle_key_pressed(KeyValues.UP)
|
||||||
|
new_y, new_x = self.game.player.y, self.game.player.x
|
||||||
|
self.assertEqual(new_y, y - 1)
|
||||||
|
self.assertEqual(new_x, x)
|
||||||
|
|
||||||
|
y, x = self.game.player.y, self.game.player.x
|
||||||
|
self.game.handle_key_pressed(KeyValues.LEFT)
|
||||||
|
new_y, new_x = self.game.player.y, self.game.player.x
|
||||||
|
self.assertEqual(new_y, y)
|
||||||
|
self.assertEqual(new_x, x - 1)
|
|
@ -0,0 +1,24 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from dungeonbattle.menus import ArbitraryMenu, MainMenu, MainMenuValues
|
||||||
|
|
||||||
|
|
||||||
|
class TestMenus(unittest.TestCase):
|
||||||
|
def test_scroll_menu(self) -> None:
|
||||||
|
"""
|
||||||
|
Test to scroll the menu.
|
||||||
|
"""
|
||||||
|
arbitrary_menu = ArbitraryMenu([])
|
||||||
|
self.assertEqual(arbitrary_menu.position, 0)
|
||||||
|
|
||||||
|
main_menu = MainMenu()
|
||||||
|
self.assertEqual(main_menu.position, 0)
|
||||||
|
self.assertEqual(main_menu.validate(), MainMenuValues.START)
|
||||||
|
main_menu.go_up()
|
||||||
|
self.assertEqual(main_menu.validate(), MainMenuValues.START)
|
||||||
|
main_menu.go_down()
|
||||||
|
self.assertEqual(main_menu.validate(), MainMenuValues.SETTINGS)
|
||||||
|
main_menu.go_down()
|
||||||
|
self.assertEqual(main_menu.validate(), MainMenuValues.EXIT)
|
||||||
|
main_menu.go_down()
|
||||||
|
self.assertEqual(main_menu.validate(), MainMenuValues.EXIT)
|
|
@ -0,0 +1,8 @@
|
||||||
|
# This is the base ascii texturepack
|
||||||
|
|
||||||
|
ascii = {
|
||||||
|
"EMPTY": ' ',
|
||||||
|
"WALL": '#',
|
||||||
|
"FLOOR": '.',
|
||||||
|
"PLAYER": '@'
|
||||||
|
}
|
6
main.py
6
main.py
|
@ -1,5 +1,9 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
from dungeonbattle.game import Game
|
from dungeonbattle.game import Game
|
||||||
|
from dungeonbattle.term_manager import TermManager
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
Game().init()
|
with TermManager() as term_manager:
|
||||||
|
game = Game()
|
||||||
|
game.new_game()
|
||||||
|
game.run(term_manager.screen)
|
||||||
|
|
Loading…
Reference in New Issue