From f14c43d6c08253a98a781e65067288a578d1115c Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 19 Jul 2025 09:57:54 -0700 Subject: Add Screen struct --- src/isogfx.c | 78 ++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 37 deletions(-) (limited to 'src/isogfx.c') diff --git a/src/isogfx.c b/src/isogfx.c index b715ca8..e182dff 100644 --- a/src/isogfx.c +++ b/src/isogfx.c @@ -32,7 +32,11 @@ typedef struct vec2 { // Renderer state. // ----------------------------------------------------------------------------- -// TODO: Define a struct Screen with width, height and pixels. +typedef struct Screen { + int width; + int height; + Pixel* pixels; +} Screen; typedef struct SpriteInstance { struct SpriteInstance* next; @@ -43,11 +47,9 @@ typedef struct SpriteInstance { } SpriteInstance; typedef struct IsoGfx { - int screen_width; - int screen_height; + Screen screen; double last_animation_time; Tile next_tile; // For procedurally-generated tiles. - Pixel* screen; Tm_Map* map; Ts_TileSet* tileset; SpriteInstance* head_sprite; // Head of sprites list. @@ -90,21 +92,21 @@ static inline vec2 cart2iso(vec2 cart, int s, int t, int w) { } static inline const Pixel* screen_xy_const_ref( - const IsoGfx* iso, int x, int y) { - assert(iso); + const Screen* screen, int x, int y) { + assert(screen); assert(x >= 0); assert(y >= 0); - assert(x < iso->screen_width); - assert(y < iso->screen_height); - return &iso->screen[y * iso->screen_width + x]; + assert(x < screen->width); + assert(y < screen->height); + return &screen->pixels[y * screen->width + x]; } -static inline Pixel screen_xy(IsoGfx* iso, int x, int y) { - return *screen_xy_const_ref(iso, x, y); +static inline Pixel screen_xy(Screen* screen, int x, int y) { + return *screen_xy_const_ref(screen, x, y); } -static inline Pixel* screen_xy_mut(IsoGfx* iso, int x, int y) { - return (Pixel*)screen_xy_const_ref(iso, x, y); +static inline Pixel* screen_xy_mut(Screen* screen, int x, int y) { + return (Pixel*)screen_xy_const_ref(screen, x, y); } // ----------------------------------------------------------------------------- @@ -126,16 +128,17 @@ IsoGfx* isogfx_new(const IsoGfxDesc* desc) { memstack_alloc_aligned(&tmp.stack, sizeof(IsoGfx), alignof(IsoGfx)); *iso = tmp; - iso->screen_width = desc->screen_width; - iso->screen_height = desc->screen_height; - iso->last_animation_time = 0.0; - const size_t screen_size_bytes = desc->screen_width * desc->screen_height * sizeof(Pixel); - iso->screen = + Pixel* screen = memstack_alloc_aligned(&iso->stack, screen_size_bytes, alignof(Pixel)); - iso->watermark = memstack_watermark(&iso->stack); + iso->screen = (Screen){.width = desc->screen_width, + .height = desc->screen_height, + .pixels = screen}; + + iso->last_animation_time = 0.0; + iso->watermark = memstack_watermark(&iso->stack); return iso; @@ -469,7 +472,7 @@ typedef struct CoordSystem { /// expressed in the Cartesian system. static CoordSystem make_iso_coord_system(const IsoGfx* iso) { assert(iso); - const ivec2 o = {iso->screen_width / 2, 0}; + const ivec2 o = {iso->screen.width / 2, 0}; const ivec2 x = { .x = iso->map->base_tile_width / 2, .y = iso->map->base_tile_height / 2}; const ivec2 y = { @@ -517,9 +520,9 @@ static Pixel alpha_blend(Pixel src, Pixel dst) { /// 'pixels' is the palette and 'indices' the pixel indices. Otherwise, the /// image is assumed to be in plain RGBA format. static void draw_rect( - IsoGfx* iso, ivec2 top_left, int rect_width, int rect_height, + Screen* screen, ivec2 top_left, int rect_width, int rect_height, const Pixel* pixels, const uint8_t* indices) { - assert(iso); + assert(screen); #define rect_pixel(X, Y) \ (indices ? pixels[indices[Y * rect_width + X]] : pixels[Y * rect_width + X]) @@ -532,16 +535,16 @@ static void draw_rect( // Rect can exceed screen bounds, so clip along Y and X as we draw. for (int py = py_offset; - (py < rect_height) && (top_left.y + py < iso->screen_height); ++py) { + (py < rect_height) && (top_left.y + py < screen->height); ++py) { const int sy = top_left.y + py; for (int px = px_offset; - (px < rect_width) && (top_left.x + px < iso->screen_width); ++px) { + (px < rect_width) && (top_left.x + px < screen->width); ++px) { const Pixel colour = rect_pixel(px, py); if (colour.a > 0) { - const int sx = top_left.x + px; - const Pixel dst = screen_xy(iso, sx, sy); - const Pixel final = alpha_blend(colour, dst); - *screen_xy_mut(iso, sx, sy) = final; + const int sx = top_left.x + px; + const Pixel dst = screen_xy(screen, sx, sy); + const Pixel final = alpha_blend(colour, dst); + *screen_xy_mut(screen, sx, sy) = final; } } } @@ -567,16 +570,17 @@ static void draw_tile(IsoGfx* iso, ivec2 screen_origin, Tile tile) { pTile->height - iso->map->base_tile_height}; const ivec2 top_left = ivec2_add(screen_origin, offset); - draw_rect(iso, top_left, pTile->width, pTile->height, pixels, 0); + draw_rect( + &iso->screen, top_left, pTile->width, pTile->height, pixels, nullptr); } static void draw_world(IsoGfx* iso) { assert(iso); - const int W = iso->screen_width; - const int H = iso->screen_height; + const int W = iso->screen.width; + const int H = iso->screen.height; - memset(iso->screen, 0, W * H * sizeof(Pixel)); + memset(iso->screen.pixels, 0, W * H * sizeof(Pixel)); const CoordSystem iso_space = make_iso_coord_system(iso); @@ -609,7 +613,7 @@ static void draw_sprite( const Ss_Row* row = ss_get_sprite_sheet_row(sheet, sprite->animation); const uint8_t* frame = ss_get_sprite_sheet_sprite(sheet, row, sprite->frame); draw_rect( - iso, origin, sheet->sprite_width, sheet->sprite_height, + &iso->screen, origin, sheet->sprite_width, sheet->sprite_height, sheet->palette.colours, frame); } @@ -651,13 +655,13 @@ void isogfx_get_screen_size(const IsoGfx* iso, int* width, int* height) { assert(iso); assert(width); assert(height); - *width = iso->screen_width; - *height = iso->screen_height; + *width = iso->screen.width; + *height = iso->screen.height; } const Pixel* isogfx_get_screen_buffer(const IsoGfx* iso) { assert(iso); - return iso->screen; + return iso->screen.pixels; } void isogfx_pick_tile( @@ -668,7 +672,7 @@ void isogfx_pick_tile( const vec2 xy_iso = cart2iso( (vec2){.x = xcart, .y = ycart}, iso->map->base_tile_width, - iso->map->base_tile_height, iso->screen_width); + iso->map->base_tile_height, iso->screen.width); if ((0 <= xy_iso.x) && (xy_iso.x < iso->map->world_width) && (0 <= xy_iso.y) && (xy_iso.y < iso->map->world_height)) { -- cgit v1.2.3