Merge remote-tracking branch 'origin/master' into display
# Conflicts: # dungeonbattle/entities/player.py # dungeonbattle/game.py # dungeonbattle/interfaces.py # dungeonbattle/mapdisplay.py # dungeonbattle/settings.py # dungeonbattle/tests/settings_test.py # dungeonbattle/texturepack.py
This commit is contained in:
commit
02d3394439
|
@ -1,33 +1,36 @@
|
||||||
from ..interfaces import Entity, FightingEntity
|
from ..interfaces import Entity, FightingEntity, Map
|
||||||
|
|
||||||
|
|
||||||
class Item(Entity):
|
class Item(Entity):
|
||||||
held:bool
|
held: bool
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(self, *args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.held = False
|
self.held = False
|
||||||
|
|
||||||
def drop(self, x:int, y:int):
|
def drop(self, y: int, x: int) -> None:
|
||||||
self.held = False
|
self.held = False
|
||||||
self.move(x, y)
|
self.move(y, x)
|
||||||
|
|
||||||
def hold(self):
|
def hold(self) -> None:
|
||||||
self.held = True
|
self.held = True
|
||||||
|
|
||||||
|
|
||||||
class Bomb(Item):
|
class Bomb(Item):
|
||||||
damage:int = 5
|
damage: int = 5
|
||||||
exploding:bool
|
exploding: bool
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
super().__init__(self, *args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.exploding = False
|
self.exploding = False
|
||||||
|
|
||||||
def drop(self, x:int, y:int):
|
def drop(self, x: int, y: int) -> None:
|
||||||
super.drop(self, x, y)
|
super().drop(x, y)
|
||||||
self.exploding = True
|
self.exploding = True
|
||||||
|
|
||||||
def act(self, map):
|
def act(self, m: Map) -> None:
|
||||||
if self.exploding:
|
if self.exploding:
|
||||||
for e in map.entities:
|
for e in m.entities:
|
||||||
if abs (e.x - self.x) + abs (e.y - self.y) <= 1 and isinstance(e,FightingEntity):
|
if abs(e.x - self.x) + abs(e.y - self.y) <= 1 and \
|
||||||
|
isinstance(e, FightingEntity):
|
||||||
e.take_damage(self, self.damage)
|
e.take_damage(self, self.damage)
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
from ..interfaces import FightingEntity
|
from ..interfaces import FightingEntity, Map
|
||||||
|
|
||||||
|
|
||||||
class Monster(FightingEntity):
|
class Monster(FightingEntity):
|
||||||
def act(self, map):
|
def act(self, m: Map) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Squirrel(Monster):
|
class Squirrel(Monster):
|
||||||
maxhealth = 10
|
maxhealth = 10
|
||||||
strength = 3
|
strength = 3
|
||||||
|
|
|
@ -1,9 +1,22 @@
|
||||||
from ..interfaces import FightingEntity
|
from ..interfaces import FightingEntity
|
||||||
|
|
||||||
|
|
||||||
class Player(FightingEntity):
|
class Player(FightingEntity):
|
||||||
maxhealth = 20
|
maxhealth = 20
|
||||||
strength = 5
|
strength = 5
|
||||||
|
|
||||||
|
def move_up(self) -> bool:
|
||||||
|
return self.check_move(self.y - 1, self.x, True)
|
||||||
|
|
||||||
|
def move_down(self) -> bool:
|
||||||
|
return self.check_move(self.y + 1, self.x, True)
|
||||||
|
|
||||||
|
def move_left(self) -> bool:
|
||||||
|
return self.check_move(self.y, self.x - 1, True)
|
||||||
|
|
||||||
|
def move_right(self) -> bool:
|
||||||
|
return self.check_move(self.y, self.x + 1, True)
|
||||||
|
|
||||||
currentXP: int
|
currentXP: int
|
||||||
maxXP: int
|
maxXP: int
|
||||||
|
|
||||||
|
|
|
@ -1,71 +1,94 @@
|
||||||
|
import sys
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
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()
|
||||||
self.key_handler = self.player_move
|
|
||||||
|
|
||||||
def new_game(self):
|
def new_game(self, init_pad: bool = True) -> None:
|
||||||
# TODO generate a new map procedurally
|
# TODO generate a new map procedurally
|
||||||
self.m = Map.load("example_map.txt")
|
self.m = Map.load("example_map.txt")
|
||||||
self.d = MapDisplay(self.m)
|
|
||||||
self.player = Player()
|
self.player = Player()
|
||||||
self.player.y = 1
|
self.player.move(1, 6)
|
||||||
self.player.x = 6
|
self.m.add_entity(self.player)
|
||||||
|
self.d = MapDisplay(self.m, self.player, init_pad)
|
||||||
|
|
||||||
@classmethod
|
@staticmethod
|
||||||
def load_game(filename):
|
def load_game(filename: str) -> None:
|
||||||
# TODO loading map from a file
|
# TODO loading map from a file
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def run(self, screen):
|
def run(self, screen: Any) -> None:
|
||||||
while True:
|
while True:
|
||||||
screen.clear()
|
screen.clear()
|
||||||
screen.refresh()
|
screen.refresh()
|
||||||
self.d.display(self.player.getPosY(), self.player.getPosX())
|
self.d.display(self.player.y, self.player.x)
|
||||||
key = screen.getkey()
|
key = screen.getkey()
|
||||||
self.key_handler(key)
|
self.handle_key_pressed(self.translate_key(key))
|
||||||
|
|
||||||
def player_move(self, key):
|
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:
|
||||||
class Player:
|
if self.state == GameMode.PLAY:
|
||||||
# FIXME Should be elsewhere, only useful to don't break the previous code
|
if key == KeyValues.UP:
|
||||||
y: int = 0
|
self.player.move_up()
|
||||||
x: int = 0
|
if key == KeyValues.DOWN:
|
||||||
|
self.player.move_down()
|
||||||
def move_up(self):
|
if key == KeyValues.LEFT:
|
||||||
self.y -= 1
|
self.player.move_left()
|
||||||
|
if key == KeyValues.RIGHT:
|
||||||
def move_down(self):
|
self.player.move_right()
|
||||||
self.y += 1
|
if self.state == GameMode.MAINMENU:
|
||||||
|
if key == KeyValues.DOWN:
|
||||||
def move_left(self):
|
self.main_menu.go_down()
|
||||||
self.x -= 1
|
if key == KeyValues.UP:
|
||||||
|
self.main_menu.go_up()
|
||||||
def move_right(self):
|
if key == KeyValues.ENTER:
|
||||||
self.x += 1
|
option = self.main_menu.validate()
|
||||||
|
if option == menus.MainMenuValues.START:
|
||||||
def getPosX(self):
|
self.state = GameMode.PLAY
|
||||||
return self.x
|
elif option == menus.MainMenuValues.SETTINGS:
|
||||||
|
self.state = GameMode.SETTINGS
|
||||||
def getPosY(self):
|
elif option == menus.MainMenuValues.EXIT:
|
||||||
return self.y
|
sys.exit(0)
|
||||||
|
|
|
@ -13,13 +13,20 @@ class Map:
|
||||||
height: int
|
height: int
|
||||||
tiles: list
|
tiles: list
|
||||||
currentx : int #coordinates of the point that should be on the topleft corner of the screen
|
currentx : int #coordinates of the point that should be on the topleft corner of the screen
|
||||||
currenty : int
|
currenty : int
|
||||||
|
|
||||||
def __init__(self, width: int, height: int, tiles: list, entities = []):
|
def __init__(self, width: int, height: int, tiles: list):
|
||||||
self.width = width
|
self.width = width
|
||||||
self.height = height
|
self.height = height
|
||||||
self.tiles = tiles
|
self.tiles = tiles
|
||||||
self.entities = entities
|
self.entities = []
|
||||||
|
|
||||||
|
def add_entity(self, entity: "Entity") -> None:
|
||||||
|
"""
|
||||||
|
Register a new entity in the map.
|
||||||
|
"""
|
||||||
|
self.entities.append(entity)
|
||||||
|
entity.map = self
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load(filename: str):
|
def load(filename: str):
|
||||||
|
@ -42,8 +49,7 @@ class Map:
|
||||||
tiles = [[Tile(c)
|
tiles = [[Tile(c)
|
||||||
for x, c in enumerate(line)] for y, line in enumerate(lines)]
|
for x, c in enumerate(line)] for y, line in enumerate(lines)]
|
||||||
|
|
||||||
return Map(width, height, tiles, [])
|
return Map(width, height, tiles)
|
||||||
|
|
||||||
|
|
||||||
def draw_string(self, pack: TexturePack) -> str:
|
def draw_string(self, pack: TexturePack) -> str:
|
||||||
"""
|
"""
|
||||||
|
@ -73,21 +79,39 @@ class Tile(Enum):
|
||||||
|
|
||||||
|
|
||||||
class Entity:
|
class Entity:
|
||||||
x: int
|
|
||||||
y: int
|
y: int
|
||||||
|
x: int
|
||||||
name : str
|
name : str
|
||||||
|
map: Map
|
||||||
|
|
||||||
def move(self, x: int, y: int) -> None:
|
def __init__(self):
|
||||||
self.x = x
|
self.y = 0
|
||||||
|
self.x = 0
|
||||||
|
|
||||||
|
def check_move(self, y: int, x: int, move_if_possible: bool = False)\
|
||||||
|
-> bool:
|
||||||
|
tile = self.map.tiles[y][x]
|
||||||
|
if tile.can_walk() and move_if_possible:
|
||||||
|
self.move(y, x)
|
||||||
|
return tile.can_walk()
|
||||||
|
|
||||||
|
def move(self, y: int, x: int) -> None:
|
||||||
self.y = y
|
self.y = y
|
||||||
|
self.x = x
|
||||||
def act(self, m:Map):
|
|
||||||
|
def act(self, m: Map) -> None:
|
||||||
|
"""
|
||||||
|
Define the action of the entity that is ran each tick.
|
||||||
|
By default, does nothing.
|
||||||
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class FightingEntity(Entity):
|
class FightingEntity(Entity):
|
||||||
maxhealth: int
|
maxhealth: int
|
||||||
health: int
|
health: int
|
||||||
strength: int
|
strength: int
|
||||||
|
dead: bool
|
||||||
intelligence: int
|
intelligence: int
|
||||||
charisma: int
|
charisma: int
|
||||||
dexterity: int
|
dexterity: int
|
||||||
|
@ -95,15 +119,17 @@ class FightingEntity(Entity):
|
||||||
level: int
|
level: int
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
self.health = self.maxhealth
|
self.health = self.maxhealth
|
||||||
|
self.dead = False
|
||||||
|
|
||||||
def hit(self, opponent) -> None:
|
def hit(self, opponent: "FightingEntity") -> None:
|
||||||
opponent.take_damage(self, self.strength)
|
opponent.take_damage(self, self.strength)
|
||||||
|
|
||||||
def take_damage(self, attacker, amount:int) -> None:
|
def take_damage(self, attacker: "Entity", amount: int) -> None:
|
||||||
self.health -= amount
|
self.health -= amount
|
||||||
if self.health <= 0:
|
if self.health <= 0:
|
||||||
self.die()
|
self.die()
|
||||||
|
|
||||||
def die(self) -> None:
|
def die(self) -> None:
|
||||||
pass
|
self.dead = True
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
import unittest
|
|
||||||
|
|
||||||
from dungeonbattle.interfaces import Map
|
|
||||||
|
|
||||||
|
|
||||||
class TestInterfaces(unittest.TestCase):
|
|
||||||
def test_map(self) -> None:
|
|
||||||
"""
|
|
||||||
Create a map and check that it is well parsed.
|
|
||||||
"""
|
|
||||||
m = Map.load_from_string(".█\n█.\n")
|
|
||||||
self.assertEqual(m.width, 2)
|
|
||||||
self.assertEqual(m.height, 2)
|
|
||||||
self.assertEqual(m.draw_string(), ".█\n█.")
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
import curses
|
||||||
|
|
||||||
|
from dungeonbattle.entities.player import Player
|
||||||
|
from dungeonbattle.interfaces import Map
|
||||||
|
|
||||||
|
|
||||||
|
class MapDisplay:
|
||||||
|
def __init__(self, m: Map, player: Player, init_pad: bool = True):
|
||||||
|
self.map = m
|
||||||
|
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())
|
||||||
|
# TODO Not all entities should be a player
|
||||||
|
for e in self.map.entities:
|
||||||
|
self.pad.addstr(e.y, e.x, '🐿')
|
||||||
|
|
||||||
|
def display(self, y: int, x: int) -> None:
|
||||||
|
deltay, deltax = (curses.LINES // 2) + 1, (curses.COLS // 2) + 1
|
||||||
|
pminrow, pmincol = y - deltay, x - deltax
|
||||||
|
sminrow, smincol = max(-pminrow, 0), max(-pmincol, 0)
|
||||||
|
deltay, deltax = curses.LINES - deltay, curses.COLS - deltax
|
||||||
|
smaxrow = self.map.height - (y + deltay) + curses.LINES - 1
|
||||||
|
smaxrow = min(smaxrow, curses.LINES - 1)
|
||||||
|
smaxcol = self.map.width - (x + deltax) + curses.COLS - 1
|
||||||
|
smaxcol = min(smaxcol, curses.COLS - 1)
|
||||||
|
pminrow = max(0, min(self.map.height, pminrow))
|
||||||
|
pmincol = max(0, min(self.map.width, pmincol))
|
||||||
|
self.pad.clear()
|
||||||
|
self.update_pad()
|
||||||
|
self.pad.refresh(pminrow, pmincol, sminrow, smincol, smaxrow, smaxcol)
|
|
@ -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
|
|
@ -11,14 +11,24 @@ class Settings:
|
||||||
We can define the setting by simply use settings.TEXTURE_PACK = 'new_key'
|
We can define the setting by simply use settings.TEXTURE_PACK = 'new_key'
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.KEY_UP_PRIMARY = ['z', 'Touche principale pour aller vers le haut']
|
self.KEY_UP_PRIMARY = \
|
||||||
self.KEY_UP_SECONDARY = ['KEY_UP', 'Touche secondaire pour aller vers le haut']
|
['z', 'Touche principale pour aller vers le haut']
|
||||||
self.KEY_DOWN_PRIMARY = ['s', 'Touche principale pour aller vers le bas']
|
self.KEY_UP_SECONDARY = \
|
||||||
self.KEY_DOWN_SECONDARY = ['KEY_DOWN', 'Touche secondaire pour aller vers le bas']
|
['KEY_UP', 'Touche secondaire pour aller vers le haut']
|
||||||
self.KEY_LEFT_PRIMARY = ['q', 'Touche principale pour aller vers la gauche']
|
self.KEY_DOWN_PRIMARY = \
|
||||||
self.KEY_LEFT_SECONDARY = ['KEY_LEFT', 'Touche secondaire pour aller vers la gauche']
|
['s', 'Touche principale pour aller vers le bas']
|
||||||
self.KEY_RIGHT_PRIMARY = ['d', 'Touche principale pour aller vers la droite']
|
self.KEY_DOWN_SECONDARY = \
|
||||||
self.KEY_RIGHT_SECONDARY = ['KEY_RIGHT', 'Touche secondaire pour aller vers la droite']
|
['KEY_DOWN', 'Touche secondaire pour aller vers le bas']
|
||||||
|
self.KEY_LEFT_PRIMARY = \
|
||||||
|
['q', 'Touche principale pour aller vers la gauche']
|
||||||
|
self.KEY_LEFT_SECONDARY = \
|
||||||
|
['KEY_LEFT', 'Touche secondaire pour aller vers la gauche']
|
||||||
|
self.KEY_RIGHT_PRIMARY = \
|
||||||
|
['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é']
|
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.entities.items import Bomb, Item
|
||||||
|
from dungeonbattle.entities.monsters import Squirrel
|
||||||
|
from dungeonbattle.entities.player import Player
|
||||||
|
from dungeonbattle.interfaces import Entity, Map
|
||||||
|
|
||||||
|
|
||||||
|
class TestEntities(unittest.TestCase):
|
||||||
|
def setUp(self) -> None:
|
||||||
|
"""
|
||||||
|
Load example map that can be used in tests.
|
||||||
|
"""
|
||||||
|
self.map = Map.load("example_map.txt")
|
||||||
|
|
||||||
|
def test_basic_entities(self) -> None:
|
||||||
|
"""
|
||||||
|
Test some random stuff with basic entities.
|
||||||
|
"""
|
||||||
|
entity = Entity()
|
||||||
|
entity.move(42, 64)
|
||||||
|
self.assertEqual(entity.y, 42)
|
||||||
|
self.assertEqual(entity.x, 64)
|
||||||
|
self.assertIsNone(entity.act(self.map))
|
||||||
|
|
||||||
|
def test_fighting_entities(self) -> None:
|
||||||
|
"""
|
||||||
|
Test some random stuff with fighting entities.
|
||||||
|
"""
|
||||||
|
entity = Squirrel()
|
||||||
|
self.assertIsNone(entity.act(self.map))
|
||||||
|
self.assertEqual(entity.maxhealth, 10)
|
||||||
|
self.assertEqual(entity.maxhealth, entity.health)
|
||||||
|
self.assertEqual(entity.strength, 3)
|
||||||
|
self.assertIsNone(entity.hit(entity))
|
||||||
|
self.assertFalse(entity.dead)
|
||||||
|
self.assertIsNone(entity.hit(entity))
|
||||||
|
self.assertFalse(entity.dead)
|
||||||
|
self.assertIsNone(entity.hit(entity))
|
||||||
|
self.assertFalse(entity.dead)
|
||||||
|
self.assertIsNone(entity.hit(entity))
|
||||||
|
self.assertTrue(entity.dead)
|
||||||
|
|
||||||
|
def test_items(self) -> None:
|
||||||
|
"""
|
||||||
|
Test some random stuff with items.
|
||||||
|
"""
|
||||||
|
item = Item()
|
||||||
|
self.assertFalse(item.held)
|
||||||
|
item.hold()
|
||||||
|
self.assertTrue(item.held)
|
||||||
|
item.drop(42, 42)
|
||||||
|
self.assertEqual(item.y, 42)
|
||||||
|
self.assertEqual(item.x, 42)
|
||||||
|
|
||||||
|
def test_bombs(self) -> None:
|
||||||
|
"""
|
||||||
|
Test some random stuff with bombs.
|
||||||
|
"""
|
||||||
|
item = Bomb()
|
||||||
|
squirrel = Squirrel()
|
||||||
|
self.map.add_entity(item)
|
||||||
|
self.map.add_entity(squirrel)
|
||||||
|
squirrel.health = 2
|
||||||
|
squirrel.move(41, 42)
|
||||||
|
item.act(self.map)
|
||||||
|
self.assertFalse(squirrel.dead)
|
||||||
|
item.drop(42, 42)
|
||||||
|
self.assertEqual(item.y, 42)
|
||||||
|
self.assertEqual(item.x, 42)
|
||||||
|
item.act(self.map)
|
||||||
|
self.assertTrue(squirrel.dead)
|
||||||
|
|
||||||
|
def test_players(self) -> None:
|
||||||
|
"""
|
||||||
|
Test some random stuff with players.
|
||||||
|
"""
|
||||||
|
player = Player()
|
||||||
|
self.map.add_entity(player)
|
||||||
|
player.move(1, 6)
|
||||||
|
self.assertEqual(player.strength, 5)
|
||||||
|
self.assertEqual(player.health, player.maxhealth)
|
||||||
|
self.assertEqual(player.maxhealth, 20)
|
||||||
|
|
||||||
|
# Test movements and ensure that collisions are working
|
||||||
|
self.assertFalse(player.move_up())
|
||||||
|
self.assertTrue(player.move_left())
|
||||||
|
self.assertFalse(player.move_left())
|
||||||
|
for i in range(8):
|
||||||
|
self.assertTrue(player.move_down())
|
||||||
|
self.assertFalse(player.move_down())
|
||||||
|
self.assertTrue(player.move_right())
|
||||||
|
self.assertTrue(player.move_right())
|
||||||
|
self.assertTrue(player.move_right())
|
||||||
|
self.assertFalse(player.move_right())
|
||||||
|
self.assertTrue(player.move_down())
|
||||||
|
self.assertTrue(player.move_down())
|
|
@ -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,33 @@
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from dungeonbattle.interfaces import Map, Tile
|
||||||
|
|
||||||
|
|
||||||
|
class TestInterfaces(unittest.TestCase):
|
||||||
|
def test_map(self) -> None:
|
||||||
|
"""
|
||||||
|
Create a map and check that it is well parsed.
|
||||||
|
"""
|
||||||
|
m = Map.load_from_string(".█\n█.\n")
|
||||||
|
self.assertEqual(m.width, 2)
|
||||||
|
self.assertEqual(m.height, 2)
|
||||||
|
self.assertEqual(m.draw_string(), ".█\n█.")
|
||||||
|
|
||||||
|
def test_load_map(self) -> None:
|
||||||
|
"""
|
||||||
|
Try to load a map from a file.
|
||||||
|
"""
|
||||||
|
m = Map.load("example_map.txt")
|
||||||
|
self.assertEqual(m.width, 52)
|
||||||
|
self.assertEqual(m.height, 17)
|
||||||
|
|
||||||
|
def test_tiles(self) -> None:
|
||||||
|
"""
|
||||||
|
Test some things about tiles.
|
||||||
|
"""
|
||||||
|
self.assertFalse(Tile.FLOOR.is_wall())
|
||||||
|
self.assertTrue(Tile.WALL.is_wall())
|
||||||
|
self.assertFalse(Tile.EMPTY.is_wall())
|
||||||
|
self.assertTrue(Tile.FLOOR.can_walk())
|
||||||
|
self.assertFalse(Tile.WALL.can_walk())
|
||||||
|
self.assertTrue(Tile.EMPTY.can_walk())
|
|
@ -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)
|
|
@ -18,8 +18,10 @@ class TestSettings(unittest.TestCase):
|
||||||
self.assertEqual(settings.KEY_LEFT_SECONDARY, 'KEY_LEFT')
|
self.assertEqual(settings.KEY_LEFT_SECONDARY, 'KEY_LEFT')
|
||||||
self.assertEqual(settings.KEY_RIGHT_SECONDARY, 'KEY_RIGHT')
|
self.assertEqual(settings.KEY_RIGHT_SECONDARY, 'KEY_RIGHT')
|
||||||
self.assertEqual(settings.TEXTURE_PACK, 'ascii')
|
self.assertEqual(settings.TEXTURE_PACK, 'ascii')
|
||||||
self.assertEqual(settings.get_comment(settings.TEXTURE_PACK), settings.get_comment('TEXTURE_PACK'))
|
self.assertEqual(settings.get_comment(settings.TEXTURE_PACK),
|
||||||
self.assertEqual(settings.get_comment(settings.TEXTURE_PACK), 'Pack de textures utilisé')
|
settings.get_comment('TEXTURE_PACK'))
|
||||||
|
self.assertEqual(settings.get_comment(settings.TEXTURE_PACK),
|
||||||
|
'Pack de textures utilisé')
|
||||||
|
|
||||||
settings.TEXTURE_PACK = 'UNICODE'
|
settings.TEXTURE_PACK = 'UNICODE'
|
||||||
self.assertEqual(settings.TEXTURE_PACK, 'UNICODE')
|
self.assertEqual(settings.TEXTURE_PACK, 'UNICODE')
|
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