Merge branch 'game' into 'master'
Menus See merge request ynerant/dungeon-battle!7
This commit was merged in pull request #88.
	This commit is contained in:
		@@ -1,45 +1,94 @@
 | 
			
		||||
import sys
 | 
			
		||||
from typing import Any
 | 
			
		||||
 | 
			
		||||
from .entities.player import Player
 | 
			
		||||
from .interfaces import Map
 | 
			
		||||
from .mapdisplay import MapDisplay
 | 
			
		||||
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:
 | 
			
		||||
    INSTANCE = None
 | 
			
		||||
 | 
			
		||||
    def init(self) -> None:
 | 
			
		||||
        Game.INSTANCE = self
 | 
			
		||||
    def __init__(self) -> None:
 | 
			
		||||
        self.state = GameMode.MAINMENU
 | 
			
		||||
        self.main_menu = menus.MainMenu()
 | 
			
		||||
        self.settings = Settings()
 | 
			
		||||
        self.settings.load_settings()
 | 
			
		||||
        self.settings.write_settings()
 | 
			
		||||
        with TermManager() as term_manager:
 | 
			
		||||
            self._start_game(term_manager.screen)
 | 
			
		||||
 | 
			
		||||
    def _start_game(self, screen: Any) -> None:
 | 
			
		||||
        # TODO Generate map, or make the possibility to load another one
 | 
			
		||||
        m = Map.load("example_map.txt")
 | 
			
		||||
        player = Player()
 | 
			
		||||
        self.player = player
 | 
			
		||||
        m.add_entity(player)
 | 
			
		||||
        player.move(1, 6)
 | 
			
		||||
        d = MapDisplay(m, player)
 | 
			
		||||
    def new_game(self, init_pad: bool = True) -> None:
 | 
			
		||||
        # TODO generate a new map procedurally
 | 
			
		||||
        self.m = Map.load("example_map.txt")
 | 
			
		||||
        self.player = Player()
 | 
			
		||||
        self.player.move(1, 6)
 | 
			
		||||
        self.m.add_entity(self.player)
 | 
			
		||||
        self.d = MapDisplay(self.m, self.player, init_pad)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def load_game(filename: str) -> None:
 | 
			
		||||
        # TODO loading map from a file
 | 
			
		||||
        raise NotImplementedError()
 | 
			
		||||
 | 
			
		||||
    def run(self, screen: Any) -> None:
 | 
			
		||||
        while True:
 | 
			
		||||
            screen.clear()
 | 
			
		||||
            screen.refresh()
 | 
			
		||||
            d.display(player.y, player.y)
 | 
			
		||||
            self.d.display(self.player.y, self.player.x)
 | 
			
		||||
            key = screen.getkey()
 | 
			
		||||
            self.handle_key_pressed(key)
 | 
			
		||||
            self.handle_key_pressed(self.translate_key(key))
 | 
			
		||||
 | 
			
		||||
    def handle_key_pressed(self, key: str) -> None:
 | 
			
		||||
        # TODO load keys from settings
 | 
			
		||||
        if key == 'z' or key == 'KEY_UP':
 | 
			
		||||
            self.player.move_up()
 | 
			
		||||
        if key == 's' or key == 'KEY_DOWN':
 | 
			
		||||
            self.player.move_down()
 | 
			
		||||
        if key == 'q' or key == 'KEY_LEFT':
 | 
			
		||||
            self.player.move_left()
 | 
			
		||||
        if key == 'd' or key == 'KEY_RIGHT':
 | 
			
		||||
            self.player.move_right()
 | 
			
		||||
    def translate_key(self, key: str) -> KeyValues:
 | 
			
		||||
        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
 | 
			
		||||
 | 
			
		||||
    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:
 | 
			
		||||
    def __init__(self, m: Map, player: Player):
 | 
			
		||||
    def __init__(self, m: Map, player: Player, init_pad: bool = True):
 | 
			
		||||
        self.map = m
 | 
			
		||||
        self.pad = curses.newpad(m.height, m.width + 1)
 | 
			
		||||
        self.player = player
 | 
			
		||||
        if init_pad:
 | 
			
		||||
            self.pad = curses.newpad(m.height, m.width + 1)
 | 
			
		||||
 | 
			
		||||
    def update_pad(self) -> None:
 | 
			
		||||
        self.pad.addstr(0, 0, self.map.draw_string())
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										34
									
								
								dungeonbattle/menus.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								dungeonbattle/menus.py
									
									
									
									
									
										Normal file
									
								
							@@ -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']
 | 
			
		||||
        self.KEY_RIGHT_SECONDARY = \
 | 
			
		||||
            ['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é']
 | 
			
		||||
 | 
			
		||||
    def __getattribute__(self, item: str) -> Any:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										97
									
								
								dungeonbattle/tests/game_test.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								dungeonbattle/tests/game_test.py
									
									
									
									
									
										Normal file
									
								
							@@ -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)
 | 
			
		||||
							
								
								
									
										24
									
								
								dungeonbattle/tests/menus_test.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								dungeonbattle/tests/menus_test.py
									
									
									
									
									
										Normal file
									
								
							@@ -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)
 | 
			
		||||
							
								
								
									
										8
									
								
								dungeonbattle/texturepack.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								dungeonbattle/texturepack.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
# This is the base ascii texturepack
 | 
			
		||||
 | 
			
		||||
ascii = {
 | 
			
		||||
    "EMPTY": ' ',
 | 
			
		||||
    "WALL": '#',
 | 
			
		||||
    "FLOOR": '.',
 | 
			
		||||
    "PLAYER": '@'
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user