Added documentation on a lot of classes and functions (and removed some files I commited by mistake)
This commit is contained in:
parent
41d1696c9b
commit
8f932604f6
|
@ -4,6 +4,11 @@ from dungeonbattle.term_manager import TermManager
|
||||||
|
|
||||||
|
|
||||||
class Bootstrap:
|
class Bootstrap:
|
||||||
|
"""
|
||||||
|
The bootstrap object is used to bootstrap the game so that it starts properly.
|
||||||
|
(It was initially created to avoid circulary imports between the Game and
|
||||||
|
Display classes)
|
||||||
|
"""
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def run_game():
|
def run_game():
|
||||||
|
|
|
@ -3,13 +3,22 @@ from typing import Optional
|
||||||
|
|
||||||
from dungeonbattle.settings import Settings
|
from dungeonbattle.settings import Settings
|
||||||
|
|
||||||
|
#This file contains a few useful enumeration classes used elsewhere in the code
|
||||||
|
|
||||||
|
|
||||||
class DisplayActions(Enum):
|
class DisplayActions(Enum):
|
||||||
|
"""
|
||||||
|
Display actions options for the callable displayaction Game uses
|
||||||
|
(it just calls the same action on the display object displayaction refers to)
|
||||||
|
"""
|
||||||
REFRESH = auto()
|
REFRESH = auto()
|
||||||
UPDATE = auto()
|
UPDATE = auto()
|
||||||
|
|
||||||
|
|
||||||
class GameMode(Enum):
|
class GameMode(Enum):
|
||||||
|
"""
|
||||||
|
Game mode options
|
||||||
|
"""
|
||||||
MAINMENU = auto()
|
MAINMENU = auto()
|
||||||
PLAY = auto()
|
PLAY = auto()
|
||||||
SETTINGS = auto()
|
SETTINGS = auto()
|
||||||
|
@ -17,6 +26,9 @@ class GameMode(Enum):
|
||||||
|
|
||||||
|
|
||||||
class KeyValues(Enum):
|
class KeyValues(Enum):
|
||||||
|
"""
|
||||||
|
Key values options used in the game
|
||||||
|
"""
|
||||||
UP = auto()
|
UP = auto()
|
||||||
DOWN = auto()
|
DOWN = auto()
|
||||||
LEFT = auto()
|
LEFT = auto()
|
||||||
|
|
|
@ -12,6 +12,9 @@ from typing import Callable
|
||||||
|
|
||||||
|
|
||||||
class Game:
|
class Game:
|
||||||
|
"""
|
||||||
|
The game object controls all actions in the game.
|
||||||
|
"""
|
||||||
map: Map
|
map: Map
|
||||||
player: Player
|
player: Player
|
||||||
# display_actions is a display interface set by the bootstrapper
|
# display_actions is a display interface set by the bootstrapper
|
||||||
|
@ -43,8 +46,8 @@ class Game:
|
||||||
def run(self, screen: Any) -> None:
|
def run(self, screen: Any) -> None:
|
||||||
"""
|
"""
|
||||||
Main infinite loop.
|
Main infinite loop.
|
||||||
We wait for a player action, then we do what that should be done
|
We wait for the player's action, then we do what that should be done
|
||||||
when the given key got pressed.
|
when the given key gets pressed.
|
||||||
"""
|
"""
|
||||||
while True: # pragma no cover
|
while True: # pragma no cover
|
||||||
screen.clear()
|
screen.clear()
|
||||||
|
@ -70,7 +73,7 @@ class Game:
|
||||||
|
|
||||||
def handle_key_pressed_play(self, key: KeyValues) -> None:
|
def handle_key_pressed_play(self, key: KeyValues) -> None:
|
||||||
"""
|
"""
|
||||||
In play mode, arrows or zqsd should move the main character.
|
In play mode, arrows or zqsd move the main character.
|
||||||
"""
|
"""
|
||||||
if key == KeyValues.UP:
|
if key == KeyValues.UP:
|
||||||
if self.player.move_up():
|
if self.player.move_up():
|
||||||
|
@ -108,15 +111,16 @@ class Game:
|
||||||
elif option == menus.MainMenuValues.EXIT:
|
elif option == menus.MainMenuValues.EXIT:
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
def game_to_str(self) -> str:
|
|
||||||
d = dict()
|
|
||||||
d["Map"] = game.map
|
|
||||||
d["Player"] = game.player
|
|
||||||
|
|
||||||
def save_state(self) -> dict():
|
def save_state(self) -> dict():
|
||||||
|
"""
|
||||||
|
Saves the game to a dictionnary
|
||||||
|
"""
|
||||||
return self.map.save_state()
|
return self.map.save_state()
|
||||||
|
|
||||||
def load_state(self, d: dict) -> None:
|
def load_state(self, d: dict) -> None:
|
||||||
|
"""
|
||||||
|
Loads the game from a dictionnary
|
||||||
|
"""
|
||||||
self.map.load_state(d)
|
self.map.load_state(d)
|
||||||
|
|
||||||
def load_game(self) -> None:
|
def load_game(self) -> None:
|
||||||
|
@ -129,7 +133,7 @@ class Game:
|
||||||
|
|
||||||
def save_game(self) -> None:
|
def save_game(self) -> None:
|
||||||
"""
|
"""
|
||||||
Save the game to a file
|
Saves the game to a file
|
||||||
"""
|
"""
|
||||||
with open("save.json", "w") as f:
|
with open("save.json", "w") as f:
|
||||||
f.write(json.dumps(self.save_state()))
|
f.write(json.dumps(self.save_state()))
|
||||||
|
|
|
@ -10,7 +10,7 @@ from dungeonbattle.display.texturepack import TexturePack
|
||||||
class Map:
|
class Map:
|
||||||
"""
|
"""
|
||||||
Object that represents a Map with its width, height
|
Object that represents a Map with its width, height
|
||||||
and the whole tiles, with their custom properties.
|
and tiles, that have their custom properties.
|
||||||
"""
|
"""
|
||||||
width: int
|
width: int
|
||||||
height: int
|
height: int
|
||||||
|
@ -120,6 +120,9 @@ class Map:
|
||||||
entity.act(self)
|
entity.act(self)
|
||||||
|
|
||||||
def save_state(self) -> dict:
|
def save_state(self) -> dict:
|
||||||
|
"""
|
||||||
|
Saves the map's attributes to a dictionnary
|
||||||
|
"""
|
||||||
d = dict()
|
d = dict()
|
||||||
d["width"] = self.width
|
d["width"] = self.width
|
||||||
d["height"] = self.height
|
d["height"] = self.height
|
||||||
|
@ -133,6 +136,9 @@ class Map:
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def load_state(self, d: dict) -> None:
|
def load_state(self, d: dict) -> None:
|
||||||
|
"""
|
||||||
|
Loads the map's attributes from a dictionnary
|
||||||
|
"""
|
||||||
self.width = d["width"]
|
self.width = d["width"]
|
||||||
self.height = d["height"]
|
self.height = d["height"]
|
||||||
self.start_y = d["start_y"]
|
self.start_y = d["start_y"]
|
||||||
|
@ -143,6 +149,9 @@ class Map:
|
||||||
#add entities
|
#add entities
|
||||||
|
|
||||||
class Tile(Enum):
|
class Tile(Enum):
|
||||||
|
"""
|
||||||
|
The internal representation of the tiles of the map
|
||||||
|
"""
|
||||||
EMPTY = auto()
|
EMPTY = auto()
|
||||||
WALL = auto()
|
WALL = auto()
|
||||||
FLOOR = auto()
|
FLOOR = auto()
|
||||||
|
@ -158,9 +167,15 @@ class Tile(Enum):
|
||||||
raise ValueError(ch)
|
raise ValueError(ch)
|
||||||
|
|
||||||
def char(self, pack: TexturePack) -> str:
|
def char(self, pack: TexturePack) -> str:
|
||||||
|
"""
|
||||||
|
Translates a Tile to the corresponding character according to the texture pack
|
||||||
|
"""
|
||||||
return getattr(pack, self.name)
|
return getattr(pack, self.name)
|
||||||
|
|
||||||
def is_wall(self) -> bool:
|
def is_wall(self) -> bool:
|
||||||
|
"""
|
||||||
|
Is this Tile a wall?
|
||||||
|
"""
|
||||||
return self == Tile.WALL
|
return self == Tile.WALL
|
||||||
|
|
||||||
def can_walk(self) -> bool:
|
def can_walk(self) -> bool:
|
||||||
|
@ -171,6 +186,9 @@ class Tile(Enum):
|
||||||
|
|
||||||
|
|
||||||
class Entity:
|
class Entity:
|
||||||
|
"""
|
||||||
|
An Entity object represents any entity present on the map
|
||||||
|
"""
|
||||||
y: int
|
y: int
|
||||||
x: int
|
x: int
|
||||||
name: str
|
name: str
|
||||||
|
@ -182,29 +200,47 @@ class Entity:
|
||||||
|
|
||||||
def check_move(self, y: int, x: int, move_if_possible: bool = False)\
|
def check_move(self, y: int, x: int, move_if_possible: bool = False)\
|
||||||
-> bool:
|
-> bool:
|
||||||
|
"""
|
||||||
|
Checks if moving to (y,x) is authorized
|
||||||
|
"""
|
||||||
free = self.map.is_free(y, x)
|
free = self.map.is_free(y, x)
|
||||||
if free and move_if_possible:
|
if free and move_if_possible:
|
||||||
self.move(y, x)
|
self.move(y, x)
|
||||||
return free
|
return free
|
||||||
|
|
||||||
def move(self, y: int, x: int) -> bool:
|
def move(self, y: int, x: int) -> bool:
|
||||||
|
"""
|
||||||
|
Moves an entity to (y,x) coordinates
|
||||||
|
"""
|
||||||
self.y = y
|
self.y = y
|
||||||
self.x = x
|
self.x = x
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def move_up(self, force: bool = False) -> bool:
|
def move_up(self, force: bool = False) -> bool:
|
||||||
|
"""
|
||||||
|
Moves the entity up one tile, if possible
|
||||||
|
"""
|
||||||
return self.move(self.y - 1, self.x) if force else \
|
return self.move(self.y - 1, self.x) if force else \
|
||||||
self.check_move(self.y - 1, self.x, True)
|
self.check_move(self.y - 1, self.x, True)
|
||||||
|
|
||||||
def move_down(self, force: bool = False) -> bool:
|
def move_down(self, force: bool = False) -> bool:
|
||||||
|
"""
|
||||||
|
Moves the entity down one tile, if possible
|
||||||
|
"""
|
||||||
return self.move(self.y + 1, self.x) if force else \
|
return self.move(self.y + 1, self.x) if force else \
|
||||||
self.check_move(self.y + 1, self.x, True)
|
self.check_move(self.y + 1, self.x, True)
|
||||||
|
|
||||||
def move_left(self, force: bool = False) -> bool:
|
def move_left(self, force: bool = False) -> bool:
|
||||||
|
"""
|
||||||
|
Moves the entity left one tile, if possible
|
||||||
|
"""
|
||||||
return self.move(self.y, self.x - 1) if force else \
|
return self.move(self.y, self.x - 1) if force else \
|
||||||
self.check_move(self.y, self.x - 1, True)
|
self.check_move(self.y, self.x - 1, True)
|
||||||
|
|
||||||
def move_right(self, force: bool = False) -> bool:
|
def move_right(self, force: bool = False) -> bool:
|
||||||
|
"""
|
||||||
|
Moves the entity right one tile, if possible
|
||||||
|
"""
|
||||||
return self.move(self.y, self.x + 1) if force else \
|
return self.move(self.y, self.x + 1) if force else \
|
||||||
self.check_move(self.y, self.x + 1, True)
|
self.check_move(self.y, self.x + 1, True)
|
||||||
|
|
||||||
|
@ -229,14 +265,23 @@ class Entity:
|
||||||
return sqrt(self.distance_squared(other))
|
return sqrt(self.distance_squared(other))
|
||||||
|
|
||||||
def is_fighting_entity(self) -> bool:
|
def is_fighting_entity(self) -> bool:
|
||||||
|
"""
|
||||||
|
Is this entity a fighting entity?
|
||||||
|
"""
|
||||||
return isinstance(self, FightingEntity)
|
return isinstance(self, FightingEntity)
|
||||||
|
|
||||||
def is_item(self) -> bool:
|
def is_item(self) -> bool:
|
||||||
|
"""
|
||||||
|
Is this entity an item?
|
||||||
|
"""
|
||||||
from dungeonbattle.entities.items import Item
|
from dungeonbattle.entities.items import Item
|
||||||
return isinstance(self, Item)
|
return isinstance(self, Item)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_all_entity_classes():
|
def get_all_entity_classes():
|
||||||
|
"""
|
||||||
|
Returns all entities subclasses
|
||||||
|
"""
|
||||||
from dungeonbattle.entities.items import Heart, Bomb
|
from dungeonbattle.entities.items import Heart, Bomb
|
||||||
from dungeonbattle.entities.monsters import Beaver, Hedgehog, \
|
from dungeonbattle.entities.monsters import Beaver, Hedgehog, \
|
||||||
Rabbit, TeddyBear
|
Rabbit, TeddyBear
|
||||||
|
@ -260,6 +305,10 @@ class Entity:
|
||||||
|
|
||||||
|
|
||||||
class FightingEntity(Entity):
|
class FightingEntity(Entity):
|
||||||
|
"""
|
||||||
|
A FightingEntity is an entity that can fight, and thus has a health,
|
||||||
|
level and stats
|
||||||
|
"""
|
||||||
maxhealth: int
|
maxhealth: int
|
||||||
health: int
|
health: int
|
||||||
strength: int
|
strength: int
|
||||||
|
@ -285,27 +334,45 @@ class FightingEntity(Entity):
|
||||||
|
|
||||||
|
|
||||||
def hit(self, opponent: "FightingEntity") -> None:
|
def hit(self, opponent: "FightingEntity") -> None:
|
||||||
|
"""
|
||||||
|
Deals damage to the opponent, based on the stats
|
||||||
|
"""
|
||||||
opponent.take_damage(self, self.strength)
|
opponent.take_damage(self, self.strength)
|
||||||
|
|
||||||
def take_damage(self, attacker: "Entity", amount: int) -> None:
|
def take_damage(self, attacker: "Entity", amount: int) -> None:
|
||||||
|
"""
|
||||||
|
Take damage from the attacker, based on the stats
|
||||||
|
"""
|
||||||
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:
|
||||||
|
"""
|
||||||
|
If a fighting entity has no more health, it dies and is removed
|
||||||
|
"""
|
||||||
self.dead = True
|
self.dead = True
|
||||||
self.map.remove_entity(self)
|
self.map.remove_entity(self)
|
||||||
|
|
||||||
def keys(self) -> list:
|
def keys(self) -> list:
|
||||||
|
"""
|
||||||
|
Returns a fighting entities specific attributes
|
||||||
|
"""
|
||||||
return ["maxhealth", "health", "level", "dead", "strength", "intelligence", "charisma", "dexterity", "constitution"]
|
return ["maxhealth", "health", "level", "dead", "strength", "intelligence", "charisma", "dexterity", "constitution"]
|
||||||
|
|
||||||
def save_state(self) -> dict:
|
def save_state(self) -> dict:
|
||||||
|
"""
|
||||||
|
Saves the state of the entity into a dictionnary
|
||||||
|
"""
|
||||||
d = super().save_state()
|
d = super().save_state()
|
||||||
for name in self.keys():
|
for name in self.keys():
|
||||||
d[name] = self.__getattribute__(name)
|
d[name] = self.__getattribute__(name)
|
||||||
return d
|
return d
|
||||||
|
|
||||||
def recover_state(self, d : dict) -> None:
|
def recover_state(self, d : dict) -> None:
|
||||||
|
"""
|
||||||
|
Loads the state of an entity from a dictionnary
|
||||||
|
"""
|
||||||
super().recover_state(d)
|
super().recover_state(d)
|
||||||
for name in d.keys():
|
for name in d.keys():
|
||||||
self.__setattribute__(name, d[name])
|
self.__setattribute__(name, d[name])
|
||||||
|
|
|
@ -8,24 +8,41 @@ from .settings import Settings
|
||||||
|
|
||||||
|
|
||||||
class Menu:
|
class Menu:
|
||||||
|
"""
|
||||||
|
A Menu object is the logical representation of a menu in the game
|
||||||
|
"""
|
||||||
values: list
|
values: list
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.position = 0
|
self.position = 0
|
||||||
|
|
||||||
def go_up(self) -> None:
|
def go_up(self) -> None:
|
||||||
|
"""
|
||||||
|
Moves the pointer of the menu on the previous value
|
||||||
|
"""
|
||||||
self.position = max(0, self.position - 1)
|
self.position = max(0, self.position - 1)
|
||||||
|
|
||||||
def go_down(self) -> None:
|
def go_down(self) -> None:
|
||||||
|
"""
|
||||||
|
Moves the pointer of the menu on the next value
|
||||||
|
"""
|
||||||
self.position = min(len(self.values) - 1, self.position + 1)
|
self.position = min(len(self.values) - 1, self.position + 1)
|
||||||
|
|
||||||
def validate(self) -> Any:
|
def validate(self) -> Any:
|
||||||
|
"""
|
||||||
|
Selects the value that is pointed by the menu pointer
|
||||||
|
"""
|
||||||
return self.values[self.position]
|
return self.values[self.position]
|
||||||
|
|
||||||
|
|
||||||
class MainMenuValues(Enum):
|
class MainMenuValues(Enum):
|
||||||
|
"""
|
||||||
|
Values of the main menu
|
||||||
|
"""
|
||||||
START = 'Nouvelle partie'
|
START = 'Nouvelle partie'
|
||||||
RESUME = 'Continuer'
|
RESUME = 'Continuer'
|
||||||
|
SAVE = 'Sauvegarder'
|
||||||
|
LOAD = 'Charger'
|
||||||
SETTINGS = 'Paramètres'
|
SETTINGS = 'Paramètres'
|
||||||
EXIT = 'Quitter'
|
EXIT = 'Quitter'
|
||||||
|
|
||||||
|
@ -34,34 +51,22 @@ class MainMenuValues(Enum):
|
||||||
|
|
||||||
|
|
||||||
class MainMenu(Menu):
|
class MainMenu(Menu):
|
||||||
|
"""
|
||||||
|
A special instance of a menu : the main menu
|
||||||
|
"""
|
||||||
values = [e for e in MainMenuValues]
|
values = [e for e in MainMenuValues]
|
||||||
|
|
||||||
def handle_key_pressed(self, key: KeyValues, game: Any) -> None:
|
|
||||||
"""
|
|
||||||
In the main menu, we can navigate through options.
|
|
||||||
"""
|
|
||||||
if key == KeyValues.DOWN:
|
|
||||||
self.go_down()
|
|
||||||
if key == KeyValues.UP:
|
|
||||||
self.go_up()
|
|
||||||
if key == KeyValues.ENTER:
|
|
||||||
option = self.validate()
|
|
||||||
if option == MainMenuValues.START:
|
|
||||||
game.new_game()
|
|
||||||
game.state = GameMode.PLAY
|
|
||||||
game.display_actions(DisplayActions.UPDATE)
|
|
||||||
elif option == MainMenuValues.RESUME:
|
|
||||||
game.state = GameMode.PLAY
|
|
||||||
elif option == MainMenuValues.SETTINGS:
|
|
||||||
game.state = GameMode.SETTINGS
|
|
||||||
elif option == MainMenuValues.EXIT:
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
|
|
||||||
class SettingsMenu(Menu):
|
class SettingsMenu(Menu):
|
||||||
|
"""
|
||||||
|
A special instance of a menu : the settings menu
|
||||||
|
"""
|
||||||
waiting_for_key: bool = False
|
waiting_for_key: bool = False
|
||||||
|
|
||||||
def update_values(self, settings: Settings) -> None:
|
def update_values(self, settings: Settings) -> None:
|
||||||
|
"""
|
||||||
|
The settings can change, so they are updated
|
||||||
|
"""
|
||||||
self.values = []
|
self.values = []
|
||||||
for i, key in enumerate(settings.settings_keys):
|
for i, key in enumerate(settings.settings_keys):
|
||||||
s = settings.get_comment(key)
|
s = settings.get_comment(key)
|
||||||
|
@ -81,7 +86,7 @@ class SettingsMenu(Menu):
|
||||||
def handle_key_pressed(self, key: Optional[KeyValues], raw_key: str,
|
def handle_key_pressed(self, key: Optional[KeyValues], raw_key: str,
|
||||||
game: Any) -> None:
|
game: Any) -> None:
|
||||||
"""
|
"""
|
||||||
Update settings
|
In the setting menu, we van select a setting and change it
|
||||||
"""
|
"""
|
||||||
if not self.waiting_for_key:
|
if not self.waiting_for_key:
|
||||||
# Navigate normally through the menu.
|
# Navigate normally through the menu.
|
||||||
|
|
Loading…
Reference in New Issue