rework to context: now there's engine and user code copies, renaming of fields, most things that shouldn't be there are hidden
This commit is contained in:
parent
7886650339
commit
e70366f82f
@ -17,7 +17,7 @@ void handle_input(void)
|
|||||||
{
|
{
|
||||||
State *state = ctx.udata;
|
State *state = ctx.udata;
|
||||||
|
|
||||||
if (ctx.mouse_window_position.y <= 60)
|
if (ctx.mouse_position.y <= 60)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (input_is_action_pressed("add_a_bit"))
|
if (input_is_action_pressed("add_a_bit"))
|
||||||
@ -27,10 +27,10 @@ void handle_input(void)
|
|||||||
if (state->bunniesCount < MAX_BUNNIES)
|
if (state->bunniesCount < MAX_BUNNIES)
|
||||||
{
|
{
|
||||||
state->bunnies[state->bunniesCount].position = input_get_action_position("add_a_bit");
|
state->bunnies[state->bunniesCount].position = input_get_action_position("add_a_bit");
|
||||||
state->bunnies[state->bunniesCount].speed.x = (float)(rand() % 500 - 250) / 60.0;
|
state->bunnies[state->bunniesCount].speed.x = (float)(rand() % 500 - 250) / 60.0f;
|
||||||
state->bunnies[state->bunniesCount].speed.y = (float)(rand() % 500 - 250) / 60.0;
|
state->bunnies[state->bunniesCount].speed.y = (float)(rand() % 500 - 250) / 60.0f;
|
||||||
state->bunnies[state->bunniesCount].color =
|
state->bunnies[state->bunniesCount].color =
|
||||||
(Color){rand() % 190 + 50, rand() % 160 + 80, rand() % 140 + 100, 255};
|
(Color){(uint8_t)(rand() % 190 + 50), (uint8_t)(rand() % 160 + 80), (uint8_t)(rand() % 140 + 100), 255};
|
||||||
state->bunniesCount++;
|
state->bunniesCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,10 +43,10 @@ void handle_input(void)
|
|||||||
if (state->bunniesCount < MAX_BUNNIES)
|
if (state->bunniesCount < MAX_BUNNIES)
|
||||||
{
|
{
|
||||||
state->bunnies[state->bunniesCount].position = input_get_action_position("add_a_lot");
|
state->bunnies[state->bunniesCount].position = input_get_action_position("add_a_lot");
|
||||||
state->bunnies[state->bunniesCount].speed.x = (float)(rand() % 500 - 250) / 60.0;
|
state->bunnies[state->bunniesCount].speed.x = (float)(rand() % 500 - 250) / 60.0f;
|
||||||
state->bunnies[state->bunniesCount].speed.y = (float)(rand() % 500 - 250) / 60.0;
|
state->bunnies[state->bunniesCount].speed.y = (float)(rand() % 500 - 250) / 60.0f;
|
||||||
state->bunnies[state->bunniesCount].color =
|
state->bunnies[state->bunniesCount].color =
|
||||||
(Color){rand() % 190 + 50, rand() % 160 + 80, rand() % 140 + 100, 255};
|
(Color){(uint8_t)(rand() % 190 + 50), (uint8_t)(rand() % 160 + 80), (uint8_t)(rand() % 140 + 100), 255};
|
||||||
state->bunniesCount++;
|
state->bunniesCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,32 +73,29 @@ void game_tick(void)
|
|||||||
|
|
||||||
State *state = ctx.udata;
|
State *state = ctx.udata;
|
||||||
|
|
||||||
const double delta =
|
|
||||||
(double)(ctx.delta_time) / 1000.0; // Receiving floating point delta value (diving by 1000 based on vibe)
|
|
||||||
|
|
||||||
for (int i = 0; i < state->bunniesCount; i++)
|
for (int i = 0; i < state->bunniesCount; i++)
|
||||||
{
|
{
|
||||||
state->bunnies[i].position.x += state->bunnies[i].speed.x;
|
state->bunnies[i].position.x += state->bunnies[i].speed.x;
|
||||||
state->bunnies[i].position.y += state->bunnies[i].speed.y;
|
state->bunnies[i].position.y += state->bunnies[i].speed.y;
|
||||||
|
|
||||||
if (((state->bunnies[i].position.x + BUNNY_W / 2) > ctx.base_draw_w) ||
|
if (((state->bunnies[i].position.x + (float)BUNNY_W / 2) > (float)ctx.resolution.x) ||
|
||||||
((state->bunnies[i].position.x + BUNNY_W / 2) < 0))
|
((state->bunnies[i].position.x + (float)BUNNY_W / 2) < 0))
|
||||||
state->bunnies[i].speed.x *= -1;
|
state->bunnies[i].speed.x *= -1;
|
||||||
if (((state->bunnies[i].position.y + BUNNY_H / 2) > ctx.base_draw_h) ||
|
if (((state->bunnies[i].position.y + (float)BUNNY_H / 2) > (float)ctx.resolution.y) ||
|
||||||
((state->bunnies[i].position.y + BUNNY_H / 2 - 60) < 0))
|
((state->bunnies[i].position.y + (float)BUNNY_H / 2 - 60) < 0))
|
||||||
state->bunnies[i].speed.y *= -1;
|
state->bunnies[i].speed.y *= -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle_input();
|
handle_input();
|
||||||
|
|
||||||
// Clear window with Gray color (set the background color this way)
|
// Clear window with Gray color (set the background color this way)
|
||||||
draw_rectangle((Rect){0, 0, ctx.base_draw_w, ctx.base_draw_h}, GRAY);
|
draw_rectangle((Rect){0, 0, (float)ctx.resolution.x, (float)ctx.resolution.y}, GRAY);
|
||||||
|
|
||||||
for (int i = 0; i < state->bunniesCount; i++)
|
for (int i = 0; i < state->bunniesCount; i++)
|
||||||
{ // Draw each bunny based on their position and color, also scale accordingly
|
{ // Draw each bunny based on their position and color, also scale accordingly
|
||||||
m_sprite(m_set(path, "wabbit_alpha.png"),
|
m_sprite(m_set(path, "wabbit_alpha.png"),
|
||||||
m_set(rect, ((Rect){.x = (int)state->bunnies[i].position.x,
|
m_set(rect, ((Rect){.x = state->bunnies[i].position.x,
|
||||||
.y = (int)state->bunnies[i].position.y,
|
.y = state->bunnies[i].position.y,
|
||||||
.w = BUNNY_W * SPRITE_SCALE,
|
.w = BUNNY_W * SPRITE_SCALE,
|
||||||
.h = BUNNY_H * SPRITE_SCALE})),
|
.h = BUNNY_H * SPRITE_SCALE})),
|
||||||
m_opt(color, (state->bunnies[i].color)), m_opt(stretch, true), );
|
m_opt(color, (state->bunnies[i].color)), m_opt(stretch, true), );
|
||||||
|
@ -19,15 +19,13 @@ static void title_tick(State *state) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
m_sprite("/assets/title.png", ((Rect) {
|
m_sprite("/assets/title.png", ((Rect) {
|
||||||
((float)ctx.base_draw_w / 2) - ((float)320 / 2), 64, 320, 128 }));
|
((float)ctx.resolution.x / 2) - ((float)320 / 2), 64, 320, 128 }));
|
||||||
|
|
||||||
|
|
||||||
/* draw the tick count as an example of dynamic text */
|
/* draw the tick count as an example of dynamic text */
|
||||||
size_t text_str_len = snprintf(NULL, 0, "%lu", state->ctx->tick_count) + 1;
|
size_t text_str_len = snprintf(NULL, 0, "%lu", state->ctx->frame_number) + 1;
|
||||||
char *text_str = cmalloc(text_str_len);
|
char *text_str = cmalloc(text_str_len);
|
||||||
snprintf(text_str, text_str_len, "%lu", state->ctx->tick_count);
|
snprintf(text_str, text_str_len, "%lu", state->ctx->frame_number);
|
||||||
|
|
||||||
const char *font = "fonts/kenney-pixel.ttf";
|
const char *font = "fonts/kenney-pixel.ttf";
|
||||||
int text_h = 32;
|
int text_h = 32;
|
||||||
|
@ -17,8 +17,8 @@ static void ingame_tick(State *state) {
|
|||||||
|
|
||||||
if (input_is_mouse_captured()) {
|
if (input_is_mouse_captured()) {
|
||||||
const float sensitivity = 0.6f; /* TODO: put this in a better place */
|
const float sensitivity = 0.6f; /* TODO: put this in a better place */
|
||||||
scn->yaw += (float)ctx.mouse_relative_position.x * sensitivity;
|
scn->yaw += (float)ctx.mouse_movement.x * sensitivity;
|
||||||
scn->pitch -= (float)ctx.mouse_relative_position.y * sensitivity;
|
scn->pitch -= (float)ctx.mouse_movement.y * sensitivity;
|
||||||
scn->pitch = clampf(scn->pitch, -89.0f, 89.0f);
|
scn->pitch = clampf(scn->pitch, -89.0f, 89.0f);
|
||||||
|
|
||||||
const float yaw_rad = scn->yaw * (float)DEG2RAD;
|
const float yaw_rad = scn->yaw * (float)DEG2RAD;
|
||||||
@ -62,8 +62,8 @@ static void ingame_tick(State *state) {
|
|||||||
|
|
||||||
for (int ly = 64; ly--;) {
|
for (int ly = 64; ly--;) {
|
||||||
for (int lx = 64; lx--;) {
|
for (int lx = 64; lx--;) {
|
||||||
float x = SDL_truncf(scn->cam.pos.x + 32 - lx);
|
float x = SDL_truncf(scn->cam.pos.x + 32 - (float)lx);
|
||||||
float y = SDL_truncf(scn->cam.pos.z + 32 - ly);
|
float y = SDL_truncf(scn->cam.pos.z + 32 - (float)ly);
|
||||||
|
|
||||||
float d0 = stb_perlin_noise3((float)x * TERRAIN_FREQUENCY, (float)y * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 3 - 6;
|
float d0 = stb_perlin_noise3((float)x * TERRAIN_FREQUENCY, (float)y * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 3 - 6;
|
||||||
float d1 = stb_perlin_noise3((float)(x + 1) * TERRAIN_FREQUENCY, (float)y * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 3 - 6;
|
float d1 = stb_perlin_noise3((float)(x + 1) * TERRAIN_FREQUENCY, (float)y * TERRAIN_FREQUENCY, 0, 0, 0, 0) * 3 - 6;
|
||||||
@ -89,7 +89,7 @@ static void ingame_tick(State *state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
draw_skybox("/assets/miramar/miramar_*.tga");
|
draw_skybox("/assets/miramar/miramar_*.tga");
|
||||||
draw_fog(0.9, 1.0, 0.05, (Color){ 140, 147, 160, 255 });
|
draw_fog(0.9f, 1.0f, 0.05f, (Color){ 140, 147, 160, 255 });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -16,15 +16,13 @@ static void title_tick(State *state) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
m_sprite("/assets/title.png", ((Rect) {
|
m_sprite("/assets/title.png", ((Rect) {
|
||||||
((float)ctx.base_draw_w / 2) - ((float)320 / 2), 64, 320, 128 }));
|
((float)ctx.resolution.x / 2) - ((float)320 / 2), 64, 320, 128 }));
|
||||||
|
|
||||||
|
|
||||||
/* draw the tick count as an example of dynamic text */
|
/* draw the tick count as an example of dynamic text */
|
||||||
size_t text_str_len = snprintf(NULL, 0, "%lu", state->ctx->tick_count) + 1;
|
size_t text_str_len = snprintf(NULL, 0, "%lu", state->ctx->frame_number) + 1;
|
||||||
char *text_str = cmalloc(text_str_len);
|
char *text_str = cmalloc(text_str_len);
|
||||||
snprintf(text_str, text_str_len, "%lu", state->ctx->tick_count);
|
snprintf(text_str, text_str_len, "%lu", state->ctx->frame_number);
|
||||||
|
|
||||||
const char *font = "/fonts/kenney-pixel.ttf";
|
const char *font = "/fonts/kenney-pixel.ttf";
|
||||||
int text_h = 32;
|
int text_h = 32;
|
||||||
@ -39,6 +37,7 @@ static void title_tick(State *state) {
|
|||||||
},
|
},
|
||||||
(Color) { 0, 0, 0, 255 }
|
(Color) { 0, 0, 0, 255 }
|
||||||
);
|
);
|
||||||
|
|
||||||
draw_text(text_str, (Vec2){ 0, 0 }, text_h, (Color) { 255, 255, 255, 255 }, font);
|
draw_text(text_str, (Vec2){ 0, 0 }, text_h, (Color) { 255, 255, 255, 255 }, font);
|
||||||
|
|
||||||
free(text_str);
|
free(text_str);
|
||||||
|
@ -8,40 +8,39 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
|
||||||
/* context that is valid for current frame */
|
/* context that is only valid for current frame */
|
||||||
/* changes to it should not have an effect, unless specified */
|
/* any changes to it will be dropped, unless explicitly stated */
|
||||||
/* TODO: ensure the statement above */
|
|
||||||
typedef struct Context {
|
typedef struct Context {
|
||||||
/* you may read from and write to these from game code */
|
/* you may read from and write to this one from game code */
|
||||||
|
/* it is ensured to persist between initializations */
|
||||||
void *udata;
|
void *udata;
|
||||||
|
|
||||||
/* TODO: is it what we actually want? */
|
/* which frame is it, starting from 0 at startup */
|
||||||
int64_t delta_time; /* preserves real time frame delta with no manipilation */
|
uint64_t frame_number;
|
||||||
uint64_t tick_count;
|
|
||||||
|
|
||||||
Vec2i mouse_window_position;
|
/* real time spent on one frame (in seconds) */
|
||||||
Vec2i mouse_relative_position;
|
/* townengine is fixed step based, so you don't have */
|
||||||
|
/* TODO: actually set it */
|
||||||
|
float frame_duration;
|
||||||
|
|
||||||
/* set just once on startup */
|
/* resolution is set from config and dictates both logical and drawing space, as they're related */
|
||||||
|
/* even if scaling is done, game logic should never change over that */
|
||||||
|
Vec2i resolution;
|
||||||
|
Vec2i mouse_position;
|
||||||
|
Vec2i mouse_movement;
|
||||||
|
|
||||||
|
/* is set on startup, should be used as source of randomness */
|
||||||
uint64_t random_seed;
|
uint64_t random_seed;
|
||||||
|
|
||||||
/* this should be a multiple of the current ticks per second */
|
/* whether debugging logic should be enabled in user code */
|
||||||
/* use it to simulate low framerate (e.g. at 60 tps, set to 2 for 30 fps) */
|
|
||||||
/* it can be changed at runtime; any resulting logic anomalies are bugs */
|
|
||||||
unsigned int update_multiplicity;
|
|
||||||
|
|
||||||
/* TODO: use Vec2i? */
|
|
||||||
int window_w;
|
|
||||||
int window_h;
|
|
||||||
int base_draw_w;
|
|
||||||
int base_draw_h;
|
|
||||||
|
|
||||||
bool debug;
|
bool debug;
|
||||||
bool is_running;
|
|
||||||
bool window_size_has_changed;
|
/* is set to true when state is invalidated and needs to be rebuilt */
|
||||||
|
/* watch for it and handle properly! */
|
||||||
bool initialization_needed;
|
bool initialization_needed;
|
||||||
} Context;
|
} Context;
|
||||||
|
|
||||||
|
/* when included after twn_engine_context there's an 'ctx' defined already */
|
||||||
#ifndef TWN_ENGINE_CONTEXT_C_H
|
#ifndef TWN_ENGINE_CONTEXT_C_H
|
||||||
TWN_API extern Context ctx;
|
TWN_API extern Context ctx;
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* include this header in game code to get the usable parts of the engine */
|
/* include this header in game code to get the usable parts of the engine */
|
||||||
#ifndef GAME_API_H
|
#ifndef TWN_GAME_API_H
|
||||||
#define GAME_API_H
|
#define TWN_GAME_API_H
|
||||||
|
|
||||||
|
|
||||||
#include "twn_context.h"
|
#include "twn_context.h"
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#ifndef UTIL_H
|
#ifndef TWN_UTIL_H
|
||||||
#define UTIL_H
|
#define TWN_UTIL_H
|
||||||
|
|
||||||
#include "twn_types.h"
|
#include "twn_types.h"
|
||||||
#include "twn_engine_api.h"
|
#include "twn_engine_api.h"
|
||||||
|
@ -57,7 +57,7 @@ static void load_game_object(void) {
|
|||||||
|
|
||||||
handle = new_handle;
|
handle = new_handle;
|
||||||
|
|
||||||
if (ctx.game.tick_count != 0)
|
if (ctx.game.frame_number != 0)
|
||||||
log_info("Game object was reloaded\n");
|
log_info("Game object was reloaded\n");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -84,7 +84,7 @@ static void watcher_callback(XWATCHER_FILE_EVENT event,
|
|||||||
switch(event) {
|
switch(event) {
|
||||||
case XWATCHER_FILE_MODIFIED:
|
case XWATCHER_FILE_MODIFIED:
|
||||||
SDL_LockMutex(lock);
|
SDL_LockMutex(lock);
|
||||||
last_tick_modified = ctx.game.tick_count;
|
last_tick_modified = ctx.game.frame_number;
|
||||||
loaded_after_modification = false;
|
loaded_after_modification = false;
|
||||||
SDL_UnlockMutex(lock);
|
SDL_UnlockMutex(lock);
|
||||||
break;
|
break;
|
||||||
@ -129,7 +129,7 @@ bool game_object_try_reloading(void) {
|
|||||||
|
|
||||||
/* only load the modified library after some time, as compilers make a lot of modifications */
|
/* only load the modified library after some time, as compilers make a lot of modifications */
|
||||||
SDL_LockMutex(lock);
|
SDL_LockMutex(lock);
|
||||||
if (ctx.game.tick_count - last_tick_modified > MODIFIED_TICKS_MERGED &&
|
if (ctx.game.frame_number - last_tick_modified > MODIFIED_TICKS_MERGED &&
|
||||||
!loaded_after_modification) {
|
!loaded_after_modification) {
|
||||||
load_game_object();
|
load_game_object();
|
||||||
loaded_after_modification = true;
|
loaded_after_modification = true;
|
||||||
|
@ -48,7 +48,7 @@ static void load_game_object(void) {
|
|||||||
|
|
||||||
handle = new_handle;
|
handle = new_handle;
|
||||||
|
|
||||||
if (ctx.game.tick_count != 0)
|
if (ctx.game.frame_number != 0)
|
||||||
log_info("Game object was reloaded\n");
|
log_info("Game object was reloaded\n");
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
@ -250,23 +250,23 @@ void render(void) {
|
|||||||
textures_update_atlas(&ctx.texture_cache);
|
textures_update_atlas(&ctx.texture_cache);
|
||||||
|
|
||||||
/* fit rendering context onto the resizable screen */
|
/* fit rendering context onto the resizable screen */
|
||||||
if (ctx.game.window_size_has_changed) {
|
if (ctx.window_size_has_changed) {
|
||||||
if ((float)ctx.game.window_w / (float)ctx.game.window_h > (float)ctx.base_render_width / (float)ctx.base_render_height) {
|
if ((float)ctx.window_dims.x / (float)ctx.window_dims.y > (float)ctx.base_render_width / (float)ctx.base_render_height) {
|
||||||
float ratio = (float)ctx.game.window_h / (float)ctx.base_render_height;
|
float ratio = (float)ctx.window_dims.y / (float)ctx.base_render_height;
|
||||||
int w = (int)((float)ctx.base_render_width * ratio);
|
int w = (int)((float)ctx.base_render_width * ratio);
|
||||||
setup_viewport(
|
setup_viewport(
|
||||||
ctx.game.window_w / 2 - w / 2,
|
ctx.window_dims.x / 2 - w / 2,
|
||||||
0,
|
0,
|
||||||
w,
|
w,
|
||||||
ctx.game.window_h
|
ctx.window_dims.y
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
float ratio = (float)ctx.game.window_w / (float)ctx.base_render_width;
|
float ratio = (float)ctx.window_dims.x / (float)ctx.base_render_width;
|
||||||
int h = (int)((float)ctx.base_render_height * ratio);
|
int h = (int)((float)ctx.base_render_height * ratio);
|
||||||
setup_viewport(
|
setup_viewport(
|
||||||
0,
|
0,
|
||||||
ctx.game.window_h / 2 - h / 2,
|
ctx.window_dims.y / 2 - h / 2,
|
||||||
ctx.game.window_w,
|
ctx.window_dims.x,
|
||||||
h
|
h
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
|
|
||||||
typedef struct EngineContext {
|
typedef struct EngineContext {
|
||||||
/* user code facing context */
|
/* user code facing context */
|
||||||
|
Context game_copy;
|
||||||
|
/* engine-side context, copied to `game_copy` before every frame */
|
||||||
Context game;
|
Context game;
|
||||||
|
|
||||||
InputState input;
|
InputState input;
|
||||||
@ -27,6 +29,8 @@ typedef struct EngineContext {
|
|||||||
/* where the app was run from, used as the root for packs */
|
/* where the app was run from, used as the root for packs */
|
||||||
char *base_dir;
|
char *base_dir;
|
||||||
|
|
||||||
|
Vec2i window_dims;
|
||||||
|
|
||||||
/* configuration */
|
/* configuration */
|
||||||
toml_table_t *config_table;
|
toml_table_t *config_table;
|
||||||
int64_t base_render_width;
|
int64_t base_render_width;
|
||||||
@ -52,6 +56,7 @@ typedef struct EngineContext {
|
|||||||
uint8_t audio_stream_channel_count;
|
uint8_t audio_stream_channel_count;
|
||||||
|
|
||||||
/* main loop machinery */
|
/* main loop machinery */
|
||||||
|
int64_t delta_time; /* preserves real time frame delta with no manipilation */
|
||||||
int64_t clocks_per_second;
|
int64_t clocks_per_second;
|
||||||
int64_t prev_frame_time;
|
int64_t prev_frame_time;
|
||||||
int64_t desired_frametime; /* how long one tick should be */
|
int64_t desired_frametime; /* how long one tick should be */
|
||||||
@ -59,10 +64,17 @@ typedef struct EngineContext {
|
|||||||
int64_t delta_averager_residual;
|
int64_t delta_averager_residual;
|
||||||
int64_t time_averager[4];
|
int64_t time_averager[4];
|
||||||
|
|
||||||
|
/* this should be a multiple of the current ticks per second */
|
||||||
|
/* use it to simulate low framerate (e.g. at 60 tps, set to 2 for 30 fps) */
|
||||||
|
/* it can be changed at runtime; any resulting logic anomalies are bugs */
|
||||||
|
uint32_t update_multiplicity;
|
||||||
|
|
||||||
SDL_GLContext *gl_context;
|
SDL_GLContext *gl_context;
|
||||||
SDL_Window *window;
|
SDL_Window *window;
|
||||||
uint32_t window_id;
|
uint32_t window_id;
|
||||||
|
|
||||||
|
bool is_running;
|
||||||
|
bool window_size_has_changed;
|
||||||
bool resync_flag;
|
bool resync_flag;
|
||||||
bool was_successful;
|
bool was_successful;
|
||||||
} EngineContext;
|
} EngineContext;
|
||||||
|
@ -194,8 +194,8 @@ void input_state_update(InputState *input) {
|
|||||||
SDL_GetRelativeMouseState(&input->mouse_relative_position.x,
|
SDL_GetRelativeMouseState(&input->mouse_relative_position.x,
|
||||||
&input->mouse_relative_position.y);
|
&input->mouse_relative_position.y);
|
||||||
|
|
||||||
ctx.game.mouse_window_position = input->mouse_window_position;
|
ctx.game.mouse_position = input->mouse_window_position;
|
||||||
ctx.game.mouse_relative_position = input->mouse_relative_position;
|
ctx.game.mouse_movement = input->mouse_relative_position;
|
||||||
|
|
||||||
for (size_t i = 0; i < shlenu(input->action_hash); ++i) {
|
for (size_t i = 0; i < shlenu(input->action_hash); ++i) {
|
||||||
Action *action = &input->action_hash[i].value;
|
Action *action = &input->action_hash[i].value;
|
||||||
|
@ -36,8 +36,8 @@ static int event_callback(void *userdata, SDL_Event *event) {
|
|||||||
|
|
||||||
switch (event->window.event) {
|
switch (event->window.event) {
|
||||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||||
ctx.game.window_w = event->window.data1;
|
ctx.window_dims.x = event->window.data1;
|
||||||
ctx.game.window_h = event->window.data2;
|
ctx.window_dims.y = event->window.data2;
|
||||||
ctx.resync_flag = true;
|
ctx.resync_flag = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -59,12 +59,12 @@ static int event_callback(void *userdata, SDL_Event *event) {
|
|||||||
static void poll_events(void) {
|
static void poll_events(void) {
|
||||||
SDL_Event e;
|
SDL_Event e;
|
||||||
|
|
||||||
ctx.game.window_size_has_changed = false;
|
ctx.window_size_has_changed = false;
|
||||||
|
|
||||||
while (SDL_PollEvent(&e)) {
|
while (SDL_PollEvent(&e)) {
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
case SDL_QUIT:
|
case SDL_QUIT:
|
||||||
ctx.game.is_running = false;
|
ctx.is_running = false;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SDL_WINDOWEVENT:
|
case SDL_WINDOWEVENT:
|
||||||
@ -73,7 +73,7 @@ static void poll_events(void) {
|
|||||||
|
|
||||||
switch (e.window.event) {
|
switch (e.window.event) {
|
||||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||||
ctx.game.window_size_has_changed = true;
|
ctx.window_size_has_changed = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
@ -111,6 +111,11 @@ static void APIENTRY opengl_log(GLenum source,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
void preserve_persistent_ctx_fields(void) {
|
||||||
|
ctx.game.udata = ctx.game_copy.udata;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void main_loop(void) {
|
static void main_loop(void) {
|
||||||
/*
|
/*
|
||||||
if (!ctx.is_running) {
|
if (!ctx.is_running) {
|
||||||
@ -124,7 +129,7 @@ static void main_loop(void) {
|
|||||||
int64_t current_frame_time = SDL_GetPerformanceCounter();
|
int64_t current_frame_time = SDL_GetPerformanceCounter();
|
||||||
int64_t delta_time = current_frame_time - ctx.prev_frame_time;
|
int64_t delta_time = current_frame_time - ctx.prev_frame_time;
|
||||||
ctx.prev_frame_time = current_frame_time;
|
ctx.prev_frame_time = current_frame_time;
|
||||||
ctx.game.delta_time = delta_time;
|
ctx.delta_time = delta_time;
|
||||||
|
|
||||||
/* handle unexpected timer anomalies (overflow, extra slow frames, etc) */
|
/* handle unexpected timer anomalies (overflow, extra slow frames, etc) */
|
||||||
if (delta_time > ctx.desired_frametime * 8) { /* ignore extra-slow frames */
|
if (delta_time > ctx.desired_frametime * 8) { /* ignore extra-slow frames */
|
||||||
@ -188,24 +193,23 @@ static void main_loop(void) {
|
|||||||
ctx.resync_flag = false;
|
ctx.resync_flag = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.game_copy = ctx.game;
|
||||||
|
|
||||||
/* finally, let's get to work */
|
/* finally, let's get to work */
|
||||||
int frames = 0;
|
int frames = 0;
|
||||||
while (ctx.frame_accumulator >= ctx.desired_frametime * ctx.game.update_multiplicity) {
|
while (ctx.frame_accumulator >= ctx.desired_frametime * ctx.update_multiplicity) {
|
||||||
frames += 1;
|
frames += 1;
|
||||||
for (size_t i = 0; i < ctx.game.update_multiplicity; ++i) {
|
for (size_t i = 0; i < ctx.update_multiplicity; ++i) {
|
||||||
/* TODO: disable rendering pushes on not-last ? */
|
/* TODO: disable rendering pushes on not-last ? */
|
||||||
render_queue_clear();
|
render_queue_clear();
|
||||||
|
|
||||||
poll_events();
|
poll_events();
|
||||||
|
|
||||||
input_state_update(&ctx.input);
|
input_state_update(&ctx.input);
|
||||||
|
|
||||||
game_object_tick();
|
game_object_tick();
|
||||||
|
preserve_persistent_ctx_fields();
|
||||||
|
|
||||||
ctx.frame_accumulator -= ctx.desired_frametime;
|
ctx.frame_accumulator -= ctx.desired_frametime;
|
||||||
ctx.game.tick_count = (ctx.game.tick_count % ULLONG_MAX) + 1;
|
ctx.game.frame_number = (ctx.game.frame_number % ULLONG_MAX) + 1;
|
||||||
ctx.game.initialization_needed = false;
|
ctx.game.initialization_needed = false;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,7 +443,7 @@ static bool initialize(void) {
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
ctx.base_render_width = datum_base_render_width.u.i;
|
ctx.base_render_width = datum_base_render_width.u.i;
|
||||||
ctx.game.base_draw_w = (int)ctx.base_render_width;
|
ctx.game.resolution.x = (int)ctx.base_render_width;
|
||||||
|
|
||||||
toml_datum_t datum_base_render_height = toml_int_in(game, "base_render_height");
|
toml_datum_t datum_base_render_height = toml_int_in(game, "base_render_height");
|
||||||
if (!datum_base_render_height.ok) {
|
if (!datum_base_render_height.ok) {
|
||||||
@ -447,7 +451,7 @@ static bool initialize(void) {
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
ctx.base_render_height = datum_base_render_height.u.i;
|
ctx.base_render_height = datum_base_render_height.u.i;
|
||||||
ctx.game.base_draw_h = (int)ctx.base_render_height;
|
ctx.game.resolution.y = (int)ctx.base_render_height;
|
||||||
|
|
||||||
ctx.window = SDL_CreateWindow(datum_title.u.s,
|
ctx.window = SDL_CreateWindow(datum_title.u.s,
|
||||||
SDL_WINDOWPOS_CENTERED,
|
SDL_WINDOWPOS_CENTERED,
|
||||||
@ -503,8 +507,8 @@ static bool initialize(void) {
|
|||||||
|
|
||||||
/* TODO: */
|
/* TODO: */
|
||||||
// SDL_GetRendererOutputSize(ctx.renderer, &ctx.window_w, &ctx.window_h);
|
// SDL_GetRendererOutputSize(ctx.renderer, &ctx.window_w, &ctx.window_h);
|
||||||
ctx.game.window_w = (int)ctx.base_render_width;
|
ctx.window_dims.x = (int)ctx.base_render_width;
|
||||||
ctx.game.window_h = (int)ctx.base_render_height;
|
ctx.window_dims.y = (int)ctx.base_render_height;
|
||||||
|
|
||||||
/* add a watcher for immediate updates on window size */
|
/* add a watcher for immediate updates on window size */
|
||||||
SDL_AddEventWatch(event_callback, NULL);
|
SDL_AddEventWatch(event_callback, NULL);
|
||||||
@ -532,7 +536,7 @@ static bool initialize(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* you could change this at runtime if you wanted */
|
/* you could change this at runtime if you wanted */
|
||||||
ctx.game.update_multiplicity = 1;
|
ctx.update_multiplicity = 1;
|
||||||
|
|
||||||
#ifndef EMSCRIPTEN
|
#ifndef EMSCRIPTEN
|
||||||
/* hook up opengl debugging callback */
|
/* hook up opengl debugging callback */
|
||||||
@ -561,13 +565,13 @@ static bool initialize(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.game.is_running = true;
|
ctx.is_running = true;
|
||||||
ctx.resync_flag = true;
|
ctx.resync_flag = true;
|
||||||
ctx.clocks_per_second = SDL_GetPerformanceFrequency();
|
ctx.clocks_per_second = SDL_GetPerformanceFrequency();
|
||||||
ctx.prev_frame_time = SDL_GetPerformanceCounter();
|
ctx.prev_frame_time = SDL_GetPerformanceCounter();
|
||||||
ctx.desired_frametime = ctx.clocks_per_second / ctx.ticks_per_second;
|
ctx.desired_frametime = ctx.clocks_per_second / ctx.ticks_per_second;
|
||||||
ctx.frame_accumulator = 0;
|
ctx.frame_accumulator = 0;
|
||||||
ctx.game.tick_count = 0;
|
ctx.game.frame_number = 0;
|
||||||
|
|
||||||
/* delta time averaging */
|
/* delta time averaging */
|
||||||
ctx.delta_averager_residual = 0;
|
ctx.delta_averager_residual = 0;
|
||||||
@ -772,7 +776,7 @@ int enter_loop(int argc, char **argv) {
|
|||||||
ctx.was_successful = true;
|
ctx.was_successful = true;
|
||||||
ctx.game.initialization_needed = true;
|
ctx.game.initialization_needed = true;
|
||||||
|
|
||||||
while (ctx.game.is_running) {
|
while (ctx.is_running) {
|
||||||
if (game_object_try_reloading()) {
|
if (game_object_try_reloading()) {
|
||||||
ctx.game.initialization_needed = true;
|
ctx.game.initialization_needed = true;
|
||||||
reset_state();
|
reset_state();
|
||||||
|
@ -273,11 +273,11 @@ void tick_timer(int *value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void tick_ftimer(float *value) {
|
void tick_ftimer(float *value) {
|
||||||
*value = MAX(*value - ((float)ctx.game.delta_time / (float)ctx.clocks_per_second), 0.0f);
|
*value = MAX(*value - ((float)ctx.delta_time / (float)ctx.clocks_per_second), 0.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool repeat_ftimer(float *value, float at) {
|
bool repeat_ftimer(float *value, float at) {
|
||||||
*value -= (float)ctx.game.delta_time / (float)ctx.clocks_per_second;
|
*value -= (float)ctx.delta_time / (float)ctx.clocks_per_second;
|
||||||
if (*value < 0.0f) {
|
if (*value < 0.0f) {
|
||||||
*value += at;
|
*value += at;
|
||||||
return true;
|
return true;
|
||||||
|
Loading…
Reference in New Issue
Block a user