Log messages in the game window
This commit is contained in:
parent
1d8539ee82
commit
b0f5e2afe0
19
actions.py
19
actions.py
@ -1,6 +1,8 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional, Tuple, TYPE_CHECKING, overload
|
||||
from typing import overload, Optional, Tuple, TYPE_CHECKING
|
||||
|
||||
import color
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from engine import Engine
|
||||
@ -71,11 +73,22 @@ class MeleeAction(ActionWithDirection):
|
||||
damage = self.entity.fighter.power - target.fighter.defense
|
||||
|
||||
attack_desc = f"{self.entity.name.capitalize()} attacks {target.name}"
|
||||
if self.entity is self.engine.player:
|
||||
attack_color = color.player_atk
|
||||
else:
|
||||
attack_color = color.enemy_atk
|
||||
|
||||
if damage > 0:
|
||||
print(f"{attack_desc} for {damage} hit points.")
|
||||
self.engine.message_log.add_message(
|
||||
f"{attack_desc} for {damage} hit points.",
|
||||
attack_color,
|
||||
)
|
||||
target.fighter.hp -= damage
|
||||
else:
|
||||
print(f"{attack_desc} but does no damage.")
|
||||
self.engine.message_log.add_message(
|
||||
f"{attack_desc} but does no damage.",
|
||||
attack_color,
|
||||
)
|
||||
|
||||
|
||||
class MovementAction(ActionWithDirection):
|
||||
|
@ -2,6 +2,7 @@ from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import color
|
||||
from components.base_component import BaseComponent
|
||||
from input_handlers import GameOverEventHandler
|
||||
from render_order import RenderOrder
|
||||
@ -32,9 +33,11 @@ class Fighter(BaseComponent):
|
||||
def die(self) -> None:
|
||||
if self.engine.player is self.entity:
|
||||
death_message = "You died!"
|
||||
death_message_color = color.player_die
|
||||
self.engine.event_handler = GameOverEventHandler(self.engine)
|
||||
else:
|
||||
death_message = f"{self.entity.name} is dead!"
|
||||
death_message_color = color.enemy_die
|
||||
|
||||
self.entity.char = "%"
|
||||
self.entity.color = (191, 0, 0)
|
||||
@ -43,4 +46,4 @@ class Fighter(BaseComponent):
|
||||
self.entity.name = f"remains of {self.entity.name}"
|
||||
self.entity.render_order = RenderOrder.CORPSE
|
||||
|
||||
print(death_message)
|
||||
self.engine.message_log.add_message(death_message, death_message_color)
|
||||
|
@ -7,6 +7,7 @@ from tcod.console import Console
|
||||
from tcod.map import compute_fov
|
||||
|
||||
from input_handlers import MainGameEventHandler
|
||||
from message_log import MessageLog
|
||||
from render_functions import render_bar
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@ -19,6 +20,7 @@ class Engine:
|
||||
|
||||
def __init__(self, player: Actor):
|
||||
self.event_handler: EventHandler = MainGameEventHandler(self)
|
||||
self.message_log = MessageLog()
|
||||
self.player = player
|
||||
|
||||
def handle_enemy_turns(self) -> None:
|
||||
@ -40,6 +42,8 @@ class Engine:
|
||||
def render(self, console: Console, context: Context) -> None:
|
||||
self.game_map.render(console)
|
||||
|
||||
self.message_log.render(console=console, x=21, y=45, width=40, height=5)
|
||||
|
||||
render_bar(
|
||||
console,
|
||||
current_value=self.player.fighter.hp,
|
||||
|
8
main.py
8
main.py
@ -3,6 +3,7 @@ import copy
|
||||
|
||||
import tcod
|
||||
|
||||
import color
|
||||
from engine import Engine
|
||||
import entity_factories
|
||||
from procgen import generate_dungeon
|
||||
@ -13,7 +14,7 @@ def main() -> None:
|
||||
screen_height = 50
|
||||
|
||||
map_width = 80
|
||||
map_height = 45
|
||||
map_height = 43
|
||||
|
||||
room_max_size = 10
|
||||
room_min_size = 6
|
||||
@ -43,6 +44,11 @@ def main() -> None:
|
||||
)
|
||||
engine.update_fov()
|
||||
|
||||
engine.message_log.add_message(
|
||||
"Hello and welcome, adventurer, to yet another dungeon!",
|
||||
color.welcome_text
|
||||
)
|
||||
|
||||
with tcod.context.new_terminal(
|
||||
screen_width,
|
||||
screen_height,
|
||||
|
79
message_log.py
Normal file
79
message_log.py
Normal file
@ -0,0 +1,79 @@
|
||||
from typing import List, Reversible, Tuple
|
||||
import textwrap
|
||||
|
||||
import tcod
|
||||
|
||||
import color
|
||||
|
||||
|
||||
class Message:
|
||||
def __init__(self, text: str, fg: Tuple[int, int, int]):
|
||||
self.plain_text = text
|
||||
self.fg = fg
|
||||
self.count = 1
|
||||
|
||||
@property
|
||||
def full_text(self) -> str:
|
||||
"""The full text of this message, including the count if necessary."""
|
||||
if self.count > 1:
|
||||
return f"{self.plain_text} (x{self.count}"
|
||||
|
||||
return self.plain_text
|
||||
|
||||
|
||||
class MessageLog:
|
||||
def __init__(self) -> None:
|
||||
self.messages: List[Message] = []
|
||||
|
||||
def add_message(
|
||||
self,
|
||||
text: str,
|
||||
fg: Tuple[int, int, int] = color.white,
|
||||
*,
|
||||
stack: bool = True
|
||||
) -> None:
|
||||
"""Add a message to this log.
|
||||
`text` is the message text, `fg` is the text color.
|
||||
If `stack is True then the message can stack with a previous message
|
||||
of the same text.
|
||||
"""
|
||||
if stack and self.messages and text == self.messages[-1].plain_text:
|
||||
self.messages[-1].count += 1
|
||||
else:
|
||||
self.messages.append(Message(text, fg))
|
||||
|
||||
def render(
|
||||
self,
|
||||
console: tcod.Console,
|
||||
x: int,
|
||||
y: int,
|
||||
width: int,
|
||||
height: int,
|
||||
) -> None:
|
||||
"""Render this log over the given area.
|
||||
`x`, `y`, `width`, `height` is the rectangular region to render onto
|
||||
the `console`.
|
||||
"""
|
||||
self.render_messages(console, x, y, width, height, self.messages)
|
||||
|
||||
@staticmethod
|
||||
def render_messages(
|
||||
console: tcod.Console,
|
||||
x: int,
|
||||
y: int,
|
||||
width: int,
|
||||
height: int,
|
||||
messages: Reversible[Message],
|
||||
) -> None:
|
||||
"""Render the messages provided.
|
||||
The `messages` are rendered starting at the last message and working
|
||||
backwards.
|
||||
"""
|
||||
y_offset = height - 1
|
||||
|
||||
for message in reversed(messages):
|
||||
for line in reversed(textwrap.wrap(message.full_text, width)):
|
||||
console.print(x=x, y=y + y_offset, string=line, fg=message.fg)
|
||||
y_offset -= 1
|
||||
if y_offset < 0:
|
||||
return # No more space to print messages
|
Loading…
Reference in New Issue
Block a user