diff --git a/CMakeLists.txt b/CMakeLists.txt index c8f9ec15..549d6e34 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -193,8 +193,8 @@ if (UNOPTIMIZED) set(COMPILER_FLAGS "${COMPILER_FLAGS} -O0 -DUNOPTIMIZED=1") set(LINKER_FLAGS "${LINKER_FLAGS} -O0") else() - set(COMPILER_FLAGS "${COMPILER_FLAGS} -O3 -flto") - set(LINKER_FLAGS "${LINKER_FLAGS} -O3 -flto -fwhole-program") + set(COMPILER_FLAGS "${COMPILER_FLAGS} -O3 -flto -fwhole-program") + set(LINKER_FLAGS "${LINKER_FLAGS} -O3 -flto -fwhole-program") endif() # Debug info diff --git a/res/graphics/timmy.ase b/res/graphics/tim.ase similarity index 100% rename from res/graphics/timmy.ase rename to res/graphics/tim.ase diff --git a/src/entity.c b/src/entity.c index 21e2c832..0f94a948 100644 --- a/src/entity.c +++ b/src/entity.c @@ -1,5 +1,43 @@ #include "entity.h" -READONLY struct entity _g_entity_nil = { - 0 -}; +READONLY struct entity _g_entity_nil = { 0 }; + +/* ========================== * + * Prop + * ========================== */ + +void entity_enable_prop(struct entity *entity, enum entity_prop prop) +{ + u64 index = prop / 64; + u64 bit = prop % 64; + entity->props[index] |= ((u64)1 << bit); +} + +void entity_disable_prop(struct entity *entity, enum entity_prop prop) +{ + u64 index = prop / 64; + u64 bit = prop % 64; + entity->props[index] &= ~((u64)1 << bit); +} + +b32 entity_has_prop(struct entity *entity, enum entity_prop prop) +{ + u64 index = prop / 64; + u64 bit = prop % 64; + 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; +} diff --git a/src/entity.h b/src/entity.h index 3dd26c76..e26400e2 100644 --- a/src/entity.h +++ b/src/entity.h @@ -93,11 +93,16 @@ struct entity { struct mixer_track_handle sound_handle; /* ====================================================================== */ - /* ENTITY_PROP_CAMERA */ + /* ENTITY_PROP_CAMERA */ + b32 camera_active; struct entity_handle camera_follow; + f32 camera_rot; + f32 camera_zoom; }; +/* Nil entity */ + extern READONLY struct entity _g_entity_nil; INLINE READONLY struct entity *entity_nil(void) @@ -105,46 +110,17 @@ INLINE READONLY struct entity *entity_nil(void) return &_g_entity_nil; } -/* ========================== * - * Prop - * ========================== */ +/* Prop */ -INLINE void entity_enable_prop(struct entity *entity, enum entity_prop prop) { - u64 index = prop / 64; - u64 bit = prop % 64; - entity->props[index] |= ((u64)1 << bit); -} +void entity_enable_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); -INLINE void entity_disable_prop(struct entity *entity, enum entity_prop prop) -{ - u64 index = prop / 64; - u64 bit = prop % 64; - entity->props[index] &= ~((u64)1 << bit); -} - -INLINE b32 entity_has_prop(struct entity *entity, enum entity_prop prop) -{ - u64 index = prop / 64; - u64 bit = prop % 64; - return !!(entity->props[index] & ((u64)1 << bit)); -} - -/* ========================== * - * Animation - * ========================== */ - -/* TODO: Move this kind of stuff to game_thread? */ +/* Animation */ #define ANIMATION_FLAG_NONE 0x0 #define ANIMATION_FLAG_LOOPING 0x1 -INLINE 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; -} +void entity_start_animation(struct entity *entity, struct string animation_name, u64 flags); #endif diff --git a/src/game.c b/src/game.c index 1624d1d1..3f816d98 100644 --- a/src/game.c +++ b/src/game.c @@ -10,7 +10,7 @@ #include "math.h" #include "scratch.h" -#define GAME_FPS 30 +#define GAME_FPS 50 GLOBAL struct { b32 shutdown; @@ -151,13 +151,6 @@ INTERNAL void game_update(void) struct temp_arena scratch = scratch_begin_no_conflict(); -#if 0 - /* TODO: remove this (testing variable frame latency) */ - u32 rand = sys_rand_u32(); - u32 sleep_ms = rand % 500; - sys_sleep((f64)sleep_ms / 1000); -#endif - ++L.tick.id; L.tick.dt = max_f64(0.0, (1.0 / GAME_FPS) * L.timescale); L.tick.time += L.tick.dt; @@ -173,7 +166,7 @@ INTERNAL void game_update(void) struct entity *player_ent; { - struct string sprite_name = STR("res/graphics/timmy.ase"); + struct string sprite_name = STR("res/graphics/tim.ase"); struct sheet *sheet = sheet_load(sprite_name); f32 meters_width = sheet->image_size.x / PIXELS_PER_UNIT; @@ -194,7 +187,7 @@ INTERNAL void game_update(void) e->sprite_tint = COLOR_WHITE; entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED); - e->player_acceleration_magnitude = 6.f; + e->player_acceleration_magnitude = 4.f; e->drag = 5; player_ent = e; @@ -209,7 +202,11 @@ INTERNAL void game_update(void) e->valid = true; e->rel_trs = TRS(); + entity_enable_prop(e, ENTITY_PROP_CAMERA); + e->camera_active = true; e->camera_follow = player_ent->handle; + e->camera_zoom = 1; + } } @@ -366,13 +363,6 @@ break_animation: ent->test_start_rel_trs.t = L.tick.player_focus; } - /* ========================== * - * Update camera position - * ========================== */ - if (ent->camera_follow.gen) { - //struct entity * - } - /* ========================== * * Calculate xforms * ========================== */ @@ -413,7 +403,20 @@ break_animation: if (!ent->valid) continue; /* ========================== * - * Update sound emitter + * Update camera position + * ========================== */ + + if (entity_has_prop(ent, ENTITY_PROP_CAMERA)) { + struct entity *follow = entity_from_handle(ent->camera_follow); + + struct v2 pos = follow->rel_trs.t; + + ent->rel_trs.t = pos; + ent->world_xform = mat3x3_from_trs(ent->rel_trs); + } + + /* ========================== * + * Update sound emitters * ========================== */ if (entity_has_prop(ent, ENTITY_PROP_TEST_SOUND_EMITTER)) { diff --git a/src/tick.c b/src/tick.c new file mode 100644 index 00000000..23454046 --- /dev/null +++ b/src/tick.c @@ -0,0 +1,10 @@ +#include "tick.h" + +void tick_cpy(struct tick *dst, struct tick *src) +{ + __prof; + /* Copy non-entity fields */ + MEMCPY(dst, src, FIELD_OFFSETOF(struct tick, entities)); + /* Copy entities */ + MEMCPY(&dst->entities, &src->entities, sizeof(struct entity) * src->entities_count); +} diff --git a/src/tick.h b/src/tick.h index 03aeacf8..6651aec2 100644 --- a/src/tick.h +++ b/src/tick.h @@ -17,13 +17,6 @@ struct tick { struct entity entities[MAX_ENTITIES]; }; -INLINE void tick_cpy(struct tick *dst, struct tick *src) -{ - __prof; - /* Copy non-entity fields */ - MEMCPY(dst, src, FIELD_OFFSETOF(struct tick, entities)); - /* Copy entities */ - MEMCPY(&dst->entities, &src->entities, sizeof(struct entity) * src->entities_count); -} +void tick_cpy(struct tick *dst, struct tick *src); #endif diff --git a/src/user.c b/src/user.c index 0e698d53..246a2cb2 100644 --- a/src/user.c +++ b/src/user.c @@ -444,9 +444,13 @@ INTERNAL void user_update(void) struct entity *e1 = &t1->entities[i]; if (e0->handle.gen == e1->handle.gen && e0->continuity_gen == e1->continuity_gen) { e->rel_trs = trs_lerp(e0->rel_trs, e1->rel_trs, tick_blend); + e->world_xform = mat3x3_lerp(e0->world_xform, e1->world_xform, tick_blend); + e->sprite_trs = trs_lerp(e0->sprite_trs, e1->sprite_trs, tick_blend); e->sprite_pivot_norm = v2_lerp(e0->sprite_pivot_norm, e1->sprite_pivot_norm, tick_blend); - e->world_xform = mat3x3_lerp(e0->world_xform, e1->world_xform, tick_blend); + + e->camera_rot = math_lerp_angle(e0->camera_rot, e1->camera_rot, tick_blend); + e->camera_zoom = math_lerp_f32(e0->camera_rot, e1->camera_rot, tick_blend); } } @@ -505,6 +509,19 @@ INTERNAL void user_update(void) struct entity *ent = &tick->entities[entity_index]; if (!ent->valid) continue; + /* Update view */ + if (entity_has_prop(ent, ENTITY_PROP_CAMERA)) { + if (ent->camera_active) { + struct v2 center = mat3x3_get_pos(ent->world_xform); + f32 rot = ent->camera_rot; + f32 zoom = ent->camera_zoom; + zoom = zoom > 0 ? zoom : 1.0; + L.world_view.center = center; + L.world_view.rot = rot; + L.world_view.zoom = 1; + } + } + /* Draw sprite */ if (ent->sprite_name.len > 0) { struct string tex_name = ent->sprite_name;