moved render stuff

This commit is contained in:
Lukas Nöllemeyer 2024-08-19 21:30:29 +02:00
parent 733c6ec30e
commit 5b2a68ff2c
6 changed files with 109 additions and 100 deletions

41
g.py
View file

@ -2,47 +2,20 @@
from __future__ import annotations from __future__ import annotations
import tcod.console from tcod.context import Context
import tcod.context from tcod.ecs import Registry
import tcod.ecs
import tcod.sdl.video
import tcod.tileset
import tcod.sdl.render
import tcod.render
from game.screens import Screen from game.screens import Screen
from game.components import Position from game.render import Renderer
context: tcod.context.Context context: Context
"""The window managed by tcod.""" """The window managed by tcod."""
world: tcod.ecs.Registry world: Registry
"""The active ECS registry and current session.""" """The active ECS registry and current session."""
screens: list[Screen] = [] screens: list[Screen] = []
"""A stack of states with the last item being the active state.""" """A stack of states with the last item being the active state."""
foreground: tcod.console.Console renderer: Renderer
"""The foreground console""" """Renderer for the game"""
background: tcod.console.Console
"""The background console"""
tileset: tcod.tileset.Tileset
"""The tileset to use"""
sdl_window: tcod.sdl.video.Window
"""The SDL window"""
sdl_renderer: tcod.sdl.render.Renderer
"""The SDL renderer"""
target_texture: tcod.sdl.render.Texture
"""The final texture that is rendered"""
atlas: tcod.render.SDLTilesetAtlas
"""The tileset atlas"""
console_render1: tcod.render.SDLConsoleRender
console_render2: tcod.render.SDLConsoleRender
"""The console renderer"""

84
game/render.py Normal file
View file

@ -0,0 +1,84 @@
"""All rendering stuff"""
from tcod.sdl.video import new_window
from tcod.console import Console
from tcod.sdl.video import WindowFlags, Window
from tcod.render import SDLConsoleRender, SDLTilesetAtlas
from tcod.sdl.render import new_renderer, TextureAccess, Renderer, Texture
from tcod.tileset import Tileset
from tcod.event import Event, MouseState
import g
class Renderer():
foreground: Console
"""The foreground console"""
background: Console
"""The background console"""
console_render1: SDLConsoleRender
console_render2: SDLConsoleRender
"""The console renderer"""
sdl_window: Window
"""The SDL window"""
sdl_renderer: Renderer
"""The SDL renderer"""
target_texture: Texture
"""The final texture that is rendered"""
atlas: SDLTilesetAtlas
"""The tileset atlas"""
tileset: Tileset
"""The tileset to use"""
def __init__(self, w, h, tileset):
self.background = Console(w, h)
self.foreground = Console(w, h)
self.tileset = tileset
w, h = self.background.width * tileset.tile_width, self.background.height * tileset.tile_height
self.sdl_window = new_window(w,h, flags=WindowFlags.RESIZABLE)
self.sdl_renderer = new_renderer(self.sdl_window, target_textures=True)
self.target_texture = self.sdl_renderer.new_texture(w, h, access=TextureAccess.TARGET)
self.atlas = SDLTilesetAtlas(self.sdl_renderer, self.tileset)
self.console_render1 = SDLConsoleRender(atlas=self.atlas)
self.console_render2 = SDLConsoleRender(atlas=self.atlas)
def main_draw(self) -> None:
"""Render and present the active screen."""
if not g.screens:
return
self.background.clear()
self.foreground.clear()
self.foreground.rgba["bg"][:] = 0
self.foreground.rgba["fg"][:] = 0
g.screens[-1].on_draw()
bg_tex = self.console_render1.render(self.background)
bg_tex.blend_mode = 1
fg_tex = self.console_render2.render(self.foreground)
fg_tex.blend_mode = 1
with self.sdl_renderer.set_render_target(self.target_texture):
self.sdl_renderer.clear()
self.sdl_renderer.copy(bg_tex)
self.sdl_renderer.copy(fg_tex)
self.sdl_renderer.copy(self.target_texture)
self.sdl_renderer.present()
def convert_event(self, event: Event):
match event:
case MouseState(position=pos):
width, height = self.tileset.tile_width, self.tileset.tile_height
event.position = (pos[0]//width, pos[1]//height)
return event
def dim(self):
self.foreground.rgb["fg"] //= 4
self.foreground.rgb["bg"] //= 4
self.background.rgb["fg"] //= 4
self.background.rgb["bg"] //= 4

View file

@ -15,7 +15,7 @@ import tcod.sdl.render
import tcod.sdl.video import tcod.sdl.video
import g import g
from game.render import Renderer
class Screen(Protocol): class Screen(Protocol):
"""An abstract game screen.""" """An abstract game screen."""
@ -25,7 +25,7 @@ class Screen(Protocol):
def on_event(self, event: Event) -> ScreenResult: def on_event(self, event: Event) -> ScreenResult:
"""Called on events.""" """Called on events."""
def on_draw(self, console: Console) -> None: def on_draw(self) -> None:
"""Called when the screen is being drawn.""" """Called when the screen is being drawn."""
@ -52,31 +52,6 @@ ScreenResult: TypeAlias = "Push | Pop | Reset | None"
"""Union of screen results.""" """Union of screen results."""
def main_draw() -> None:
"""Render and present the active screen."""
if not g.screens:
return
g.background.clear()
g.foreground.clear()
g.foreground.rgba["bg"][:] = 0
g.foreground.rgba["fg"][:] = 0
g.screens[-1].on_draw(g.background)
bg_tex = g.console_render1.render(g.background)
bg_tex.blend_mode = 1
fg_tex = g.console_render2.render(g.foreground)
fg_tex.blend_mode = 1
with g.sdl_renderer.set_render_target(g.target_texture):
g.sdl_renderer.clear()
g.sdl_renderer.copy(bg_tex)
g.sdl_renderer.copy(fg_tex)
g.sdl_renderer.copy(g.target_texture)
g.sdl_renderer.present()
def _apply_screen_result(result: ScreenResult) -> None: def _apply_screen_result(result: ScreenResult) -> None:
"""Apply a ScreenResult to `g.screens`.""" """Apply a ScreenResult to `g.screens`."""
match result: match result:
@ -93,22 +68,15 @@ def _apply_screen_result(result: ScreenResult) -> None:
case _: case _:
raise TypeError(result) raise TypeError(result)
def convert_event(event: tcod.event.Event):
match event:
case tcod.event.MouseState(position=pos):
width, height = g.tileset.tile_width, g.tileset.tile_height
event.position = (pos[0]//width, pos[1]//height)
return event
def main_loop() -> None: def main_loop() -> None:
"""Run the active screen forever.""" """Run the active screen forever."""
while g.screens: while g.screens:
main_draw() g.renderer.main_draw()
for event in wait_for_event(): for event in wait_for_event():
match event: match event:
case Quit(): case Quit():
raise SystemExit() raise SystemExit()
tile_event = convert_event(event) tile_event = g.renderer.convert_event(event)
if g.screens: if g.screens:
_apply_screen_result(g.screens[-1].on_event(tile_event)) _apply_screen_result(g.screens[-1].on_event(tile_event))
@ -119,14 +87,11 @@ def get_previous_screen(screen: Screen) -> Screen | None:
return g.screens[current_index - 1] if current_index > 0 else None return g.screens[current_index - 1] if current_index > 0 else None
def draw_previous_screens(screen: Screen, console: tcod.console.Console, dim: bool = True) -> None: def draw_previous_screens(screen: Screen, dim: bool = True) -> None:
"""Draw previous screens, optionally dimming all but the active screen.""" """Draw previous screens, optionally dimming all but the active screen."""
prev_screen = get_previous_screen(screen) prev_screen = get_previous_screen(screen)
if prev_screen is None: if prev_screen is None:
return return
prev_screen.on_draw(console) prev_screen.on_draw()
if dim and screen is g.screens[-1]: if dim and screen is g.screens[-1]:
g.foreground.rgb["fg"] //= 4 g.renderer.dim()
g.foreground.rgb["bg"] //= 4
g.background.rgb["fg"] //= 4
g.background.rgb["bg"] //= 4

View file

@ -64,7 +64,7 @@ def _draw_entity(entity: tcod.ecs.Entity, camera_pos, camera_radius_x, camera_ra
graphic = entity.components[Graphic] graphic = entity.components[Graphic]
r,gg,b,_ = graphic.fg r,gg,b,_ = graphic.fg
fg = (r,gg,b,255) fg = (r,gg,b,255)
g.foreground.rgba[["ch", "fg"]][screen_pos.y + camera_radius_y, screen_pos.x + camera_radius_x] = graphic.ch, fg g.renderer.foreground.rgba[["ch", "fg"]][screen_pos.y + camera_radius_y, screen_pos.x + camera_radius_x] = graphic.ch, fg
@attrs.define() @attrs.define()
@ -86,9 +86,9 @@ class MainScreen(Screen):
case _: case _:
return None return None
def on_draw(self, console: tcod.console.Console) -> None: def on_draw(self) -> None:
"""Draw the standard screen.""" """Draw the standard screen."""
console = g.background console = g.renderer.background
centers = [a.components[Position] for a in g.world.Q.all_of(tags=[IsPlayer])] centers = [a.components[Position] for a in g.world.Q.all_of(tags=[IsPlayer])]
camera_pos = sum(centers, start=Position(0,0)) camera_pos = sum(centers, start=Position(0,0))
camera_pos = camera_pos.mod(len(centers)) camera_pos = camera_pos.mod(len(centers))

View file

@ -45,10 +45,9 @@ class SelectItem(MenuItem):
case _: case _:
return None return None
def on_draw(self, console: tcod.console.Console, x: int, y: int, highlight: bool) -> None: def on_draw(self, x: int, y: int, highlight: bool) -> None:
"""Render this items label.""" """Render this items label."""
#g.foreground.print(x, y, self.label, fg=(255, 255, 255), bg=(64, 64, 64) if highlight else (0, 0, 0)) g.renderer.background.print(x, y, self.label, fg=(255, 255, 255), bg=(64, 64, 64) if highlight else (0, 0, 0))
g.background.print(x, y, self.label, fg=(255, 255, 255), bg=(64, 64, 64) if highlight else (0, 0, 0))
@attrs.define() @attrs.define()
@ -94,8 +93,8 @@ class ListMenu(Screen):
"""Handle escape or right click being pressed on menus.""" """Handle escape or right click being pressed on menus."""
return Pop() return Pop()
def on_draw(self, console: tcod.console.Console) -> None: def on_draw(self) -> None:
"""Render the menu.""" """Render the menu."""
draw_previous_screens(self, g.foreground) draw_previous_screens(self)
for i, item in enumerate(self.items): for i, item in enumerate(self.items):
item.on_draw(g.foreground, x=self.x, y=self.y + i, highlight=i == self.selected) item.on_draw(x=self.x, y=self.y + i, highlight=i == self.selected)

18
main.py
View file

@ -15,27 +15,15 @@ import g
import game.tilesetmanager import game.tilesetmanager
import game.screens import game.screens
from game.screens.menu_screens import MainMenu from game.screens.menu_screens import MainMenu
from game.render import Renderer
def main() -> None: def main() -> None:
"""Entry point function.""" """Entry point function."""
g.tileset = game.tilesetmanager.valid_tileset() tileset = game.tilesetmanager.valid_tileset()
#tcod.tileset.procedural_block_elements(tileset=tileset) #tcod.tileset.procedural_block_elements(tileset=tileset)
g.screens = [MainMenu()] g.screens = [MainMenu()]
g.background = tcod.console.Console(80, 35) g.renderer = Renderer(80, 35, tileset)
g.foreground = tcod.console.Console(80, 35)
w, h = g.background.width * g.tileset.tile_width, g.background.height * g.tileset.tile_height
win = tcod.sdl.video.new_window(w,h, flags=tcod.lib.SDL_WINDOW_RESIZABLE)
g.sdl_window = win
g.sdl_renderer = tcod.sdl.render.new_renderer(g.sdl_window, target_textures=True)
g.target_texture = g.sdl_renderer.new_texture(w, h, access=tcod.sdl.render.TextureAccess.TARGET)
g.atlas = tcod.render.SDLTilesetAtlas(g.sdl_renderer, g.tileset)
g.console_render1 = tcod.render.SDLConsoleRender(atlas=g.atlas)
g.console_render2 = tcod.render.SDLConsoleRender(atlas=g.atlas)
game.screens.main_loop() game.screens.main_loop()