153 lines
3.7 KiB
C
153 lines
3.7 KiB
C
#include "program.h"
|
|
#include "camera.h"
|
|
#include "game_world.h"
|
|
#include "physics_world.h"
|
|
#include "time.h"
|
|
#include "assets.h"
|
|
#include "debug.h"
|
|
#include "input.h"
|
|
#include <SDL2/SDL_video.h>
|
|
#include <SDL2/SDL_image.h>
|
|
|
|
SDL_Window* g_window;
|
|
static double _target_delta_time = 0.0;
|
|
static double _delta_time;
|
|
static double _frame_start;
|
|
static double _game_start_time;
|
|
|
|
|
|
#define INITFLAGS SDL_INIT_EVENTS | SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_GAMECONTROLLER | SDL_INIT_JOYSTICK
|
|
|
|
static inline
|
|
double tstos(struct timespec ts) {
|
|
return (double)ts.tv_sec + (double)ts.tv_nsec * 1E-09;
|
|
}
|
|
|
|
struct timespec get_time() {
|
|
struct timespec ts;
|
|
(void)timespec_get(&ts, TIME_UTC);
|
|
return ts;
|
|
}
|
|
|
|
double get_time_s() {
|
|
return tstos(get_time());
|
|
}
|
|
|
|
static
|
|
void program_tick(const struct ProgramSettings* settings, float delta_time) {
|
|
settings->on_tick();
|
|
game_world_update();
|
|
physics_world_tick();
|
|
}
|
|
|
|
void program_run(const struct ProgramSettings* settings) {
|
|
LOG_INFO("Starting program...");
|
|
if(settings->target_fps <= 0) {
|
|
_target_delta_time = 0;
|
|
} else {
|
|
_target_delta_time = 1.0f/settings->target_fps;
|
|
}
|
|
_game_start_time = get_time_s();
|
|
_frame_start = _game_start_time;
|
|
if(SDL_Init(INITFLAGS) != 0) {
|
|
LOG_ERROR("SDL init error: %s", SDL_GetError());
|
|
}
|
|
|
|
g_window = SDL_CreateWindow(
|
|
settings->title,
|
|
SDL_WINDOWPOS_CENTERED_DISPLAY(0),
|
|
SDL_WINDOWPOS_CENTERED_DISPLAY(0),
|
|
settings->view_resolution.x,
|
|
settings->view_resolution.y,
|
|
SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_RESIZABLE);
|
|
|
|
physics_world_init();
|
|
render_init(g_window, settings);
|
|
camera_init();
|
|
assets_init();
|
|
input_init();
|
|
game_world_init();
|
|
|
|
LOG_INFO("settings->on_play");
|
|
settings->on_play();
|
|
|
|
LOG_INFO("Starting program loop");
|
|
for(;;) {
|
|
render_present();
|
|
|
|
double current_time = get_time_s();
|
|
_delta_time += current_time - _frame_start;
|
|
_frame_start = current_time;
|
|
|
|
program_handle_events();
|
|
if(settings->target_fps == 0) {
|
|
program_tick(settings, _delta_time);
|
|
_delta_time = 0.f;
|
|
} else {
|
|
while(_delta_time > _target_delta_time) {
|
|
_delta_time -= _target_delta_time;
|
|
program_tick(settings, _target_delta_time);
|
|
}
|
|
}
|
|
settings->on_draw();
|
|
game_world_draw();
|
|
SDL_Delay(1);
|
|
}
|
|
|
|
ASSERT_RETURN(0,, "Program escaped containment, nuking from orbit...");
|
|
abort();
|
|
}
|
|
|
|
void program_quit() {
|
|
game_world_close();
|
|
input_clean();
|
|
assets_clean();
|
|
render_clean();
|
|
physics_world_clean();
|
|
SDL_DestroyWindow(g_window);
|
|
SDL_Quit();
|
|
exit(0);
|
|
}
|
|
|
|
void program_handle_events() {
|
|
SDL_Event event;
|
|
while(SDL_PollEvent(&event)) {
|
|
switch(event.type) {
|
|
default: break;
|
|
case SDL_KEYUP:
|
|
case SDL_KEYDOWN:
|
|
case SDL_CONTROLLERBUTTONUP:
|
|
case SDL_CONTROLLERBUTTONDOWN:
|
|
case SDL_CONTROLLERAXISMOTION:
|
|
input_handle_event(event);
|
|
break;
|
|
case SDL_WINDOWEVENT:
|
|
if(event.window.windowID == SDL_GetWindowID(g_window)) {
|
|
program_handle_windowevent(&event.window);
|
|
}
|
|
break;
|
|
case SDL_QUIT:
|
|
program_quit();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void program_handle_windowevent(SDL_WindowEvent* event) {
|
|
switch(event->type) {
|
|
default:
|
|
render_handle_resize();
|
|
break;
|
|
}
|
|
}
|
|
|
|
inline
|
|
float delta_time() {
|
|
return (float)(_target_delta_time == 0 ? _delta_time : _target_delta_time);
|
|
}
|
|
|
|
inline
|
|
float game_time() {
|
|
return (float)(get_time_s() - _game_start_time);
|
|
}
|