imporved wall rendering and added floor rendering

This commit is contained in:
Lukas Nöllemeyer 2024-08-18 13:28:14 +02:00
parent b23194ea46
commit f29f067aad
4 changed files with 40 additions and 31 deletions

View file

@ -41,5 +41,7 @@ ACTION_KEYS: Final = {
} }
GRASS_CHAR: Final = ord(',')
FLOOR_CHAR: Final = ord('.')
WALL_CHAR: Final = ord('_') WALL_CHAR: Final = ord('_')
VERTICAL_WALL_CHAR: Final = ord('|') VERTICAL_WALL_CHAR: Final = ord('|')

View file

@ -6,13 +6,14 @@ from random import Random
import attrs import attrs
import tcod.console import tcod.console
import tcod.constants import tcod.constants
import tcod.ecs
import tcod.event import tcod.event
from tcod.event import KeySym from tcod.event import KeySym
from tcod.map import Map from tcod.map import Map
import g import g
from game.components import Action, Gold, Graphic, Position 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.screens import Push, Screen, ScreenResult
from game.tags import IsDoor, IsItem, IsPlayer, IsActor from game.tags import IsDoor, IsItem, IsPlayer, IsActor
from game.constants import WALL_CHAR, VERTICAL_WALL_CHAR from game.constants import WALL_CHAR, VERTICAL_WALL_CHAR
@ -52,6 +53,18 @@ def _handle_action(player):
entity.components[Action](entity) entity.components[Action](entity)
_recalc_fov(player_pos) _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() @attrs.define()
class MainScreen(Screen): class MainScreen(Screen):
"""Primary in-game state.""" """Primary in-game state."""
@ -82,42 +95,35 @@ class MainScreen(Screen):
w = console.width//2 w = console.width//2
map: Map = g.world[None].components[Map] 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 # Draw walls
doors = [ world_pos_to_map_pos(d.components[Position]) for d in g.world.Q.all_of(tags=[IsDoor]) ] 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 i in range(console.width):
for (x, val) in enumerate(row): for j in range(console.height):
pos = map_pos_to_world_pos(Position(x,y)) world_pos = Position(i-w,j-h)+camera_pos
ch = 0 map_pos = world_pos_to_map_pos(world_pos)
if not val: in_map = 0 <= map_pos.x < map.width and 0 <= map_pos.y < map.height
ch = VERTICAL_WALL_CHAR in_fov = in_map and map.fov[map_pos.y,map_pos.x]
if map.walkable[y+1,x] and not Position(x,y+1) in doors: if not in_fov:
ch = WALL_CHAR console.rgb[["ch","fg"]][j, i] = 0x2591, (50,50,50)
graphic = Graphic(ch) continue
draw(pos, graphic) 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 # draw all entities that are not actors
for entity in g.world.Q.all_of(components=[Position, Graphic]).none_of(tags=[IsActor]): 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 # draw all actors
for actor in g.world.Q.all_of(components=[Position, Graphic], tags=[IsActor]).none_of(tags=[IsPlayer]): 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 # draw the player
for player in g.world.Q.all_of(tags=[IsPlayer]): 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)): 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)) console.print(x=0, y=console.height - 1, string=text, fg=(255, 255, 255), bg=(0, 0, 0))

View file

@ -17,10 +17,12 @@ def valid_tileset():
terraintiles = tcod.tileset.load_tilesheet( terraintiles = tcod.tileset.load_tilesheet(
"Oryx/oryx_roguelike_2.0/Terrain.png", columns=16, rows=11, charmap=tcod.tileset.CHARMAP_CP437 "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('@'), 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('!'))) 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('0')))
tileset.set_tile(ord('\\'), terraintiles.get_tile(ord('/'))) 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 return tileset

View file

@ -37,7 +37,6 @@ def add_door(world, pos):
) )
add_wall(world, pos) add_wall(world, pos)
def new_world() -> Registry: def new_world() -> Registry:
"""Return a freshly generated world.""" """Return a freshly generated world."""
world = Registry() world = Registry()