Introduced configurable fixed time step

dev
Shariq Shah 6 years ago
parent e18b32a9a5
commit 4ccf09683e
  1. 2
      src/common/version.h
  2. 36
      src/game/enemy.c
  3. 1
      src/game/enemy.h
  4. 32
      src/game/game.c
  5. 1
      src/game/game.h
  6. 12
      src/game/player.c
  7. 2
      src/game/player.h
  8. 14
      src/game/scene.c
  9. 1
      src/game/scene.h
  10. 4
      src/system/config_vars.c
  11. 4
      todo.txt

@ -4,7 +4,7 @@
/* Auto generated version file. DO NOT MODIFY */
#define SYMMETRY_VERSION_MAJOR 0
#define SYMMETRY_VERSION_MINOR 1
#define SYMMETRY_VERSION_REVISION 318
#define SYMMETRY_VERSION_REVISION 319
#define SYMMETRY_VERSION_BRANCH "dev"
#endif

@ -8,11 +8,15 @@
#include "../common/hashmap.h"
#include "../common/parser.h"
#include "event.h"
#include "../system/platform.h"
#include "debug_vars.h"
#include <string.h>
#include <math.h>
static void enemy_on_scene_loaded(struct Event* event, void* enemy_ptr);
static void enemy_update_turret(struct Enemy* enemy, struct Game_State* game_state, float dt);
static void enemy_update_physics_turret(struct Enemy* enemy, struct Game_State* game_state, float fixed_dt);
static void enemy_update_ai_turret(struct Enemy* enemy, struct Game_State* game_state, float dt);
void enemy_init(struct Enemy* enemy, int type)
{
@ -77,7 +81,17 @@ void enemy_update(struct Enemy* enemy, struct Scene* scene, float dt)
switch(enemy->type)
{
case ENEMY_TURRET: enemy_update_turret(enemy, game_state, dt); break;
case ENEMY_TURRET: enemy_update_ai_turret(enemy, game_state, dt); break;
}
}
void enemy_update_physics(struct Enemy* enemy, struct Scene* scene, float fixed_dt)
{
struct Game_State* game_state = game_state_get();
switch(enemy->type)
{
case ENEMY_TURRET: enemy_update_physics_turret(enemy, game_state, fixed_dt); break;
}
}
@ -160,8 +174,9 @@ void enemy_on_scene_loaded(struct Event* event, void* enemy_ptr)
// Do other post-scene-load initialization stuff per enemy type here
}
void enemy_update_turret(struct Enemy* enemy, struct Game_State* game_state, float dt)
void enemy_update_physics_turret(struct Enemy* enemy, struct Game_State* game_state, float dt)
{
/* Turning/Rotation */
static vec3 turn_axis = { 0.f, 1.f, 0.f };
float current_yaw = quat_get_yaw(&enemy->base.transform.rotation);
@ -183,4 +198,19 @@ void enemy_update_turret(struct Enemy* enemy, struct Game_State* game_state, flo
if(yaw != 0.f)
transform_rotate(enemy, &turn_axis, yaw, TS_LOCAL);
/* Movement */
float ticks = (float)platform_ticks_get();
float pulsate_speed = 50.f;
vec3 translation = { 0.f };
transform_get_absolute_position(enemy, &translation);
translation.y += sinf(TO_RADIANS(ticks)) * dt * pulsate_speed;
debug_vars_show_float("T", sinf(TO_RADIANS(ticks * dt * pulsate_speed)));
transform_set_position(enemy, &translation);
//transform_translate(enemy, &translation, TS_LOCAL);
}
void enemy_update_ai_turret(struct Enemy* enemy, struct Game_State* game_state, float dt)
{
}

@ -8,6 +8,7 @@ struct Entity;
struct Hashmap;
void enemy_init(struct Enemy* enemy, int type);
void enemy_update_physics(struct Enemy* enemy, struct Scene* scene, float dt);
void enemy_update(struct Enemy* enemy, struct Scene* scene, float dt);
void enemy_reset(struct Enemy* enemy);
struct Enemy* enemy_read(struct Parser_Object* object, const char* name, struct Entity* parent_entity);

@ -43,6 +43,7 @@
#define LEN(a) (sizeof(a)/sizeof(a)[0])
static void game_update(float dt, bool* window_should_close);
static void game_update_physics(float fixed_dt);
static void game_post_update(float dt);
static void game_render(void);
static void game_debug(float dt);
@ -69,6 +70,7 @@ bool game_init(struct Window* window, struct Hashmap* cvars)
game_state->window = window;
game_state->cvars = cvars;
game_state->is_initialized = false;
game_state->fixed_delta_time = 1.f / 60.f;
game_state->game_mode = GAME_MODE_GAME;
game_state->renderer = calloc(1, sizeof(*game_state->renderer));
game_state->scene = calloc(1, sizeof(*game_state->scene));
@ -512,21 +514,31 @@ void game_debug(float dt)
bool game_run(void)
{
uint32 last_time = platform_ticks_get();
uint32 previous_time = platform_ticks_get();
float accumulator = 0.f;
bool should_window_close = false;
while(!should_window_close)
{
uint32 curr_time = platform_ticks_get();
float delta_time = (float)(curr_time - last_time) / 1000.f;
last_time = curr_time;
if(delta_time > MAX_FRAME_TIME) delta_time = (1.f / 60.f); /* To deal with resuming from breakpoint we artificially set delta time */
uint32 current_time = platform_ticks_get();
float frame_time = (float)(current_time - previous_time) / 1000.f;
previous_time = current_time;
if(frame_time > MAX_FRAME_TIME) frame_time = (1.f / 60.f); /* To deal with resuming from breakpoint we artificially set delta time */
accumulator += frame_time;
gui_input_begin(game_state->gui);
event_manager_poll_events(game_state->event_manager, &should_window_close);
gui_input_end(game_state->gui);
game_update(delta_time, &should_window_close);
game_post_update(delta_time);
struct Game_State* game_state = game_state_get();
while(accumulator >= game_state->fixed_delta_time)
{
game_update_physics(game_state->fixed_delta_time);
accumulator -= game_state->fixed_delta_time;
}
game_update(frame_time, &should_window_close);
game_post_update(frame_time);
game_render();
window_swap_buffers(game_state->window);
}
@ -1983,3 +1995,9 @@ void game_on_log_error(const char* context, const char* error_message, va_list a
{
console_on_log_error(game_state->console, context, error_message, args);
}
void game_update_physics(float fixed_dt)
{
struct Game_State* game_state = game_state_get();
scene_update_physics(game_state->scene, fixed_dt);
}

@ -25,6 +25,7 @@ struct Game_State
{
bool is_initialized;
int game_mode;
float fixed_delta_time;
struct Window* window;
struct Renderer* renderer;
struct Scene* scene;

@ -80,7 +80,7 @@ void player_destroy(struct Player* player)
player->base.flags = EF_NONE;
}
void player_update(struct Player* player, struct Scene* scene, float dt)
void player_update_physics(struct Player* player, struct Scene* scene, float fixed_dt)
{
/* Look around */
float total_pitch = quat_get_pitch(&player->camera->base.transform.rotation);
@ -103,8 +103,8 @@ void player_update(struct Player* player, struct Scene* scene, float dt)
cursor_yaw = cursor_pitch = 0;
}
pitch = -cursor_pitch * player->turn_speed * dt;
yaw = cursor_yaw * player->turn_speed * dt;
pitch = -cursor_pitch * player->turn_speed * fixed_dt;
yaw = cursor_yaw * player->turn_speed * fixed_dt;
total_pitch += pitch;
if(total_pitch >= max_pitch)
@ -221,9 +221,9 @@ void player_update(struct Player* player, struct Scene* scene, float dt)
vec3 translation = {0.f, 0.f, 0.f};
vec3_assign(&translation, &move_direction);
translation.x *= move_speed * dt;
translation.z *= move_speed * dt;
translation.y = move_speed_vertical * dt;
translation.x *= move_speed * fixed_dt;
translation.z *= move_speed * fixed_dt;
translation.y = move_speed_vertical * fixed_dt;
transform_translate(player, &translation, TS_WORLD);
debug_vars_show_bool("Grounded", player->grounded);

@ -6,6 +6,6 @@ struct Scene;
void player_init(struct Player* player, struct Scene* scene);
void player_destroy(struct Player* player);
void player_update(struct Player* player, struct Scene* scene, float dt);
void player_update_physics(struct Player* player, struct Scene* scene, float dt);
#endif

@ -366,7 +366,6 @@ void scene_update(struct Scene* scene, float dt)
{
if(game_state_get()->game_mode == GAME_MODE_GAME)
{
player_update(&scene->player, scene, dt);
for(int i = 0; i < MAX_SCENE_ENEMIES; i++)
{
if(scene->enemies[i].base.flags & EF_ACTIVE)
@ -375,6 +374,19 @@ void scene_update(struct Scene* scene, float dt)
}
}
void scene_update_physics(struct Scene* scene, float fixed_dt)
{
if(game_state_get()->game_mode == GAME_MODE_GAME)
{
player_update_physics(&scene->player, scene, fixed_dt);
for(int i = 0; i < MAX_SCENE_ENEMIES; i++)
{
if(scene->enemies[i].base.flags & EF_ACTIVE)
enemy_update_physics(&scene->enemies[i], scene, fixed_dt);
}
}
}
void scene_post_update(struct Scene* scene)
{
assert(scene);

@ -28,6 +28,7 @@ bool scene_load(struct Scene* scene, const char* filename, int directory_type);
bool scene_save(struct Scene* scene, const char* filename, int directory_type);
void scene_destroy(struct Scene* scene);
void scene_update(struct Scene* scene, float dt);
void scene_update_physics(struct Scene* scene, float fixed_dt);
void scene_post_update(struct Scene* scene);
struct Entity* scene_entity_duplicate(struct Scene* scene, struct Entity* entity);

@ -31,9 +31,9 @@ void config_vars_init(struct Hashmap* cvars)
hashmap_vec4_setf(cvars, "debug_draw_color", 0.8f, 0.4f, 0.1f, 1.f);
hashmap_float_set(cvars, "player_move_speed", 20.f);
hashmap_float_set(cvars, "player_move_speed_multiplier", 1.75f);
hashmap_float_set(cvars, "player_turn_speed", 45.f);
hashmap_float_set(cvars, "player_turn_speed", 25.f);
hashmap_float_set(cvars, "player_jump_speed", 50.f);
hashmap_float_set(cvars, "player_gravity", -0.25f);
hashmap_float_set(cvars, "player_gravity", -2.5f);
hashmap_float_set(cvars, "player_min_forward_distance", 5.f);
hashmap_float_set(cvars, "player_min_downward_distance", 2.f);
}

@ -1,4 +1,6 @@
Todo:
- Make movement framerate independent
- Implement displaying bounding boxes as a command which should work in game mode
- Enemy ray casting and shooting
- Player shooting
- Player jump cooldown, don't allow jump until a certian time interval has passed, even if we're grounded
@ -13,6 +15,7 @@ Todo:
- Main Menu Scene
? Split this todo into gameplay/engine todos
- Check if running in a lower frame rate affects movement
- Remove ODE completely
? Write entity flags to scene file or when saving entity to file?
? Add scene init/de-init function hashmap that maps a function that should be called when scene is loaded and unloaded. Save this to file for every scene or map functions based on the name of the scene?
- Release mouse when window loses focus and limit fps
@ -406,3 +409,4 @@ Done:
* Imlemented reading/writing enemy mesh and weapon sound to file and resetting it in code
* Implemented on_load and on_update callbacks for enemies. Different enemy types have different callbacks that are assigned when they are created.
* Added Scene reload command
* Introduced fixed time step interval which can be configured and be used for movement and other physics related updates
Loading…
Cancel
Save