diff --git a/game/constants.py b/game/constants.py index a187442..f3fa8fb 100644 --- a/game/constants.py +++ b/game/constants.py @@ -41,5 +41,7 @@ ACTION_KEYS: Final = { } +GRASS_CHAR: Final = ord(',') +FLOOR_CHAR: Final = ord('.') WALL_CHAR: Final = ord('_') VERTICAL_WALL_CHAR: Final = ord('|') diff --git a/game/screens/game_screens.py b/game/screens/game_screens.py index 5054a4e..1b16020 100644 --- a/game/screens/game_screens.py +++ b/game/screens/game_screens.py @@ -6,13 +6,14 @@ from random import Random import attrs import tcod.console import tcod.constants +import tcod.ecs import tcod.event from tcod.event import KeySym from tcod.map import Map import g from game.components import Action, Gold, Graphic, Position -from game.constants import DIRECTION_KEYS, ACTION_KEYS +from game.constants import DIRECTION_KEYS, ACTION_KEYS, FLOOR_CHAR from game.screens import Push, Screen, ScreenResult from game.tags import IsDoor, IsItem, IsPlayer, IsActor from game.constants import WALL_CHAR, VERTICAL_WALL_CHAR @@ -52,6 +53,18 @@ def _handle_action(player): entity.components[Action](entity) _recalc_fov(player_pos) +def _draw_entity(entity: tcod.ecs.Entity, camera_pos, camera_radius_x, camera_radius_y): + pos = entity.components[Position] + screen_pos = pos - camera_pos + if not (-camera_radius_x <= screen_pos.x < camera_radius_x\ + and -camera_radius_y <= screen_pos.y < camera_radius_y): + return + map_pos = world_pos_to_map_pos(pos) + if g.world[None].components[Map].fov[map_pos.y, map_pos.x]: + graphic = entity.components[Graphic] + g.console.rgb[["ch", "fg"]][screen_pos.y + camera_radius_y, screen_pos.x + camera_radius_x] = graphic.ch, graphic.fg + + @attrs.define() class MainScreen(Screen): """Primary in-game state.""" @@ -82,42 +95,35 @@ class MainScreen(Screen): w = console.width//2 map: Map = g.world[None].components[Map] - # TODO: eigentlich wäre andersrum rendern schöner - # also nicht alle objekte zu rendern und dabei rauszufinden ob sie auf dem screen sind, - # sondern über alle screen zellen laufen, über prüfen ob es im fov ist und dann gucken ob es dort ein objekt - # gibt und es entsprechend rendern - def draw(e_pos, e_graph): - screen_pos = e_pos - camera_pos - map_pos = world_pos_to_map_pos(e_pos) - if (-w <= screen_pos.x < w\ - and -h <= screen_pos.y < h): - if map.fov[map_pos.y, map_pos.x]: - graphic = e_graph - else: - graphic = Graphic(0x2591, (50, 50, 50)) - if graphic.ch != 0: - console.rgb[["ch", "fg"]][screen_pos.y + h, screen_pos.x + w] = graphic.ch, graphic.fg # Draw walls doors = [ world_pos_to_map_pos(d.components[Position]) for d in g.world.Q.all_of(tags=[IsDoor]) ] - for (y, row) in enumerate(map.walkable): - for (x, val) in enumerate(row): - pos = map_pos_to_world_pos(Position(x,y)) - ch = 0 - if not val: - ch = VERTICAL_WALL_CHAR - if map.walkable[y+1,x] and not Position(x,y+1) in doors: - ch = WALL_CHAR - graphic = Graphic(ch) - draw(pos, graphic) + for i in range(console.width): + for j in range(console.height): + world_pos = Position(i-w,j-h)+camera_pos + map_pos = world_pos_to_map_pos(world_pos) + in_map = 0 <= map_pos.x < map.width and 0 <= map_pos.y < map.height + in_fov = in_map and map.fov[map_pos.y,map_pos.x] + if not in_fov: + console.rgb[["ch","fg"]][j, i] = 0x2591, (50,50,50) + continue + walkable = (not in_map) or map.walkable[map_pos.y, map_pos.x] + if walkable: + console.rgb[["ch","fg"]][j, i] = FLOOR_CHAR, (70,70,70) + continue + ch = VERTICAL_WALL_CHAR + if map.walkable[map_pos.y+1, map_pos.x] and world_pos+Position(0,1) not in doors: + ch = WALL_CHAR + console.rgb[["ch","fg"]][j, i] = ch, (255,255,255) + # draw all entities that are not actors for entity in g.world.Q.all_of(components=[Position, Graphic]).none_of(tags=[IsActor]): - draw(entity.components[Position], entity.components[Graphic]) + _draw_entity(entity, camera_pos, w, h) # draw all actors for actor in g.world.Q.all_of(components=[Position, Graphic], tags=[IsActor]).none_of(tags=[IsPlayer]): - draw(actor.components[Position], entity.components[Graphic]) + _draw_entity(actor, camera_pos, w, h) # draw the player for player in g.world.Q.all_of(tags=[IsPlayer]): - draw(player.components[Position], player.components[Graphic]) + _draw_entity(player, camera_pos, w, h) if text := g.world[None].components.get(("Text", str)): console.print(x=0, y=console.height - 1, string=text, fg=(255, 255, 255), bg=(0, 0, 0)) diff --git a/game/tilesetmanager.py b/game/tilesetmanager.py index dda303e..a127dda 100644 --- a/game/tilesetmanager.py +++ b/game/tilesetmanager.py @@ -17,10 +17,12 @@ def valid_tileset(): terraintiles = tcod.tileset.load_tilesheet( "Oryx/oryx_roguelike_2.0/Terrain.png", columns=16, rows=11, charmap=tcod.tileset.CHARMAP_CP437 ) - + tileset.set_tile(ord('@'), monstertiles.get_tile(1)) tileset.set_tile(ord('/'), terraintiles.get_tile(ord('?'))) tileset.set_tile(ord('|'), terraintiles.get_tile(ord('!'))) tileset.set_tile(ord('_'), terraintiles.get_tile(ord('0'))) tileset.set_tile(ord('\\'), terraintiles.get_tile(ord('/'))) + tileset.set_tile(ord('.'), terraintiles.get_tile(2)) + tileset.set_tile(ord(','), terraintiles.get_tile(11)) return tileset diff --git a/game/world_tools.py b/game/world_tools.py index 5ac2e64..df06f11 100644 --- a/game/world_tools.py +++ b/game/world_tools.py @@ -37,7 +37,6 @@ def add_door(world, pos): ) add_wall(world, pos) - def new_world() -> Registry: """Return a freshly generated world.""" world = Registry()