First pass on the logs

The newly-added logs manage a list of messages. Entities do register a
message to it when hitting each other. Display is created, but not yet
added to the layout actually displayed.
This commit is contained in:
Nicolas Margulies 2020-11-19 12:03:05 +01:00
parent 9b00863891
commit 6e71146aa2
6 changed files with 54 additions and 7 deletions

View File

@ -3,6 +3,7 @@ from squirrelbattle.display.mapdisplay import MapDisplay
from squirrelbattle.display.statsdisplay import StatsDisplay from squirrelbattle.display.statsdisplay import StatsDisplay
from squirrelbattle.display.menudisplay import SettingsMenuDisplay, \ from squirrelbattle.display.menudisplay import SettingsMenuDisplay, \
MainMenuDisplay MainMenuDisplay
from squirrelbattle.display.logsdisplay import LogsDisplay
from squirrelbattle.display.texturepack import TexturePack from squirrelbattle.display.texturepack import TexturePack
from typing import Any from typing import Any
from squirrelbattle.game import Game, GameMode from squirrelbattle.game import Game, GameMode
@ -20,8 +21,10 @@ class DisplayManager:
self.mainmenudisplay = MainMenuDisplay(self.game.main_menu, self.mainmenudisplay = MainMenuDisplay(self.game.main_menu,
screen, pack) screen, pack)
self.settingsmenudisplay = SettingsMenuDisplay(screen, pack) self.settingsmenudisplay = SettingsMenuDisplay(screen, pack)
self.logsdisplay = LogsDisplay(screen, pack)
self.displays = [self.statsdisplay, self.mapdisplay, self.displays = [self.statsdisplay, self.mapdisplay,
self.mainmenudisplay, self.settingsmenudisplay] self.mainmenudisplay, self.settingsmenudisplay,
self.logsdisplay]
self.update_game_components() self.update_game_components()
def handle_display_action(self, action: DisplayActions) -> None: def handle_display_action(self, action: DisplayActions) -> None:
@ -36,6 +39,7 @@ class DisplayManager:
self.mapdisplay.update_map(self.game.map) self.mapdisplay.update_map(self.game.map)
self.statsdisplay.update_player(self.game.player) self.statsdisplay.update_player(self.game.player)
self.settingsmenudisplay.update_menu(self.game.settings_menu) self.settingsmenudisplay.update_menu(self.game.settings_menu)
self.logsdisplay.update_logs(self.game.logs)
def refresh(self) -> None: def refresh(self) -> None:
if self.game.state == GameMode.PLAY: if self.game.state == GameMode.PLAY:

View File

@ -0,0 +1,17 @@
from squirrelbattle.display.display import Display
from squirrelbattle.interfaces import Logs
class LogsDisplay(Display):
def __init__(self, *args) -> None:
super().__init__(*args)
self.pad = self.newpad(self.rows, self.cols)
def update_logs(self, logs: Logs) -> None:
self.logs = logs
def display(self) -> None:
messages = self.logs.messages[-self.height:].reverse()
for i, y in enumerate(range(self.y + self.height - 1, self.y - 1, - 1)):
self.pad.addstr(y, self.x, messages[i][:self.width])

View File

@ -44,7 +44,7 @@ class Monster(FightingEntity):
next_y, next_x = target.paths[(self.y, self.x)] next_y, next_x = target.paths[(self.y, self.x)]
moved = self.check_move(next_y, next_x, True) moved = self.check_move(next_y, next_x, True)
if not moved and self.distance_squared(target) <= 1: if not moved and self.distance_squared(target) <= 1:
self.hit(target) self.map.logs.add_message(self.hit(target))
else: else:
for _ in range(100): for _ in range(100):
if choice([self.move_up, self.move_down, if choice([self.move_up, self.move_down,

View File

@ -70,7 +70,7 @@ class Player(FightingEntity):
for entity in self.map.entities: for entity in self.map.entities:
if entity.y == y and entity.x == x: if entity.y == y and entity.x == x:
if entity.is_fighting_entity(): if entity.is_fighting_entity():
self.hit(entity) self.map.logs.add_message(self.hit(entity))
if entity.dead: if entity.dead:
self.add_xp(randint(3, 7)) self.add_xp(randint(3, 7))
return True return True

View File

@ -6,7 +6,7 @@ import sys
from .entities.player import Player from .entities.player import Player
from .enums import GameMode, KeyValues, DisplayActions from .enums import GameMode, KeyValues, DisplayActions
from .interfaces import Map from .interfaces import Map, Logs
from .resources import ResourceManager from .resources import ResourceManager
from .settings import Settings from .settings import Settings
from . import menus from . import menus
@ -33,6 +33,7 @@ class Game:
self.settings.load_settings() self.settings.load_settings()
self.settings.write_settings() self.settings.write_settings()
self.settings_menu.update_values(self.settings) self.settings_menu.update_values(self.settings)
self.logs = Logs()
def new_game(self) -> None: def new_game(self) -> None:
""" """
@ -40,6 +41,7 @@ class Game:
""" """
# TODO generate a new map procedurally # TODO generate a new map procedurally
self.map = Map.load(ResourceManager.get_asset_path("example_map_2.txt")) self.map = Map.load(ResourceManager.get_asset_path("example_map_2.txt"))
self.map.logs = self.logs
self.player = Player() self.player = Player()
self.map.add_entity(self.player) self.map.add_entity(self.player)
self.player.move(self.map.start_y, self.map.start_x) self.player.move(self.map.start_y, self.map.start_x)

View File

@ -7,6 +7,26 @@ from typing import List, Optional
from squirrelbattle.display.texturepack import TexturePack from squirrelbattle.display.texturepack import TexturePack
class Logs:
"""
The logs object stores the messages to display. It is encapsulating a list
of such messages, to allow multiple pointers to keep track of it even if
the list was to be reassigned.
"""
def __init__(self) -> None:
self.messages = []
def add_message(self, msg: str) -> None:
self.messages.append(msg)
def add_messages(self, msg: List[str]) -> None:
self.messages += msg
def clear(self) -> None:
self.messages = []
class Map: class Map:
""" """
Object that represents a Map with its width, height Object that represents a Map with its width, height
@ -18,6 +38,7 @@ class Map:
start_x: int start_x: int
tiles: List[List["Tile"]] tiles: List[List["Tile"]]
entities: List["Entity"] entities: List["Entity"]
logs: Logs
# coordinates of the point that should be # coordinates of the point that should be
# on the topleft corner of the screen # on the topleft corner of the screen
currentx: int currentx: int
@ -362,19 +383,22 @@ class FightingEntity(Entity):
def dead(self) -> bool: def dead(self) -> bool:
return self.health <= 0 return self.health <= 0
def hit(self, opponent: "FightingEntity") -> None: def hit(self, opponent: "FightingEntity") -> str:
""" """
Deals damage to the opponent, based on the stats Deals damage to the opponent, based on the stats
""" """
opponent.take_damage(self, self.strength) return f"{self.name} hits {opponent.name}. "\
+ opponent.take_damage(self, self.strength)
def take_damage(self, attacker: "Entity", amount: int) -> None: def take_damage(self, attacker: "Entity", amount: int) -> str:
""" """
Take damage from the attacker, based on the stats 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()
return f"{self.name} takes {amount} damage."\
+ (f" {self.name} dies." if self.health <= 0 else "")
def die(self) -> None: def die(self) -> None:
""" """