static float _physics_speed = 1.0f;
static float _physics_time;
static float _physics_frame_time;
static void _update_physics(void) {
const float timestep = 1.0f / 60.0f;
static float p_time = 0.0f;
static float s_time = 0.0f;
float time = _physics_time;
_physics_time = (float)((double)uv_hrtime() / 1000000000.0);
_physics_frame_time = _physics_time - time;
s_time += _physics_frame_time * _physics_speed;
if(p_time >= s_time) {
alias_transform_update2d_serial(engine_ecs(), engine_ecs_transform());
}
while(p_time < s_time) {
alias_physics_update2d_serial_pre_transform(engine_ecs(), engine_ecs_physics_2d(), timestep);
alias_transform_update2d_serial(engine_ecs(), engine_ecs_transform());
alias_physics_update2d_serial_post_transform(engine_ecs(), engine_ecs_physics_2d(), timestep);
p_time += timestep;
}
}
static void __timer_cb(uv_timer_t *timer) {
if(glfwWindowShouldClose(_r_window)) {
uv_timer_stop(timer);
return;
}
glfwPollEvents();
_input_frame();
if(!_state_frame()) {
glfwSetWindowShouldClose(_r_window, GLFW_TRUE);
uv_timer_stop(timer);
return;
}
_update_physics();
_draw_frame();
}
void _gl_debug_message_callback(uint32_t source, uint32_t type, uint32_t id, uint32_t severity, int length, const char *message, const void *ud) {
const char *source_str = source == GL_DEBUG_SOURCE_API ? "API"
: source == GL_DEBUG_SOURCE_WINDOW_SYSTEM ? "Window System"
: source == GL_DEBUG_SOURCE_SHADER_COMPILER ? "Shader Compiler"
: source == GL_DEBUG_SOURCE_THIRD_PARTY ? "Third Party"
: source == GL_DEBUG_SOURCE_APPLICATION ? "Application"
: source == GL_DEBUG_SOURCE_OTHER ? "Other"
: "Invalid";
const char *type_str = type == GL_DEBUG_TYPE_ERROR ? "Error"
: type == GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR ? "Deprecated Behavior"
: type == GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR ? "Undefined Behavior"
: type == GL_DEBUG_TYPE_PORTABILITY ? "Portability"
: type == GL_DEBUG_TYPE_PERFORMANCE ? "Performance"
: type == GL_DEBUG_TYPE_MARKER ? "Marker"
: type == GL_DEBUG_TYPE_PUSH_GROUP ? "Push Group"
: type == GL_DEBUG_TYPE_POP_GROUP ? "Pop Group"
: type == GL_DEBUG_TYPE_OTHER ? "Other"
: "Invalid";
switch(severity) {
case GL_DEBUG_SEVERITY_HIGH:
default:
engine_error("%s from %s: %.*s", type_str, source_str, length, message);
break;
case GL_DEBUG_SEVERITY_MEDIUM:
engine_warning("%s from %s: %.*s", type_str, source_str, length, message);
break;
case GL_DEBUG_SEVERITY_LOW:
engine_debug("%s from %s: %.*s", type_str, source_str, length, message);
break;
case GL_DEBUG_SEVERITY_NOTIFICATION:
engine_info("%s from %s: %.*s", type_str, source_str, length, message);
break;
}
}
int main(int argc, char * argv []) {
uint32_t i;
argv = uv_setup_args(argc, argv);
alias_libuv_init();
alias_ecs_create_instance(NULL, &_ecs);
// process -set arguments
i = 1;
while(i < argc) {
if(argv[i] == NULL) {
i++;
continue;
}
if(argv[i][0] == '-' && argv[i][1] == 's' && argv[i][2] == 'e' && argv[i][3] == 't' && argv[i][4] == 0) {
uint32_t start = i;
i++;
while(i < argc && argv[i][0] != '-' && argv[i][0] != '+') i++;
argv[start] += 1;
_command_execute(i - start, (char const * const *)(argv + start));
for(uint32_t j = start; j < i; j++) {
argv[j] = NULL;
}
} else {
i++;
}
}
_fs_init();
_state = engine_application_entryPoint();
alias_libuv_run_forever();
// now files commands have been run, files are loaded. we can loop again for the rendering timer.
// but first, process the + arguments
i = 1;
while(i < argc) {
if(argv[i] == NULL) {
i++;
continue;
}
if(argv[i][0] == '-' || argv[i][0] == '+') {
uint32_t start = i;
i++;
while(i < argc && argv[i][0] != '-' && argv[i][0] != '+') i++;
argv[start] += 1;
_command_execute(i - start, (char const * const *)(argv + start));
for(uint32_t j = start; j < i; j++) {
argv[j] = NULL;
}
} else {
engine_error("unused argument %s", argv[i]);
i++;
}
}
if(!glfwInit()) {
engine_error("glfw: failed to initialize");
return 0;
}
glfwDefaultWindowHints();
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_API);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
int width = r_window_width;
int height = r_window_height;
GLFWmonitor *primary = glfwGetPrimaryMonitor();
int count;
GLFWmonitor **monitors = glfwGetMonitors(&count);
GLFWmonitor *monitor = r_monitor == -1 ? primary : monitors[alias_min(alias_max(r_monitor, 0), count)];
const GLFWvidmode *mode = glfwGetVideoMode(monitor);
if(r_window_mode == r_window_mode_windowed) {
monitor = NULL;
if(width == 0) {
width = mode->width / 2;
}
if(height == 0) {
height = mode->height / 2;
}
} else if(r_window_mode == r_window_mode_fullscreen) {
} else if(r_window_mode == r_window_mode_borderless) {
glfwWindowHint(GLFW_RED_BITS, mode->redBits);
glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits);
glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits);
glfwWindowHint(GLFW_REFRESH_RATE, mode->refreshRate);
width = mode->width;
height = mode->height;
}
_r_window = glfwCreateWindow(width, height, "alias engine", monitor, NULL);
if(_r_window == NULL) {
engine_error("glfw: could not create window");
return 0;
}
glfwMakeContextCurrent(_r_window);
if(gladLoadGL(glfwGetProcAddress) == 0) {
engine_error("glad: could not load");
return 0;
}
glDebugMessageCallback(_gl_debug_message_callback, NULL);
uv_timer_t timer;
uv_timer_init(alias_libuv_event_loop(), &timer);
uv_timer_start(&timer, __timer_cb, 1000 / 60, 1000 / 60);
if(_state != NULL && _state->begin != NULL) {
_state->begin(_state->ud);
}
alias_libuv_run_forever();
return 0;
}