From f6d942c6143a3a795a3350edb6a2a585be628bbf Mon Sep 17 00:00:00 2001 From: Nyeogmi Date: Mon, 26 Feb 2024 17:31:58 -0800 Subject: [PATCH] Load Ultimate Lizard Total Destruction spritesheet --- game/art/game_demo_sprites.h | 2 +- game/game.c | 10 ++++++++ pytools/spritesheet.py | 13 +++++++--- sys/sys_data.h | 5 ++++ sys/sys_graphics.c | 49 +++++++++++++++++++++++++++++++++--- sys/sys_graphics.h | 21 ++++++++++++++-- 6 files changed, 91 insertions(+), 9 deletions(-) diff --git a/game/art/game_demo_sprites.h b/game/art/game_demo_sprites.h index f400544..6cac699 100644 --- a/game/art/game_demo_sprites.h +++ b/game/art/game_demo_sprites.h @@ -3,6 +3,6 @@ #include "sys/sys.h" -sys_sprite game_demo_sprites[256]; +extern sys_spritesheet game_demo_sprites; #endif // CROCPARTY_GAME_DEMO_SPRITES_H \ No newline at end of file diff --git a/game/game.c b/game/game.c index f4930c1..bf7afe0 100644 --- a/game/game.c +++ b/game/game.c @@ -1,3 +1,4 @@ +#include "art/game_demo_sprites.h" #include "device/device.h" #include "game.h" #include "sys/sys.h" @@ -91,4 +92,13 @@ void game_draw() { sys_line_draw(x0, y0, x1, y1, 254); sys_print("Hello, blood\nsources!", x1, y1, 224); + sys_dpal_reset(); + + sys_sprite_draw_ext( + game_demo_sprites, + 0, + x1, y1-64, + 16, 8, + false, false + ); } diff --git a/pytools/spritesheet.py b/pytools/spritesheet.py index 344284b..7c5e139 100644 --- a/pytools/spritesheet.py +++ b/pytools/spritesheet.py @@ -6,7 +6,7 @@ import shared TEMPLATE = """ // generated code! be nice! #include "sys/sys.h" -sys_sprite {{spritesheet_name}}[{{n_sprites}}] = { +sys_sprite {{spritesheet_name}}_data[{{n_sprites}}] = { {% for sprite in sprites -%} { .pixels={ {% for row in sprite -%} @@ -15,11 +15,16 @@ sys_sprite {{spritesheet_name}}[{{n_sprites}}] = { } }{% if not loop.last %},{% endif %} {%- endfor %} }; +sys_spritesheet {{spritesheet_name}} = { + .sprites=&{{spritesheet_name}}_data, + .width={{width}}, + .height={{height}}, +}; """.lstrip() def main(spritesheet_name, n_sprites, key_color, fname_png, fname_c): - sprites = load_sprites(fname_png, key_color) + sprites, width, height = load_sprites(fname_png, key_color) assert(len(sprites) == n_sprites), f"must be exactly {n_sprites} sprites" with open(fname_c, "wt") as output: @@ -28,6 +33,8 @@ def main(spritesheet_name, n_sprites, key_color, fname_png, fname_c): spritesheet_name=spritesheet_name, n_sprites=n_sprites, sprites=sprites, + width=width, + height=height, ) ) @@ -49,7 +56,7 @@ def load_sprites(fname_png: str, key_color: int): pixels.append(row) sprites.append(pixels) - return sprites + return sprites, width//8, height//8 palette_colors = { diff --git a/sys/sys_data.h b/sys/sys_data.h index 51e7425..623121f 100644 --- a/sys/sys_data.h +++ b/sys/sys_data.h @@ -15,6 +15,11 @@ typedef uint64_t sys_glyph; typedef struct { sys_color pixels[SYS_SPRITE_H][SYS_SPRITE_W]; } sys_sprite; +typedef struct { + sys_sprite* sprites; + uint32_t width; + uint32_t height; +} sys_spritesheet; sys_screen_color sys_make_screen_color(uint8_t r, uint8_t g, uint8_t b); diff --git a/sys/sys_graphics.c b/sys/sys_graphics.c index 0dd78ec..c60cad3 100644 --- a/sys/sys_graphics.c +++ b/sys/sys_graphics.c @@ -11,7 +11,8 @@ void sys_pixel_internal_set(sys_i32 x, sys_i32 y, sys_color c); void sys_scanline_internal_set( sys_i32 x0, sys_i32 x1, sys_i32 y, sys_color c, bool fill ); -void sys_glyph_draw(sys_i32 x, sys_i32 y, sys_glyph g, sys_color c); +void sys_glyph_internal_draw(sys_i32 x, sys_i32 y, sys_glyph g, sys_color c); +void sys_sprite_internal_draw(sys_i32 x, sys_i32 y, sys_sprite s); // == public == void sys_clip_set(sys_i32 x0, sys_i32 y0, sys_i32 x1, sys_i32 y1) { @@ -63,7 +64,7 @@ void sys_print(char* str, sys_i32 x, sys_i32 y, sys_color col) { if (c == 0) { break; } if (c == '\n') { x = x_orig; y += 8; continue; } if (c == '\r') { x = x_orig; continue; } - sys_glyph_draw(x, y, sys_font_small[c], col); + sys_glyph_internal_draw(x, y, sys_font_small[c], col); x += 8; } } @@ -232,6 +233,40 @@ void sys_dpal_reset() { } } +void sys_sprite_draw( + sys_spritesheet spritesheet, + sys_i32 n, + sys_i32 x, sys_i32 y +) { + sys_sprite_draw_ext( + spritesheet, + n, + x, y, + 1, 1, + false, false + ); +} + +void sys_sprite_draw_ext( + sys_spritesheet spritesheet, + sys_i32 n, + sys_i32 x, sys_i32 y, + sys_i32 w, sys_i32 h, + bool flip_x, bool flip_y +) { + // map n to a specific entity on the spritesheet + // (this is necessary for w and h) + for (int sy = 0; sy < h; sy++) { + for (int sx = 0; sx < w; sx++) { + sys_i32 tile = n + sx + sy * spritesheet.width; + if (tile < 0 || tile >= spritesheet.width * spritesheet.height) { + continue; + } + sys_sprite_internal_draw(x + sx * 8, y + sy * 8, spritesheet.sprites[tile]); + } + } +} + // == internal primitives == void sys_pixel_internal_set(sys_i32 x, sys_i32 y, sys_color c) { sys_color realc = sys_dpal[c]; @@ -265,7 +300,7 @@ void sys_scanline_internal_set( } } -void sys_glyph_draw(sys_i32 x, sys_i32 y, sys_glyph g, sys_color c) { +void sys_glyph_internal_draw(sys_i32 x, sys_i32 y, sys_glyph g, sys_color c) { // iterate through the bits of the glyph, and draw the character // if that bit is set for (int py = 0; py < 8; py++) { @@ -276,4 +311,12 @@ void sys_glyph_draw(sys_i32 x, sys_i32 y, sys_glyph g, sys_color c) { } } } +} + +void sys_sprite_internal_draw(sys_i32 x, sys_i32 y, sys_sprite s) { + for (int py = 0; py < 8; py++) { + for (int px = 0; px < 8; px++) { + sys_pixel_internal_set(x + px, y + py, s.pixels[py][px]); + } + } } \ No newline at end of file diff --git a/sys/sys_graphics.h b/sys/sys_graphics.h index 66f8d93..89cb854 100644 --- a/sys/sys_graphics.h +++ b/sys/sys_graphics.h @@ -83,7 +83,7 @@ void sys_camera_reset(); * * If r is negative, the circle is not drawn. * - * This is a special case of sys_circ_oval_draw_ext. + * This is a special case of sys_oval_draw_ext. */ void sys_circ_draw(sys_i32 x, sys_i32 y, sys_i32 r, sys_color c); void sys_circ_fill(sys_i32 x, sys_i32 y, sys_i32 r, sys_color c); @@ -146,7 +146,24 @@ void sys_dpal_set(sys_color c0, sys_color c1); */ void sys_dpal_reset(); -// TODO: SPR +/** + * Draw a given sprite. + * + * w, h default to 1. + * flip_x and flip_y default to false. + */ +void sys_sprite_draw( + sys_spritesheet spritesheet, + sys_i32 n, + sys_i32 x, sys_i32 y +); +void sys_sprite_draw_ext( + sys_spritesheet spritesheet, + sys_i32 n, + sys_i32 x, sys_i32 y, + sys_i32 w, sys_i32 h, + bool flip_x, bool flip_y +); // TODO: SSPR // TODO: FILLP?