282 lines
6.8 KiB
Plaintext
282 lines
6.8 KiB
Plaintext
MEM_DEBUG :: false;
|
|
|
|
#if MEM_DEBUG {
|
|
#import "Basic"()(MEMORY_DEBUGGER=true);
|
|
} else {
|
|
#import "Basic";
|
|
}
|
|
#import "Math";
|
|
#import "Input";
|
|
#import "Hash_Table";
|
|
#import "Hash";
|
|
#import "Simple_Package_Reader";
|
|
|
|
String :: #import "String";
|
|
Jaison :: #import "Jaison";
|
|
stbi :: #import "stb_image";
|
|
|
|
FLAG_ANY_TEST :: FLAG_TEST_ENGINE || FLAG_TEST_EXE_ENGINE || FLAG_TEST_GAME || FLAG_TEST_EXE_GAME;
|
|
FLAG_ANY_EXE_TEST :: FLAG_TEST_EXE_ENGINE || FLAG_TEST_EXE_GAME;
|
|
|
|
// The engine's own tests build against test_game/, so they still compile on a
|
|
// checkout that does not have the game/ directory. Game tests build against the
|
|
// real game, which is the whole point of them.
|
|
FLAG_USE_TEST_GAME :: FLAG_TEST_ENGINE || FLAG_TEST_EXE_ENGINE;
|
|
|
|
// The framework (suites, checks, the exe-test command list) is available under
|
|
// every test flag; the engine's own test cases are not.
|
|
#if FLAG_ANY_TEST { #load "tests/framework.jai"; }
|
|
#if (FLAG_TEST_ENGINE || FLAG_TEST_EXE_ENGINE) { #load "tests/index.jai"; }
|
|
|
|
#load "logging.jai";
|
|
#load "pseudophysics/core.jai";
|
|
#load "pack_hotreload.jai";
|
|
#load "trile.jai";
|
|
#load "rendering/rendering.jai";
|
|
#load "input/hotkeys.jai";
|
|
#load "ui/ui.jai";
|
|
#if !FLAG_RELEASE_BUILD { #load "editor/editor.jai"; }
|
|
#load "time.jai";
|
|
#load "events.jai";
|
|
#load "load.jai";
|
|
#load "ray.jai";
|
|
#load "profiling.jai";
|
|
#load "particles/particles.jai";
|
|
#load "orientation.jai";
|
|
#load "entities.jai";
|
|
#load "world.jai";
|
|
#load "utils.jai";
|
|
#load "audio/audio.jai";
|
|
#load "assets/asset_manager.jai";
|
|
#load "settings_menu.jai";
|
|
#load "loading_screen.jai";
|
|
|
|
#if FLAG_USE_TEST_GAME {
|
|
#load "../test_game/game.jai";
|
|
} else {
|
|
#load "../game/game.jai";
|
|
}
|
|
|
|
last_frame_time : float64; // timestamp of the last frame
|
|
delta\ _time : float64;
|
|
|
|
latest_frametime : float64; // latest frame generation duration
|
|
|
|
V_MAJOR :: 0;
|
|
V_MINOR :: 7;
|
|
|
|
state: struct {
|
|
dpi_scale : float;
|
|
font_default : Ui_Font;
|
|
};
|
|
|
|
Window_Info :: struct {
|
|
width : s32;
|
|
height : s32;
|
|
title : *u8;
|
|
};
|
|
|
|
get_window_info :: () -> Window_Info {
|
|
|
|
return Window_Info.{
|
|
1920,
|
|
1080,
|
|
"trueno!"
|
|
};
|
|
}
|
|
|
|
round_pow2 :: (v: float) -> s32 {
|
|
vi := (cast(u32) v) - 1;
|
|
for i : 0..4 {
|
|
vi |= (vi >> (1<<i));
|
|
}
|
|
return cast(s32) (vi + 1);
|
|
}
|
|
|
|
debug_font : *Font;
|
|
|
|
init :: () {
|
|
scene_init();
|
|
sfetch_setup(*(sfetch_desc_t.{
|
|
max_requests = 128,
|
|
num_channels = 2,
|
|
num_lanes = 8,
|
|
logger = .{ func = slog_func },
|
|
}));
|
|
asset_manager_init();
|
|
#if OS != .WASM { Thread.init(*g_mixer.mutex); }
|
|
audio_init_thread_context();
|
|
saudio_setup(*(saudio_desc.{
|
|
logger = .{ func = slog_func },
|
|
stream_cb = sokol_audio_callback,
|
|
}));
|
|
g_audio_sample_rate = saudio_sample_rate();
|
|
stm_setup();
|
|
state.dpi_scale = sapp_dpi_scale();
|
|
atlas_dim := round_pow2(1024.0 * state.dpi_scale);
|
|
text_init(atlas_dim);
|
|
|
|
g_mixer.paused = true;
|
|
|
|
useless_mem : [1]u8;
|
|
debug_font = get_font_at_size(useless_mem, 15);
|
|
load_pack("boot", .BLOCK_ENGINE);
|
|
load_pack("core");
|
|
load_pack("game_core");
|
|
|
|
#if FLAG_TEST_EXE_ENGINE {
|
|
engine_exe_tests_add();
|
|
}
|
|
#if FLAG_TEST_EXE_GAME {
|
|
// Fixed-name hook, same convention as game_init / game_tick.
|
|
game_exe_tests_add();
|
|
}
|
|
}
|
|
|
|
init_after_core :: () {
|
|
add_font_from_pack("boot", "DroidSerif-Regular.ttf");
|
|
ui_init_font_fields(*state.font_default);
|
|
init_ui();
|
|
ltriles();
|
|
tt := get_trile_table_ptr();
|
|
if tt.count == 0 {
|
|
set_trile("test", Trile.{});
|
|
} else {
|
|
name : string;
|
|
for v : tt {
|
|
name = v.name;
|
|
break;
|
|
}
|
|
}
|
|
#if !FLAG_RELEASE_BUILD {
|
|
init_editor();
|
|
} else {
|
|
init_keybinds();
|
|
init_settings_menu();
|
|
}
|
|
|
|
audio_init();
|
|
|
|
// Let the game configure engine settings before full init.
|
|
game_engine_config();
|
|
|
|
init_world_system();
|
|
// We want to do this last.
|
|
game_init();
|
|
|
|
// #if UNCAPPED_FRAMES then sapp_glx_swapinterval(0);
|
|
}
|
|
|
|
|
|
delta_time_accumulator : float64 = 0;
|
|
|
|
frame :: () {
|
|
clear_frame_profiling();
|
|
check_and_handle_window_resize();
|
|
delta_time = get_time() - last_frame_time;
|
|
last_frame_time = get_time();
|
|
|
|
asset_manager_tick();
|
|
|
|
add_frame_profiling_point("After asset manager tick");
|
|
|
|
if !mandatory_loads_done() {
|
|
print("Mandatory loads not done!!\n");
|
|
return;
|
|
}
|
|
|
|
if show_loading_screen() {
|
|
input_per_frame_event_and_flag_update();
|
|
if init_after_core_done {
|
|
draw_loading_screen();
|
|
tick_ui();
|
|
ui_pass();
|
|
render();
|
|
reset_temporary_storage();
|
|
}
|
|
return;
|
|
}
|
|
|
|
if !init_after_core_done {
|
|
init_after_core();
|
|
init_after_core_done = true;
|
|
}
|
|
|
|
if g_mixer.paused && !in_editor_view && !show_loading_screen() {
|
|
g_mixer.paused = false;
|
|
}
|
|
|
|
|
|
add_frame_profiling_point("After loading logic");
|
|
|
|
#if FLAG_ANY_EXE_TEST {
|
|
run_exe_tests();
|
|
}
|
|
|
|
frame_start_time := get_time();
|
|
|
|
dpis := state.dpi_scale;
|
|
|
|
#if OS != .WASM { tick_profiler(); }
|
|
|
|
should_tick_game := #ifx FLAG_RELEASE_BUILD then true else !in_editor_view;
|
|
|
|
if should_tick_game {
|
|
delta_time_accumulator += delta_time;
|
|
if delta_time_accumulator > (4.0/60.0) then delta_time_accumulator = 4.0/60.0;
|
|
}
|
|
|
|
if should_tick_game && !settings_menu_blocks_game() {
|
|
while delta_time_accumulator > (1.0/480.0) {
|
|
game_tick(1.0/480.0);
|
|
tick_particles(1.0/480.0);
|
|
delta_time_accumulator -= (1.0/480.0);
|
|
}
|
|
}
|
|
for event: Input.events_this_frame {
|
|
GR.getrect_handle_event(event);
|
|
}
|
|
|
|
|
|
add_frame_profiling_point("After game ticks");
|
|
tick_ui();
|
|
add_frame_profiling_point("After UI tick");
|
|
|
|
if should_tick_game then game_draw();
|
|
add_frame_profiling_point("After game draw");
|
|
|
|
ui_clear_mouse_occluders();
|
|
ui_pass();
|
|
add_frame_profiling_point("After UI draw");
|
|
|
|
#if !FLAG_RELEASE_BUILD {
|
|
prepare_text(debug_font, tprint("frametime: % ms", delta_time * 1000));
|
|
draw_prepared_text(debug_font, 10, 10, .{0.0, 1.0, 0.0, 1.0});
|
|
draw_editor();
|
|
}
|
|
|
|
add_frame_profiling_point("After editor draw");
|
|
render();
|
|
add_frame_profiling_point("After rendering");
|
|
|
|
end_frame_profiling();
|
|
#if MEM_DEBUG {
|
|
memory_visualizer_per_frame_update();
|
|
}
|
|
|
|
#if OS != .WASM { profiler_update(); }
|
|
reset_temporary_storage();
|
|
frame_end_time := get_time();
|
|
input_per_frame_event_and_flag_update();
|
|
}
|
|
|
|
cleanup :: () {
|
|
log_info("Cleanup called....");
|
|
audio_cleanup();
|
|
scene_shutdown();
|
|
}
|
|
|
|
get_window_size :: () -> (s32, s32) {
|
|
return sapp_width(), sapp_height();
|
|
}
|