sprite tag / animating logic touchup
This commit is contained in:
parent
6b21649c74
commit
ed9841c1b1
BIN
res/graphics/tim.ase
(Stored with Git LFS)
BIN
res/graphics/tim.ase
(Stored with Git LFS)
Binary file not shown.
@ -910,6 +910,7 @@ struct ase_decode_sheet_result ase_decode_sheet(struct arena *arena, struct buff
|
|||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
|
|
||||||
res.image_size = V2(image_width, image_height);
|
res.image_size = V2(image_width, image_height);
|
||||||
|
res.frame_size = V2(frame_width, frame_height);
|
||||||
res.num_frames = num_frames;
|
res.num_frames = num_frames;
|
||||||
res.num_tags = num_tags;
|
res.num_tags = num_tags;
|
||||||
res.frame_head = frame_head;
|
res.frame_head = frame_head;
|
||||||
|
|||||||
@ -23,6 +23,7 @@ struct ase_decode_image_result {
|
|||||||
|
|
||||||
struct ase_decode_sheet_result {
|
struct ase_decode_sheet_result {
|
||||||
struct v2 image_size;
|
struct v2 image_size;
|
||||||
|
struct v2 frame_size;
|
||||||
u32 num_frames;
|
u32 num_frames;
|
||||||
u32 num_tags;
|
u32 num_tags;
|
||||||
struct ase_frame *frame_head;
|
struct ase_frame *frame_head;
|
||||||
|
|||||||
15
src/entity.c
15
src/entity.c
@ -26,18 +26,3 @@ b32 entity_has_prop(struct entity *entity, enum entity_prop prop)
|
|||||||
u64 bit = prop % 64;
|
u64 bit = prop % 64;
|
||||||
return !!(entity->props[index] & ((u64)1 << bit));
|
return !!(entity->props[index] & ((u64)1 << bit));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
|
||||||
* Animation
|
|
||||||
* ========================== */
|
|
||||||
|
|
||||||
/* TODO: Move this to game */
|
|
||||||
|
|
||||||
void entity_start_animation(struct entity *entity, struct string animation_name, u64 flags)
|
|
||||||
{
|
|
||||||
entity_enable_prop(entity, ENTITY_PROP_SPRITE_ANIMATED);
|
|
||||||
entity->animation_name = animation_name;
|
|
||||||
entity->animation_flags = flags;
|
|
||||||
entity->animation_time_in_frame = 0;
|
|
||||||
++entity->animation_start_gen;
|
|
||||||
}
|
|
||||||
|
|||||||
21
src/entity.h
21
src/entity.h
@ -16,7 +16,7 @@ struct entity_handle {
|
|||||||
enum entity_prop {
|
enum entity_prop {
|
||||||
ENTITY_PROP_NONE,
|
ENTITY_PROP_NONE,
|
||||||
|
|
||||||
ENTITY_PROP_SPRITE_ANIMATED,
|
ENTITY_PROP_ANIMATING,
|
||||||
ENTITY_PROP_PLAYER_CONTROLLED,
|
ENTITY_PROP_PLAYER_CONTROLLED,
|
||||||
ENTITY_PROP_CAMERA,
|
ENTITY_PROP_CAMERA,
|
||||||
|
|
||||||
@ -48,7 +48,6 @@ struct entity {
|
|||||||
/* Translation, rotation, scale in relation to parent entity */
|
/* Translation, rotation, scale in relation to parent entity */
|
||||||
|
|
||||||
struct trs rel_trs;
|
struct trs rel_trs;
|
||||||
|
|
||||||
struct mat3x3 world_xform; /* Calculated post-physics */
|
struct mat3x3 world_xform; /* Calculated post-physics */
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
@ -65,6 +64,7 @@ struct entity {
|
|||||||
/* Sprite */
|
/* Sprite */
|
||||||
|
|
||||||
struct string sprite_name;
|
struct string sprite_name;
|
||||||
|
struct string sprite_tag_name;
|
||||||
struct trs sprite_trs;
|
struct trs sprite_trs;
|
||||||
struct v2 sprite_pivot_norm; /* Pivot x & y are each normalized about sprite dimensions. <0, 0> is center, <1, 1> is bottom right corner, etc. */
|
struct v2 sprite_pivot_norm; /* Pivot x & y are each normalized about sprite dimensions. <0, 0> is center, <1, 1> is bottom right corner, etc. */
|
||||||
u32 sprite_tint;
|
u32 sprite_tint;
|
||||||
@ -72,13 +72,9 @@ struct entity {
|
|||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Animation */
|
/* Animation */
|
||||||
|
|
||||||
/* ENTITY_PROP_SPRITE_ANIMATED */
|
/* ENTITY_PROP_ANIMATING */
|
||||||
struct string animation_name;
|
b32 animation_looping;
|
||||||
u64 animation_flags;
|
f64 animation_start_time; /* Calculated */
|
||||||
f64 animation_time_in_frame;
|
|
||||||
u64 animation_start_gen;
|
|
||||||
u64 animation_gen;
|
|
||||||
struct sheet_frame animation_frame;
|
|
||||||
|
|
||||||
/* ====================================================================== */
|
/* ====================================================================== */
|
||||||
/* Testing */
|
/* Testing */
|
||||||
@ -117,11 +113,4 @@ void entity_enable_prop(struct entity *entity, enum entity_prop prop);
|
|||||||
void entity_disable_prop(struct entity *entity, enum entity_prop prop);
|
void entity_disable_prop(struct entity *entity, enum entity_prop prop);
|
||||||
b32 entity_has_prop(struct entity *entity, enum entity_prop prop);
|
b32 entity_has_prop(struct entity *entity, enum entity_prop prop);
|
||||||
|
|
||||||
/* Animation */
|
|
||||||
|
|
||||||
#define ANIMATION_FLAG_NONE 0x0
|
|
||||||
#define ANIMATION_FLAG_LOOPING 0x1
|
|
||||||
|
|
||||||
void entity_start_animation(struct entity *entity, struct string animation_name, u64 flags);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
64
src/game.c
64
src/game.c
@ -167,10 +167,11 @@ INTERNAL void game_update(void)
|
|||||||
{
|
{
|
||||||
|
|
||||||
struct string sprite_name = STR("res/graphics/tim.ase");
|
struct string sprite_name = STR("res/graphics/tim.ase");
|
||||||
|
struct string sprite_tag_name = STR("UNARMED");
|
||||||
|
|
||||||
struct sheet *sheet = sheet_load(sprite_name);
|
struct sheet *sheet = sheet_load(sprite_name);
|
||||||
f32 meters_width = sheet->image_size.x / PIXELS_PER_UNIT;
|
f32 meters_width = sheet->frame_size.x / PIXELS_PER_UNIT;
|
||||||
f32 meters_height = sheet->image_size.y / PIXELS_PER_UNIT;
|
f32 meters_height = sheet->frame_size.y / PIXELS_PER_UNIT;
|
||||||
struct v2 sprite_size = V2(meters_width, meters_height);
|
struct v2 sprite_size = V2(meters_width, meters_height);
|
||||||
|
|
||||||
struct v2 pos = V2(0, 0);
|
struct v2 pos = V2(0, 0);
|
||||||
@ -181,6 +182,7 @@ INTERNAL void game_update(void)
|
|||||||
e->rel_trs = TRS(.t = pos, .r = 0, .s = V2(1, 1));
|
e->rel_trs = TRS(.t = pos, .r = 0, .s = V2(1, 1));
|
||||||
|
|
||||||
e->sprite_name = sprite_name;
|
e->sprite_name = sprite_name;
|
||||||
|
e->sprite_tag_name = sprite_tag_name;
|
||||||
e->sprite_trs = TRS(.s = sprite_size);
|
e->sprite_trs = TRS(.s = sprite_size);
|
||||||
e->sprite_pivot_norm = V2(0, 0.65);
|
e->sprite_pivot_norm = V2(0, 0.65);
|
||||||
//e->sprite_pivot_norm = V2(0.4, 0.65);
|
//e->sprite_pivot_norm = V2(0.4, 0.65);
|
||||||
@ -190,6 +192,9 @@ INTERNAL void game_update(void)
|
|||||||
e->player_max_speed = 5.f;
|
e->player_max_speed = 5.f;
|
||||||
e->player_acceleration = 15.0f;
|
e->player_acceleration = 15.0f;
|
||||||
|
|
||||||
|
entity_enable_prop(e, ENTITY_PROP_ANIMATING);
|
||||||
|
e->animation_looping = true;
|
||||||
|
|
||||||
player_ent = e;
|
player_ent = e;
|
||||||
|
|
||||||
//entity_enable_prop(e, ENTITY_PROP_TEST);
|
//entity_enable_prop(e, ENTITY_PROP_TEST);
|
||||||
@ -205,7 +210,7 @@ INTERNAL void game_update(void)
|
|||||||
entity_enable_prop(e, ENTITY_PROP_CAMERA);
|
entity_enable_prop(e, ENTITY_PROP_CAMERA);
|
||||||
e->camera_active = true;
|
e->camera_active = true;
|
||||||
e->camera_follow = player_ent->handle;
|
e->camera_follow = player_ent->handle;
|
||||||
e->camera_zoom = 1;
|
e->camera_zoom = 1.5;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -260,39 +265,46 @@ INTERNAL void game_update(void)
|
|||||||
ent->test_start_sprite_trs = ent->sprite_trs;
|
ent->test_start_sprite_trs = ent->sprite_trs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ENTITY_PROP_ANIMATING */
|
||||||
|
if (entity_has_prop(ent, ENTITY_PROP_ANIMATING) && ent->animation_start_time == 0) {
|
||||||
|
ent->animation_start_time = L.tick.time;
|
||||||
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
* Update animation
|
* Update animation
|
||||||
* ========================== */
|
* ========================== */
|
||||||
|
|
||||||
if (entity_has_prop(ent, ENTITY_PROP_SPRITE_ANIMATED)) {
|
if (ent->animation_start_time > 0) {
|
||||||
struct sheet *sheet = sheet_load(ent->sprite_name);
|
/* Stop animation if past duration and not looping */
|
||||||
struct sheet_tag tag = sheet_get_tag(sheet, ent->animation_name);
|
if (!ent->animation_looping) {
|
||||||
|
f64 time_in_anim = L.tick.time - ent->animation_start_time;
|
||||||
|
|
||||||
if (ent->animation_start_gen == ent->animation_gen) {
|
struct sheet *sheet = sheet_load(ent->sprite_name);
|
||||||
ent->animation_time_in_frame += L.tick.dt;
|
if (sheet) {
|
||||||
} else {
|
struct sheet_tag tag = sheet_get_tag(sheet, ent->sprite_tag_name);
|
||||||
ent->animation_frame = sheet_get_frame(sheet, tag.start);
|
|
||||||
ent->animation_start_gen = ent->animation_gen;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (ent->animation_frame.duration != 0 && ent->animation_time_in_frame > ent->animation_frame.duration) {
|
struct sheet_frame frame = { 0 };
|
||||||
u64 new_frame_index = ent->animation_frame.index + 1;
|
u64 frame_index = tag.start;
|
||||||
if (new_frame_index > tag.end) {
|
while (time_in_anim > 0) {
|
||||||
if (ent->animation_flags & ANIMATION_FLAG_LOOPING) {
|
frame = sheet_get_frame(sheet, frame_index);
|
||||||
/* Restart animation */
|
if (frame_index > tag.end) {
|
||||||
new_frame_index = tag.start;
|
entity_disable_prop(ent, ENTITY_PROP_ANIMATING);
|
||||||
} else {
|
ent->animation_start_time = 0;
|
||||||
/* End animation */
|
break;
|
||||||
entity_start_animation(ent, STR("Default"), ANIMATION_FLAG_LOOPING);
|
}
|
||||||
goto break_animation;
|
time_in_anim -= frame.duration;
|
||||||
|
++frame_index;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
entity_disable_prop(ent, ENTITY_PROP_ANIMATING);
|
||||||
|
ent->animation_start_time = 0;
|
||||||
}
|
}
|
||||||
ent->animation_frame = sheet_get_frame(sheet, new_frame_index);
|
|
||||||
ent->animation_time_in_frame -= ent->animation_frame.duration;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break_animation:
|
|
||||||
(UNUSED)0; /* Disable label at end of compound statement warning */
|
/* ========================== *
|
||||||
|
* Test
|
||||||
|
* ========================== */
|
||||||
|
|
||||||
/* ENTITY_PROP_TEST */
|
/* ENTITY_PROP_TEST */
|
||||||
if (entity_has_prop(ent, ENTITY_PROP_TEST)) {
|
if (entity_has_prop(ent, ENTITY_PROP_TEST)) {
|
||||||
|
|||||||
@ -331,6 +331,15 @@ INLINE struct v2 v2_norm(struct v2 a)
|
|||||||
return a;
|
return a;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
INLINE struct v2 v2_round(struct v2 a)
|
||||||
|
{
|
||||||
|
return V2(
|
||||||
|
(f32)math_round_f32(a.x),
|
||||||
|
(f32)math_round_f32(a.y)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
INLINE f32 v2_dot(struct v2 a, struct v2 b)
|
INLINE f32 v2_dot(struct v2 a, struct v2 b)
|
||||||
{
|
{
|
||||||
return a.x * b.x + a.y * b.y;
|
return a.x * b.x + a.y * b.y;
|
||||||
|
|||||||
@ -83,6 +83,7 @@ INTERNAL struct sheet sheet_from_ase(struct arena *arena, struct ase_decode_shee
|
|||||||
|
|
||||||
/* Init frames */
|
/* Init frames */
|
||||||
sheet.image_size = ase.image_size;
|
sheet.image_size = ase.image_size;
|
||||||
|
sheet.frame_size = ase.frame_size;
|
||||||
sheet.frames = arena_push_array_zero(arena, struct sheet_frame, ase.num_frames);
|
sheet.frames = arena_push_array_zero(arena, struct sheet_frame, ase.num_frames);
|
||||||
sheet.frames_count = ase.num_frames;
|
sheet.frames_count = ase.num_frames;
|
||||||
for (struct ase_frame *ase_frame = ase.frame_head; ase_frame; ase_frame = ase_frame->next) {
|
for (struct ase_frame *ase_frame = ase.frame_head; ase_frame; ase_frame = ase_frame->next) {
|
||||||
|
|||||||
@ -8,6 +8,7 @@ struct sheet_frame;
|
|||||||
|
|
||||||
struct sheet {
|
struct sheet {
|
||||||
struct v2 image_size;
|
struct v2 image_size;
|
||||||
|
struct v2 frame_size;
|
||||||
u32 frames_count;
|
u32 frames_count;
|
||||||
struct sheet_frame *frames;
|
struct sheet_frame *frames;
|
||||||
u32 tags_count;
|
u32 tags_count;
|
||||||
|
|||||||
84
src/user.c
84
src/user.c
@ -226,7 +226,13 @@ INTERNAL struct mat3x3 view_get_xform(struct view view)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
INTERNAL struct v2 view_inverse_point(struct view view, struct v2 p)
|
INTERNAL struct v2 view_xform_point(struct view view, struct v2 p)
|
||||||
|
{
|
||||||
|
struct mat3x3 mtx = view_get_xform(view);
|
||||||
|
return mat3x3_mul_v2(mtx, p);
|
||||||
|
}
|
||||||
|
|
||||||
|
INTERNAL struct v2 view_inverse_xform_point(struct view view, struct v2 p)
|
||||||
{
|
{
|
||||||
struct mat3x3 mtx_inverse = mat3x3_inverse(view_get_xform(view));
|
struct mat3x3 mtx_inverse = mat3x3_inverse(view_get_xform(view));
|
||||||
return mat3x3_mul_v2(mtx_inverse, p);
|
return mat3x3_mul_v2(mtx_inverse, p);
|
||||||
@ -234,7 +240,7 @@ INTERNAL struct v2 view_inverse_point(struct view view, struct v2 p)
|
|||||||
|
|
||||||
INTERNAL struct v2 view_mouse_pos(struct view view)
|
INTERNAL struct v2 view_mouse_pos(struct view view)
|
||||||
{
|
{
|
||||||
return view_inverse_point(view, L.screen_mouse);
|
return view_inverse_xform_point(view, L.screen_mouse);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ========================== *
|
/* ========================== *
|
||||||
@ -606,11 +612,33 @@ INTERNAL void user_update(void)
|
|||||||
if (texture) {
|
if (texture) {
|
||||||
u32 tint = ent->sprite_tint;
|
u32 tint = ent->sprite_tint;
|
||||||
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.texture = texture, .tint = tint);
|
struct draw_texture_params params = DRAW_TEXTURE_PARAMS(.texture = texture, .tint = tint);
|
||||||
if (entity_has_prop(ent, ENTITY_PROP_SPRITE_ANIMATED)) {
|
|
||||||
struct sheet_frame frame = ent->animation_frame;
|
struct sheet *sheet = sheet_load(ent->sprite_name);
|
||||||
|
if (sheet) {
|
||||||
|
struct sheet_tag tag = sheet_get_tag(sheet, ent->sprite_tag_name);
|
||||||
|
|
||||||
|
struct sheet_frame frame = sheet_get_frame(sheet, tag.start);
|
||||||
|
if (entity_has_prop(ent, ENTITY_PROP_ANIMATING)) {
|
||||||
|
b32 looping = ent->animation_looping;
|
||||||
|
f64 time_in_anim = tick->time - ent->animation_start_time;
|
||||||
|
|
||||||
|
u64 frame_index = tag.start;
|
||||||
|
while (time_in_anim > 0) {
|
||||||
|
frame = sheet_get_frame(sheet, frame_index);
|
||||||
|
time_in_anim -= frame.duration;
|
||||||
|
++frame_index;
|
||||||
|
if (frame_index > tag.end) {
|
||||||
|
frame_index = tag.start;
|
||||||
|
if (!looping) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
params.clip = frame.clip;
|
params.clip = frame.clip;
|
||||||
params = DRAW_TEXTURE_PARAMS(.texture = texture, .clip = frame.clip);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_texture_quad(L.world_canvas, params, quad);
|
draw_texture_quad(L.world_canvas, params, quad);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,22 +673,18 @@ INTERNAL void user_update(void)
|
|||||||
|
|
||||||
/* Debug draw info */
|
/* Debug draw info */
|
||||||
if (L.debug_draw && !is_camera) {
|
if (L.debug_draw && !is_camera) {
|
||||||
struct mat3x3 mtx = ent->world_xform;
|
|
||||||
struct trs trs = trs_from_mat3x3(mtx);
|
|
||||||
struct v2 velocity = ent->velocity;
|
|
||||||
struct v2 acceleration = ent->acceleration;
|
|
||||||
|
|
||||||
struct font *disp_font = font_load_async(STR("res/fonts/fixedsys.ttf"), 12.0f);
|
struct font *disp_font = font_load_async(STR("res/fonts/fixedsys.ttf"), 12.0f);
|
||||||
|
|
||||||
//f32 offset = 0.75;
|
|
||||||
//struct v2 dir = v2_mul(mat3x3_get_up(mtx), 0.5f);
|
|
||||||
//dir = v2_add(dir, v2_mul(v2_norm(dir), offset));
|
|
||||||
//struct v2 pos = v2_add(mat3x3_get_pos(mtx), dir);
|
|
||||||
|
|
||||||
f32 offset = 1.5;
|
|
||||||
struct v2 pos = v2_add(mat3x3_get_pos(mtx), v2_mul(V2(0, -1), offset));
|
|
||||||
|
|
||||||
if (disp_font) {
|
if (disp_font) {
|
||||||
|
struct mat3x3 mtx = ent->world_xform;
|
||||||
|
struct trs trs = trs_from_mat3x3(mtx);
|
||||||
|
struct v2 velocity = ent->velocity;
|
||||||
|
struct v2 acceleration = ent->acceleration;
|
||||||
|
|
||||||
|
f32 offset = 1;
|
||||||
|
struct v2 pos = v2_add(mat3x3_get_pos(mtx), v2_mul(V2(0, -1), offset));
|
||||||
|
pos = view_xform_point(L.world_view, pos);
|
||||||
|
pos = v2_round(pos);
|
||||||
|
|
||||||
struct string disp_name = ent->sprite_name;
|
struct string disp_name = ent->sprite_name;
|
||||||
|
|
||||||
struct string fmt = STR(
|
struct string fmt = STR(
|
||||||
@ -681,7 +705,7 @@ INTERNAL void user_update(void)
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
draw_text_ex(L.world_canvas, disp_font, pos, 1.0f / PIXELS_PER_UNIT, text);
|
draw_text(L.ui_canvas, disp_font, pos, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug_draw_xform(ent->world_xform);
|
debug_draw_xform(ent->world_xform);
|
||||||
@ -753,11 +777,21 @@ INTERNAL void user_update(void)
|
|||||||
|
|
||||||
/* Present */
|
/* Present */
|
||||||
i32 vsync = VSYNC_ENABLED;
|
i32 vsync = VSYNC_ENABLED;
|
||||||
struct renderer_canvas *canvases[] = {
|
|
||||||
L.world_canvas,
|
struct renderer_canvas **canvases = NULL;
|
||||||
L.ui_canvas
|
u64 canvases_count = 0;
|
||||||
};
|
|
||||||
renderer_canvas_present(canvases, ARRAY_COUNT(canvases), L.screen_size.x, L.screen_size.y, vsync);
|
if (t0->id <= 0 || t1->id <= 0) {
|
||||||
|
/* Don't render world on first frame */
|
||||||
|
struct renderer_canvas *present_canvases[] = { L.ui_canvas };
|
||||||
|
canvases = present_canvases;
|
||||||
|
canvases_count = ARRAY_COUNT(present_canvases);
|
||||||
|
} else {
|
||||||
|
struct renderer_canvas *present_canvases[] = { L.world_canvas, L.ui_canvas };
|
||||||
|
canvases = present_canvases;
|
||||||
|
canvases_count = ARRAY_COUNT(present_canvases);
|
||||||
|
}
|
||||||
|
renderer_canvas_present(canvases, canvases_count, L.screen_size.x, L.screen_size.y, vsync);
|
||||||
|
|
||||||
scratch_end(scratch);
|
scratch_end(scratch);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user