From 79bc261ccdc169ca69a3b6807a1a07c9da6da7e0 Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Sat, 27 Jul 2024 16:55:38 +0300 Subject: [PATCH] rendering.c: sprite rotation --- src/game/scenes/ingame.c | 17 ++++++ src/rendering.c | 1 + src/rendering/sprites.h | 120 +++++++++++++++++++++++++++------------ src/util.c | 8 +++ src/util.h | 47 +++++++-------- 5 files changed, 135 insertions(+), 58 deletions(-) diff --git a/src/game/scenes/ingame.c b/src/game/scenes/ingame.c index ad7d6f6..c4de337 100644 --- a/src/game/scenes/ingame.c +++ b/src/game/scenes/ingame.c @@ -11,6 +11,23 @@ static void ingame_tick(struct state *state) { world_drawdef(scn->world); player_calc(scn->player); + push_sprite_ex((t_frect){ .x = 32, .y = 32, .w = 64, .h = 64 }, (t_push_sprite_args){ + .path = "/assets/player/baron-walk.png", + .color = (t_color){255, 255, 255, 255}, + .rotation = (float)M_PI * 2 * (float)(ctx.tick_count % 64) / 64, + .blend = true }); + + push_sprite_ex((t_frect){ .x = 64, .y = 32, .w = 64, .h = 64 }, (t_push_sprite_args){ + .path = "/assets/player/baron-walk.png", + .color = (t_color){255, 255, 255, 255}, + .rotation = (float)M_PI / 64, + .blend = true }); + + push_sprite_ex((t_frect){ .x = 96, .y = 32, .w = 64, .h = 64 }, (t_push_sprite_args){ + .path = "/assets/player/baron-walk.png", + .color = (t_color){255, 255, 255, 255}, + .blend = true }); + unfurl_triangle("/assets/big-violet.png", (t_fvec3){ -1, -1, 0 }, (t_fvec3){ 1, -1, 0 }, diff --git a/src/rendering.c b/src/rendering.c index 1acecc2..a5d34cd 100644 --- a/src/rendering.c +++ b/src/rendering.c @@ -90,6 +90,7 @@ static void render_2d(void) { glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_ALWAYS); + glDepthRange((double)batch_count / UINT16_MAX, 1.0); glDisable(GL_ALPHA_TEST); render_sprites(current, batch.size, false); diff --git a/src/rendering/sprites.h b/src/rendering/sprites.h index 3995fb1..6c78b5b 100644 --- a/src/rendering/sprites.h +++ b/src/rendering/sprites.h @@ -135,45 +135,95 @@ static void render_sprites(const struct primitive_2d primitives[], const float xr = (float)srcrect.x / (float)dims.w; const float yr = (float)srcrect.y / (float)dims.h; - payload[i] = (struct sprite_primitive_payload) { - /* upper-left */ - .v0 = { - sprite.rect.x, - sprite.rect.y }, - .uv0 = { - xr + wr * sprite.flip_x, - yr + hr * sprite.flip_y, }, + /* non-rotated case */ + if (sprite.rotation == 0.0f) { + payload[i] = (struct sprite_primitive_payload) { + /* upper-left */ + .v0 = { + sprite.rect.x, + sprite.rect.y }, + .uv0 = { + xr + wr * sprite.flip_x, + yr + hr * sprite.flip_y, }, - /* bottom-left */ - .v1 = { - (sprite.rect.x), - (sprite.rect.y + sprite.rect.h) }, - .uv1 = { - xr + wr * sprite.flip_x, - yr + hr * !sprite.flip_y, }, + /* bottom-left */ + .v1 = { + (sprite.rect.x), + (sprite.rect.y + sprite.rect.h) }, + .uv1 = { + xr + wr * sprite.flip_x, + yr + hr * !sprite.flip_y, }, - /* bottom-right */ - .v2 = { - (sprite.rect.x + sprite.rect.w), - (sprite.rect.y + sprite.rect.h) }, - .uv2 = { - xr + wr * !sprite.flip_x, - yr + hr * !sprite.flip_y, }, + /* bottom-right */ + .v2 = { + (sprite.rect.x + sprite.rect.w), + (sprite.rect.y + sprite.rect.h) }, + .uv2 = { + xr + wr * !sprite.flip_x, + yr + hr * !sprite.flip_y, }, - /* upper-right */ - .v3 = { - (sprite.rect.x + sprite.rect.w), - (sprite.rect.y) }, - .uv3 = { - xr + wr * !sprite.flip_x, - yr + hr * sprite.flip_y, }, + /* upper-right */ + .v3 = { + (sprite.rect.x + sprite.rect.w), + (sprite.rect.y) }, + .uv3 = { + xr + wr * !sprite.flip_x, + yr + hr * sprite.flip_y, }, - /* equal for all (flat shaded) */ - .c0 = sprite.color, - .c1 = sprite.color, - .c2 = sprite.color, - .c3 = sprite.color, - }; + /* equal for all (flat shaded) */ + .c0 = sprite.color, + .c1 = sprite.color, + .c2 = sprite.color, + .c3 = sprite.color, + }; + } else { + /* rotated case */ + const t_fvec2 c = frect_center(sprite.rect); + const t_fvec2 d = { + .x = (cosf(sprite.rotation + (float)M_PI_4) * sprite.rect.w) * (float)M_SQRT1_2, + .y = (sinf(sprite.rotation + (float)M_PI_4) * sprite.rect.h) * (float)M_SQRT1_2, + }; + + payload[i] = (struct sprite_primitive_payload) { + /* upper-left */ + .v0 = { + c.x - d.x, + c.y - d.y }, + .uv0 = { + xr + wr * sprite.flip_x, + yr + hr * sprite.flip_y, }, + + /* bottom-left */ + .v1 = { + c.x - d.y, + c.y + d.x }, + .uv1 = { + xr + wr * sprite.flip_x, + yr + hr * !sprite.flip_y, }, + + /* bottom-right */ + .v2 = { + c.x + d.x, + c.y + d.y }, + .uv2 = { + xr + wr * !sprite.flip_x, + yr + hr * !sprite.flip_y, }, + + /* upper-right */ + .v3 = { + c.x + d.y, + c.y - d.x }, + .uv3 = { + xr + wr * !sprite.flip_x, + yr + hr * sprite.flip_y, }, + + /* equal for all (flat shaded) */ + .c0 = sprite.color, + .c1 = sprite.color, + .c2 = sprite.color, + .c3 = sprite.color, + }; + } } glUnmapBuffer(GL_ARRAY_BUFFER); diff --git a/src/util.c b/src/util.c index 9e49a64..b368957 100644 --- a/src/util.c +++ b/src/util.c @@ -186,6 +186,14 @@ t_frect to_frect(t_rect rect) { } +t_fvec2 frect_center(t_frect rect) { + return (t_fvec2){ + .x = rect.x + rect.w / 2, + .y = rect.y + rect.h / 2, + }; +} + + t_fvec2 fvec2_from_vec2(t_vec2 vec) { return (t_fvec2) { .x = (float)vec.x, diff --git a/src/util.h b/src/util.h index 03be517..98b2fae 100644 --- a/src/util.h +++ b/src/util.h @@ -77,29 +77,6 @@ typedef struct color { } t_color; -/* a rectangle with the origin at the upper left (integer) */ -typedef struct rect { - int x, y; - int w, h; -} t_rect; - - -bool intersect_rect(const t_rect *a, const t_rect *b, t_rect *result); - - -/* a rectangle with the origin at the upper left (floating point) */ -typedef struct frect { - float x, y; - float w, h; -} t_frect; - - -bool intersect_frect(const t_frect *a, const t_frect *b, t_frect *result); - -/* TODO: generics and specials (see m_to_fvec2() for an example)*/ -t_frect to_frect(t_rect rect); - - /* a point in some space (integer) */ typedef struct vec2 { int x, y; @@ -125,6 +102,30 @@ typedef struct shvec2 { } t_shvec2; +/* a rectangle with the origin at the upper left (integer) */ +typedef struct rect { + int x, y; + int w, h; +} t_rect; + + +/* a rectangle with the origin at the upper left (floating point) */ +typedef struct frect { + float x, y; + float w, h; +} t_frect; + + +bool intersect_rect(const t_rect *a, const t_rect *b, t_rect *result); + +bool intersect_frect(const t_frect *a, const t_frect *b, t_frect *result); + +/* TODO: generics and specials (see m_to_fvec2() for an example)*/ +t_frect to_frect(t_rect rect); + +t_fvec2 frect_center(t_frect rect); + + /* aren't macros to prevent double evaluation with side effects */ /* maybe could be inlined? i hope LTO will resolve this */ t_fvec2 fvec2_from_vec2(t_vec2 vec);