Stepwise/source/engine.py
Kayne Ruse f831019148 Items can be picked up and stored in the inventory
When more than one item can be picked up, and options window is shown.

Stubs for "using" an item are in place.
2025-03-29 16:30:44 +11:00

116 lines
2.8 KiB
Python

from __future__ import annotations
from typing import List
from tcod.context import Context
from tcod.console import Console
from tcod.map import compute_fov
from entity import Entity
from message_log import Message, MessageLog
from floor_map import FloorMap #TODO: replace with "DungeonMap" or similar
from actions import BaseAction
from render_functions import render_hp_bar, render_names_at
class Engine:
player: Entity
floor_map: FloorMap
def __init__(self, *, floor_map: FloorMap, initial_log: List[Message] = None, ui_width: int = None, ui_height: int = None):
#events
from event_handlers import GameplayHandler
self.event_handler = GameplayHandler(self)
self.mouse_position = (0, 0)
#map
self.floor_map = floor_map
self.floor_map.engine = self #entities in maps can also reference the engine
#messages
self.message_log = MessageLog()
if initial_log:
self.message_log.push_messages(initial_log)
#grab the player object (generated by the procgen, usually)
self.player = self.floor_map.player
#default values
self.ui_width = floor_map.width if ui_width is None else ui_width
self.ui_height = 0 if ui_height is None else ui_height
#kick off the fov
self.update_fov()
def run_loop(self, context: Context, console: Console) -> None:
while True:
self.update_fov()
if self.event_handler.handle_events(context):
self.handle_entities() #TODO: what 'game state'?
self.handle_rendering(context, console)
def handle_entities(self) -> bool:
"""
Processes monster AI and other things.
Returns `True` if the game state should be progressed.
"""
actions: List[BaseAction] = []
#make the entities think and act
for entity in set(self.floor_map.entities) - {self.player}:
if entity.ai:
actions.append(entity.ai.process())
result = False
for action in actions:
result |= action.perform()
return result
def handle_rendering(self, context: Context, console: Console) -> None:
#map and all entities within
self.floor_map.render(console)
#UI
render_hp_bar(
console = console,
x = 0,
y = self.floor_map.height,
current_value = self.player.stats.current_hp,
max_value = self.player.stats.maximum_hp,
total_width = self.ui_width // 2,
)
render_names_at(
console = console,
x = 1,
y = self.floor_map.height + 2,
engine = self,
)
self.message_log.render(
console=console,
x=self.ui_width // 2,
y=self.floor_map.height,
width = self.ui_width // 2,
height = self.ui_height,
)
self.event_handler.render(console)
#send to the screen
context.present(console)
console.clear()
#utils
def update_fov(self):
self.floor_map.visible[:] = compute_fov(
self.floor_map.tiles["transparent"],
(self.player.x, self.player.y),
radius = 8,
)
#add the visible tiles to the explored list
self.floor_map.explored |= self.floor_map.visible