diff options
author | 3gg <3gg@shellblade.net> | 2025-07-19 09:57:54 -0700 |
---|---|---|
committer | 3gg <3gg@shellblade.net> | 2025-07-19 09:57:54 -0700 |
commit | f14c43d6c08253a98a781e65067288a578d1115c (patch) | |
tree | 482ad61f0a88eda6a9c7c9a04f46eeef6a1798c7 | |
parent | eaf394f1de8f6bbaf761e96212ccf0eabc0f36ce (diff) |
Add Screen struct
-rw-r--r-- | src/isogfx.c | 78 |
1 files changed, 41 insertions, 37 deletions
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 { | |||
32 | // Renderer state. | 32 | // Renderer state. |
33 | // ----------------------------------------------------------------------------- | 33 | // ----------------------------------------------------------------------------- |
34 | 34 | ||
35 | // TODO: Define a struct Screen with width, height and pixels. | 35 | typedef struct Screen { |
36 | int width; | ||
37 | int height; | ||
38 | Pixel* pixels; | ||
39 | } Screen; | ||
36 | 40 | ||
37 | typedef struct SpriteInstance { | 41 | typedef struct SpriteInstance { |
38 | struct SpriteInstance* next; | 42 | struct SpriteInstance* next; |
@@ -43,11 +47,9 @@ typedef struct SpriteInstance { | |||
43 | } SpriteInstance; | 47 | } SpriteInstance; |
44 | 48 | ||
45 | typedef struct IsoGfx { | 49 | typedef struct IsoGfx { |
46 | int screen_width; | 50 | Screen screen; |
47 | int screen_height; | ||
48 | double last_animation_time; | 51 | double last_animation_time; |
49 | Tile next_tile; // For procedurally-generated tiles. | 52 | Tile next_tile; // For procedurally-generated tiles. |
50 | Pixel* screen; | ||
51 | Tm_Map* map; | 53 | Tm_Map* map; |
52 | Ts_TileSet* tileset; | 54 | Ts_TileSet* tileset; |
53 | SpriteInstance* head_sprite; // Head of sprites list. | 55 | SpriteInstance* head_sprite; // Head of sprites list. |
@@ -90,21 +92,21 @@ static inline vec2 cart2iso(vec2 cart, int s, int t, int w) { | |||
90 | } | 92 | } |
91 | 93 | ||
92 | static inline const Pixel* screen_xy_const_ref( | 94 | static inline const Pixel* screen_xy_const_ref( |
93 | const IsoGfx* iso, int x, int y) { | 95 | const Screen* screen, int x, int y) { |
94 | assert(iso); | 96 | assert(screen); |
95 | assert(x >= 0); | 97 | assert(x >= 0); |
96 | assert(y >= 0); | 98 | assert(y >= 0); |
97 | assert(x < iso->screen_width); | 99 | assert(x < screen->width); |
98 | assert(y < iso->screen_height); | 100 | assert(y < screen->height); |
99 | return &iso->screen[y * iso->screen_width + x]; | 101 | return &screen->pixels[y * screen->width + x]; |
100 | } | 102 | } |
101 | 103 | ||
102 | static inline Pixel screen_xy(IsoGfx* iso, int x, int y) { | 104 | static inline Pixel screen_xy(Screen* screen, int x, int y) { |
103 | return *screen_xy_const_ref(iso, x, y); | 105 | return *screen_xy_const_ref(screen, x, y); |
104 | } | 106 | } |
105 | 107 | ||
106 | static inline Pixel* screen_xy_mut(IsoGfx* iso, int x, int y) { | 108 | static inline Pixel* screen_xy_mut(Screen* screen, int x, int y) { |
107 | return (Pixel*)screen_xy_const_ref(iso, x, y); | 109 | return (Pixel*)screen_xy_const_ref(screen, x, y); |
108 | } | 110 | } |
109 | 111 | ||
110 | // ----------------------------------------------------------------------------- | 112 | // ----------------------------------------------------------------------------- |
@@ -126,16 +128,17 @@ IsoGfx* isogfx_new(const IsoGfxDesc* desc) { | |||
126 | memstack_alloc_aligned(&tmp.stack, sizeof(IsoGfx), alignof(IsoGfx)); | 128 | memstack_alloc_aligned(&tmp.stack, sizeof(IsoGfx), alignof(IsoGfx)); |
127 | *iso = tmp; | 129 | *iso = tmp; |
128 | 130 | ||
129 | iso->screen_width = desc->screen_width; | ||
130 | iso->screen_height = desc->screen_height; | ||
131 | iso->last_animation_time = 0.0; | ||
132 | |||
133 | const size_t screen_size_bytes = | 131 | const size_t screen_size_bytes = |
134 | desc->screen_width * desc->screen_height * sizeof(Pixel); | 132 | desc->screen_width * desc->screen_height * sizeof(Pixel); |
135 | iso->screen = | 133 | Pixel* screen = |
136 | memstack_alloc_aligned(&iso->stack, screen_size_bytes, alignof(Pixel)); | 134 | memstack_alloc_aligned(&iso->stack, screen_size_bytes, alignof(Pixel)); |
137 | 135 | ||
138 | iso->watermark = memstack_watermark(&iso->stack); | 136 | iso->screen = (Screen){.width = desc->screen_width, |
137 | .height = desc->screen_height, | ||
138 | .pixels = screen}; | ||
139 | |||
140 | iso->last_animation_time = 0.0; | ||
141 | iso->watermark = memstack_watermark(&iso->stack); | ||
139 | 142 | ||
140 | return iso; | 143 | return iso; |
141 | 144 | ||
@@ -469,7 +472,7 @@ typedef struct CoordSystem { | |||
469 | /// expressed in the Cartesian system. | 472 | /// expressed in the Cartesian system. |
470 | static CoordSystem make_iso_coord_system(const IsoGfx* iso) { | 473 | static CoordSystem make_iso_coord_system(const IsoGfx* iso) { |
471 | assert(iso); | 474 | assert(iso); |
472 | const ivec2 o = {iso->screen_width / 2, 0}; | 475 | const ivec2 o = {iso->screen.width / 2, 0}; |
473 | const ivec2 x = { | 476 | const ivec2 x = { |
474 | .x = iso->map->base_tile_width / 2, .y = iso->map->base_tile_height / 2}; | 477 | .x = iso->map->base_tile_width / 2, .y = iso->map->base_tile_height / 2}; |
475 | const ivec2 y = { | 478 | const ivec2 y = { |
@@ -517,9 +520,9 @@ static Pixel alpha_blend(Pixel src, Pixel dst) { | |||
517 | /// 'pixels' is the palette and 'indices' the pixel indices. Otherwise, the | 520 | /// 'pixels' is the palette and 'indices' the pixel indices. Otherwise, the |
518 | /// image is assumed to be in plain RGBA format. | 521 | /// image is assumed to be in plain RGBA format. |
519 | static void draw_rect( | 522 | static void draw_rect( |
520 | IsoGfx* iso, ivec2 top_left, int rect_width, int rect_height, | 523 | Screen* screen, ivec2 top_left, int rect_width, int rect_height, |
521 | const Pixel* pixels, const uint8_t* indices) { | 524 | const Pixel* pixels, const uint8_t* indices) { |
522 | assert(iso); | 525 | assert(screen); |
523 | 526 | ||
524 | #define rect_pixel(X, Y) \ | 527 | #define rect_pixel(X, Y) \ |
525 | (indices ? pixels[indices[Y * rect_width + X]] : pixels[Y * rect_width + X]) | 528 | (indices ? pixels[indices[Y * rect_width + X]] : pixels[Y * rect_width + X]) |
@@ -532,16 +535,16 @@ static void draw_rect( | |||
532 | 535 | ||
533 | // Rect can exceed screen bounds, so clip along Y and X as we draw. | 536 | // Rect can exceed screen bounds, so clip along Y and X as we draw. |
534 | for (int py = py_offset; | 537 | for (int py = py_offset; |
535 | (py < rect_height) && (top_left.y + py < iso->screen_height); ++py) { | 538 | (py < rect_height) && (top_left.y + py < screen->height); ++py) { |
536 | const int sy = top_left.y + py; | 539 | const int sy = top_left.y + py; |
537 | for (int px = px_offset; | 540 | for (int px = px_offset; |
538 | (px < rect_width) && (top_left.x + px < iso->screen_width); ++px) { | 541 | (px < rect_width) && (top_left.x + px < screen->width); ++px) { |
539 | const Pixel colour = rect_pixel(px, py); | 542 | const Pixel colour = rect_pixel(px, py); |
540 | if (colour.a > 0) { | 543 | if (colour.a > 0) { |
541 | const int sx = top_left.x + px; | 544 | const int sx = top_left.x + px; |
542 | const Pixel dst = screen_xy(iso, sx, sy); | 545 | const Pixel dst = screen_xy(screen, sx, sy); |
543 | const Pixel final = alpha_blend(colour, dst); | 546 | const Pixel final = alpha_blend(colour, dst); |
544 | *screen_xy_mut(iso, sx, sy) = final; | 547 | *screen_xy_mut(screen, sx, sy) = final; |
545 | } | 548 | } |
546 | } | 549 | } |
547 | } | 550 | } |
@@ -567,16 +570,17 @@ static void draw_tile(IsoGfx* iso, ivec2 screen_origin, Tile tile) { | |||
567 | pTile->height - iso->map->base_tile_height}; | 570 | pTile->height - iso->map->base_tile_height}; |
568 | const ivec2 top_left = ivec2_add(screen_origin, offset); | 571 | const ivec2 top_left = ivec2_add(screen_origin, offset); |
569 | 572 | ||
570 | draw_rect(iso, top_left, pTile->width, pTile->height, pixels, 0); | 573 | draw_rect( |
574 | &iso->screen, top_left, pTile->width, pTile->height, pixels, nullptr); | ||
571 | } | 575 | } |
572 | 576 | ||
573 | static void draw_world(IsoGfx* iso) { | 577 | static void draw_world(IsoGfx* iso) { |
574 | assert(iso); | 578 | assert(iso); |
575 | 579 | ||
576 | const int W = iso->screen_width; | 580 | const int W = iso->screen.width; |
577 | const int H = iso->screen_height; | 581 | const int H = iso->screen.height; |
578 | 582 | ||
579 | memset(iso->screen, 0, W * H * sizeof(Pixel)); | 583 | memset(iso->screen.pixels, 0, W * H * sizeof(Pixel)); |
580 | 584 | ||
581 | const CoordSystem iso_space = make_iso_coord_system(iso); | 585 | const CoordSystem iso_space = make_iso_coord_system(iso); |
582 | 586 | ||
@@ -609,7 +613,7 @@ static void draw_sprite( | |||
609 | const Ss_Row* row = ss_get_sprite_sheet_row(sheet, sprite->animation); | 613 | const Ss_Row* row = ss_get_sprite_sheet_row(sheet, sprite->animation); |
610 | const uint8_t* frame = ss_get_sprite_sheet_sprite(sheet, row, sprite->frame); | 614 | const uint8_t* frame = ss_get_sprite_sheet_sprite(sheet, row, sprite->frame); |
611 | draw_rect( | 615 | draw_rect( |
612 | iso, origin, sheet->sprite_width, sheet->sprite_height, | 616 | &iso->screen, origin, sheet->sprite_width, sheet->sprite_height, |
613 | sheet->palette.colours, frame); | 617 | sheet->palette.colours, frame); |
614 | } | 618 | } |
615 | 619 | ||
@@ -651,13 +655,13 @@ void isogfx_get_screen_size(const IsoGfx* iso, int* width, int* height) { | |||
651 | assert(iso); | 655 | assert(iso); |
652 | assert(width); | 656 | assert(width); |
653 | assert(height); | 657 | assert(height); |
654 | *width = iso->screen_width; | 658 | *width = iso->screen.width; |
655 | *height = iso->screen_height; | 659 | *height = iso->screen.height; |
656 | } | 660 | } |
657 | 661 | ||
658 | const Pixel* isogfx_get_screen_buffer(const IsoGfx* iso) { | 662 | const Pixel* isogfx_get_screen_buffer(const IsoGfx* iso) { |
659 | assert(iso); | 663 | assert(iso); |
660 | return iso->screen; | 664 | return iso->screen.pixels; |
661 | } | 665 | } |
662 | 666 | ||
663 | void isogfx_pick_tile( | 667 | void isogfx_pick_tile( |
@@ -668,7 +672,7 @@ void isogfx_pick_tile( | |||
668 | 672 | ||
669 | const vec2 xy_iso = cart2iso( | 673 | const vec2 xy_iso = cart2iso( |
670 | (vec2){.x = xcart, .y = ycart}, iso->map->base_tile_width, | 674 | (vec2){.x = xcart, .y = ycart}, iso->map->base_tile_width, |
671 | iso->map->base_tile_height, iso->screen_width); | 675 | iso->map->base_tile_height, iso->screen.width); |
672 | 676 | ||
673 | if ((0 <= xy_iso.x) && (xy_iso.x < iso->map->world_width) && | 677 | if ((0 <= xy_iso.x) && (xy_iso.x < iso->map->world_width) && |
674 | (0 <= xy_iso.y) && (xy_iso.y < iso->map->world_height)) { | 678 | (0 <= xy_iso.y) && (xy_iso.y < iso->map->world_height)) { |