summaryrefslogtreecommitdiff
path: root/gfx-iso/src/isogfx.c
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2023-07-26 08:39:37 -0700
committer3gg <3gg@shellblade.net>2023-07-26 08:39:37 -0700
commitcef3385c2bee0b098a7795548345a9281ace008e (patch)
treeb594e9cc151a4ae7fd8b5732cf349eb01f37683d /gfx-iso/src/isogfx.c
parent48cef82988d6209987ae27fe29b72d7d5e402b3c (diff)
Add support for paletted sprites.
Diffstat (limited to 'gfx-iso/src/isogfx.c')
-rw-r--r--gfx-iso/src/isogfx.c65
1 files changed, 46 insertions, 19 deletions
diff --git a/gfx-iso/src/isogfx.c b/gfx-iso/src/isogfx.c
index 9ba1bec..4568375 100644
--- a/gfx-iso/src/isogfx.c
+++ b/gfx-iso/src/isogfx.c
@@ -100,26 +100,49 @@ static inline const Ts_Tile* ts_tileset_get_next_tile(
100/// The pixels of the row follow a "sprite-major" order. It contains the 100/// The pixels of the row follow a "sprite-major" order. It contains the
101/// 'sprite_width * sprite_height' pixels for the first column/sprite, then the 101/// 'sprite_width * sprite_height' pixels for the first column/sprite, then the
102/// second column/sprite, etc. 102/// second column/sprite, etc.
103///
104/// Pixels are 8-bit indices into the sprite sheet's colour palette.
103typedef struct Ss_Row { 105typedef struct Ss_Row {
104 uint16_t num_cols; /// Number of columns in this row. 106 uint16_t num_cols; /// Number of columns in this row.
105 Pixel pixels[1]; /// Count: num_cols * sprite_width * sprite_height. 107 uint8_t pixels[1]; /// Count: num_cols * sprite_width * sprite_height.
106} Ss_Row; 108} Ss_Row;
107 109
110typedef struct Ss_Palette {
111 uint16_t num_colours;
112 Pixel colours[1]; /// Count: num_colors.
113} Ss_Palette;
114
108/// Sprite sheet top-level data definition. 115/// Sprite sheet top-level data definition.
109/// 116///
110/// Sprite width and height are assumed constant throughout the sprite sheet. 117/// Sprite width and height are assumed constant throughout the sprite sheet.
111typedef struct Ss_SpriteSheet { 118typedef struct Ss_SpriteSheet {
112 uint16_t sprite_width; /// Sprite width in pixels. 119 uint16_t sprite_width; /// Sprite width in pixels.
113 uint16_t sprite_height; /// Sprite height in pixels. 120 uint16_t sprite_height; /// Sprite height in pixels.
114 uint16_t num_rows; 121 uint16_t num_rows;
115 Ss_Row rows[1]; /// Count: num_rows. 122 Ss_Palette palette; /// Variable size.
123 Ss_Row rows[1]; /// Count: num_rows. Variable offset.
116} Ss_SpriteSheet; 124} Ss_SpriteSheet;
117 125
118const Ss_Row* get_sprite_sheet_row(const Ss_SpriteSheet* sheet, int row) { 126static inline const Ss_Row* get_sprite_sheet_row(
127 const Ss_SpriteSheet* sheet, int row) {
119 assert(sheet); 128 assert(sheet);
120 assert(row >= 0); 129 assert(row >= 0);
121 assert(row < sheet->num_rows); 130 assert(row < sheet->num_rows);
122 return &sheet->rows[row]; 131 // Skip over the palette.
132 const Ss_Row* rows =
133 (const Ss_Row*)(&sheet->palette.colours[0] + sheet->palette.num_colours);
134 return &rows[row];
135}
136
137static inline const uint8_t* get_sprite_sheet_sprite(
138 const Ss_SpriteSheet* sheet, const Ss_Row* row, int col) {
139 assert(sheet);
140 assert(row);
141 assert(col >= 0);
142 assert(col < row->num_cols);
143 const int sprite_offset = col * sheet->sprite_width * sheet->sprite_height;
144 const uint8_t* sprite = &row->pixels[sprite_offset];
145 return sprite;
123} 146}
124 147
125// ----------------------------------------------------------------------------- 148// -----------------------------------------------------------------------------
@@ -732,11 +755,19 @@ static Pixel alpha_blend(Pixel src, Pixel dst) {
732/// 755///
733/// The rectangle's pixels are assumed to be arranged in a linear, row-major 756/// The rectangle's pixels are assumed to be arranged in a linear, row-major
734/// fashion. 757/// fashion.
758///
759/// If indices are given, then the image is assumed to be colour-paletted, where
760/// 'pixels' is the palette and 'indices' the pixel indices. Otherwise, the
761/// image is assumed to be in plain RGBA format.
735static void draw_rect( 762static void draw_rect(
736 IsoGfx* iso, ivec2 origin, int rect_width, int rect_height, 763 IsoGfx* iso, ivec2 origin, int rect_width, int rect_height,
737 const Pixel* pixels) { 764 const Pixel* pixels, const uint8_t* indices) {
738 assert(iso); 765 assert(iso);
739 766
767#define rect_pixel(x, y) \
768 (indices ? pixels[indices[py * rect_width + px]] \
769 : pixels[py * rect_width + px])
770
740 // Rect can exceed screen bounds, so we must clip it. 771 // Rect can exceed screen bounds, so we must clip it.
741#define max(a, b) (a > b ? a : b) 772#define max(a, b) (a > b ? a : b)
742 const int py_offset = max(0, rect_height - origin.y); 773 const int py_offset = max(0, rect_height - origin.y);
@@ -748,7 +779,7 @@ static void draw_rect(
748 const int sy = origin.y + py - py_offset; 779 const int sy = origin.y + py - py_offset;
749 for (int px = 0; (px < rect_width) && (origin.x + px < iso->screen_width); 780 for (int px = 0; (px < rect_width) && (origin.x + px < iso->screen_width);
750 ++px) { 781 ++px) {
751 const Pixel colour = pixels[py * rect_width + px]; 782 const Pixel colour = rect_pixel(px, py);
752 if (colour.a > 0) { 783 if (colour.a > 0) {
753 const int sx = origin.x + px; 784 const int sx = origin.x + px;
754 const Pixel dst = screen_xy(iso, sx, sy); 785 const Pixel dst = screen_xy(iso, sx, sy);
@@ -767,7 +798,7 @@ static void draw_tile(IsoGfx* iso, ivec2 origin, Tile tile) {
767 798
768 const Pixel* pixels = tile_xy_const_ref(iso, tile_data, 0, 0); 799 const Pixel* pixels = tile_xy_const_ref(iso, tile_data, 0, 0);
769 800
770 draw_rect(iso, origin, tile_data->width, tile_data->height, pixels); 801 draw_rect(iso, origin, tile_data->width, tile_data->height, pixels, 0);
771} 802}
772 803
773static void draw(IsoGfx* iso) { 804static void draw(IsoGfx* iso) {
@@ -807,15 +838,11 @@ static void draw_sprite(
807 assert(sprite->animation < sheet->num_rows); 838 assert(sprite->animation < sheet->num_rows);
808 assert(sprite->frame >= 0); 839 assert(sprite->frame >= 0);
809 840
810 const SpriteSheetRow* ss_row = &sheet->rows[sprite->animation]; 841 const SpriteSheetRow* row = get_sprite_sheet_row(sheet, sprite->animation);
811 assert(sprite->frame < ss_row->num_cols); 842 const uint8_t* frame = get_sprite_sheet_sprite(sheet, row, sprite->frame);
812 843 draw_rect(
813 const int sprite_offset = 844 iso, origin, sheet->sprite_width, sheet->sprite_height,
814 sprite->frame * sheet->sprite_width * sheet->sprite_height; 845 sheet->palette.colours, frame);
815
816 const Pixel* frame = &ss_row->pixels[sprite_offset];
817
818 draw_rect(iso, origin, sheet->sprite_width, sheet->sprite_height, frame);
819} 846}
820 847
821static void draw_sprites(IsoGfx* iso) { 848static void draw_sprites(IsoGfx* iso) {