Compare commits
12 Commits
2286cdefeb
...
f3a2dc9063
Author | SHA1 | Date | |
---|---|---|---|
|
f3a2dc9063 | ||
|
53c43a8f34 | ||
|
507bff6ed8 | ||
|
00636d65a9 | ||
|
42253fc58a | ||
|
c6cbf941a2 | ||
|
277d1b2e10 | ||
|
46955a19c1 | ||
|
9ab3e942cd | ||
|
c7bb317ead | ||
|
241e72be1a | ||
|
f4fccc08c4 |
@ -27,7 +27,6 @@ set(TWN_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "")
|
|||||||
|
|
||||||
# feature configuration, set them with -DFEATURE=ON/OFF in cli
|
# feature configuration, set them with -DFEATURE=ON/OFF in cli
|
||||||
option(TWN_FEATURE_DYNLIB_GAME "Enable dynamic library loading support" ON)
|
option(TWN_FEATURE_DYNLIB_GAME "Enable dynamic library loading support" ON)
|
||||||
option(TWN_FEATURE_PUSH_AUDIO "Enable frame based audio push for easy realtime audio" ON)
|
|
||||||
option(TWN_USE_AMALGAM "Enable use of twn_amalgam.c as a single compilation unit" ON)
|
option(TWN_USE_AMALGAM "Enable use of twn_amalgam.c as a single compilation unit" ON)
|
||||||
|
|
||||||
# todo: figure out how to compile for dynamic linking instead
|
# todo: figure out how to compile for dynamic linking instead
|
||||||
@ -136,8 +135,6 @@ set_target_properties(${TWN_TARGET} PROPERTIES
|
|||||||
C_STANDARD_REQUIRED ON
|
C_STANDARD_REQUIRED ON
|
||||||
C_EXTENSIONS ON) # extensions are required by stb_ds.h
|
C_EXTENSIONS ON) # extensions are required by stb_ds.h
|
||||||
|
|
||||||
target_compile_definitions(${TWN_TARGET} PRIVATE $<$<BOOL:${TWN_FEATURE_PUSH_AUDIO}>:TWN_FEATURE_PUSH_AUDIO>)
|
|
||||||
|
|
||||||
# precompile commonly used not-so-small headers
|
# precompile commonly used not-so-small headers
|
||||||
target_precompile_headers(${TWN_TARGET} PRIVATE
|
target_precompile_headers(${TWN_TARGET} PRIVATE
|
||||||
$<$<NOT:$<BOOL:${EMSCRIPTEN}>>:third-party/glad/include/glad/glad.h>
|
$<$<NOT:$<BOOL:${EMSCRIPTEN}>>:third-party/glad/include/glad/glad.h>
|
||||||
|
@ -2,6 +2,8 @@ cmake_minimum_required(VERSION 3.21)
|
|||||||
cmake_policy(SET CMP0171 NEW)
|
cmake_policy(SET CMP0171 NEW)
|
||||||
project(twnlua LANGUAGES C)
|
project(twnlua LANGUAGES C)
|
||||||
|
|
||||||
|
option(TWN_OUT_DIR "Artifact destination" ${CMAKE_SOURCE_DIR})
|
||||||
|
|
||||||
if(NOT CMAKE_BUILD_TYPE)
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
set(CMAKE_BUILD_TYPE Debug)
|
set(CMAKE_BUILD_TYPE Debug)
|
||||||
endif()
|
endif()
|
||||||
@ -39,5 +41,5 @@ set(SOURCE_FILES
|
|||||||
${CMAKE_CURRENT_SOURCE_DIR}/luabind.c
|
${CMAKE_CURRENT_SOURCE_DIR}/luabind.c
|
||||||
)
|
)
|
||||||
|
|
||||||
cmake_path(GET CMAKE_SOURCE_DIR STEM LAST_ONLY GAME_PROJECT_NAME)
|
cmake_path(GET TWN_OUT_DIR STEM LAST_ONLY GAME_PROJECT_NAME)
|
||||||
use_townengine(${GAME_PROJECT_NAME} "${SOURCE_FILES}" ${CMAKE_SOURCE_DIR})
|
use_townengine(${GAME_PROJECT_NAME} "${SOURCE_FILES}" ${TWN_OUT_DIR})
|
||||||
|
3
bin/twn
3
bin/twn
@ -37,6 +37,9 @@ case "$1" in
|
|||||||
api-gen ) "$toolpath"/gen_api_header.sh
|
api-gen ) "$toolpath"/gen_api_header.sh
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
wiki ) xdg-open "file://$TWNROOT/docs/wiki/index.html"
|
||||||
|
;;
|
||||||
|
|
||||||
* ) echo "Unknown command."
|
* ) echo "Unknown command."
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
@ -24,12 +24,11 @@ if "--release" in argv:
|
|||||||
cmake += ["-DCMAKE_BUILD_TYPE=Release"]
|
cmake += ["-DCMAKE_BUILD_TYPE=Release"]
|
||||||
# pass arbitrary arguments over
|
# pass arbitrary arguments over
|
||||||
if "--" in argv:
|
if "--" in argv:
|
||||||
cmake += argv[argv.find("--"):]
|
cmake += argv[argv.index("--")+1:]
|
||||||
|
|
||||||
# if no root cmake file is present, infer it from `twn.toml:game.interpreter`
|
# if no root cmake file is present, infer it from `twn.toml:game.interpreter`
|
||||||
if not Path("CMakeLists.txt").is_file():
|
if not Path("CMakeLists.txt").is_file():
|
||||||
with open("data/twn.toml", "rb") as f:
|
config = tomllib.loads(Path("data/twn.toml").read_text())
|
||||||
config = tomllib.load(f)
|
|
||||||
cmake += ["-S", expandvars(config["game"]["interpreter"])]
|
cmake += ["-S", expandvars(config["game"]["interpreter"])]
|
||||||
|
|
||||||
run(cmake, check=True)
|
run(cmake, check=True)
|
||||||
|
44
docs/wiki/about-townengine.html
Normal file
44
docs/wiki/about-townengine.html
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Townengine Wiki : About Townengine</title>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1 style="margin-bottom:0in;">1. About Townengine</h1>
|
||||||
|
<a href="index.html">Go back
|
||||||
|
<p><a name="introduction"></a><strong>1.1 </strong><strong>Introduction</strong>
|
||||||
|
<blockquote>
|
||||||
|
<p>Townengine, {twn}, is an opinionated game development framework designed around ideas of simplicity, managed state,
|
||||||
|
care for old devices, portability, language agnosticism, use-case orientation, iterability and low latency.
|
||||||
|
<p><b>Simplicity.</b> It makes assumptions that trickle down to your game code. There's no delta between frames, nor resolution change.
|
||||||
|
Textures have constant known size, not requiring scaling.
|
||||||
|
<p><b>Managed state.</b> Designed around this we can provide hot reloading at any point,
|
||||||
|
serialization for save files and debug dumps, as well as synchronization over network, without any user code.
|
||||||
|
Every frame apparent engine state is cleared, which removes another variable for you to handle, - when to initialize.
|
||||||
|
There's no need for you to call `LoadImage()` of sorts before using it in render, you just pass filepaths around.
|
||||||
|
Input is initialized anew each frame, making rebinds trivial.
|
||||||
|
<p><b>Care for old devices.</b> It's to both to provide it for more people, who otherwise might not be able to make games they want,
|
||||||
|
as well as to have restrictions that constitute in desired aesthetic. Graphics capabilities are limited, but
|
||||||
|
what is present, - is heavily optimized. It is rather different from performance-driven approach that tries to take
|
||||||
|
advantage of the latest hardware and features, sacrificing both the reach and portability.
|
||||||
|
<p><b>Portability.</b> Written in C11 with all dependencies being in C, it's possible to compile it to most platforms.
|
||||||
|
SDL2 is at the center and you cannot get better than this. Default graphics API is OpenGL 1.5 with extension detection.
|
||||||
|
As an example, it builds and runs on Haiku OS with LLVMpipe.
|
||||||
|
<p><b>Language agnosticism.</b> API is restricted to not require much glue.
|
||||||
|
Language interpreters don't need to be part of the engine itself. Anything with C ABI support can link to it.
|
||||||
|
<p><b>Use-case orientation.</b> It doesn't try to be a yet another general purpose engine conquering all and nothing.
|
||||||
|
Instead we seek particular use cases and implement the most essential parts.
|
||||||
|
<p><b>Iterability.</b> Defaults provided for most of the API, making initial code faster to spring.
|
||||||
|
Hot reloading for both assets and code.
|
||||||
|
<p><b>Low latency.</b> Care is given to various incarnations of feared latency. Engine is fast to build, allowing for low commitment patches.
|
||||||
|
Startup time is profiled and optimized. Streaming is used as much as possible for asset load.
|
||||||
|
</blockquote>
|
||||||
|
<p><a name="wiki"></a><strong>1.2 </strong><strong>Wiki</strong>
|
||||||
|
<blockquote>
|
||||||
|
<p>Purpose of this wiki is to collect information on various usages of {twn} across the genres, FAQ style.
|
||||||
|
You're welcomed to contribute to it. It's written in HTML so basic you can edit it by hand.
|
||||||
|
Just check <a href="template.html">template.html</a>.
|
||||||
|
</blockquote>
|
||||||
|
</body>
|
||||||
|
</html>
|
24
docs/wiki/index.html
Normal file
24
docs/wiki/index.html
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Townengine Wiki</title>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Townengine Wiki</h1>
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td><strong>1.</strong> <a href="#about-townengine">About Townengnine</a></td>
|
||||||
|
<td><strong>2.</strong> <a href="#making-2dot5d-shooters">Making 2.5D Shooters</a></td>
|
||||||
|
</tr>
|
||||||
|
</tbody></table>
|
||||||
|
<p><a name="about-townengine"></a><strong>1. </strong><a href="about-townengine.html"><strong>About Townengine</strong></a></p>
|
||||||
|
<blockquote>
|
||||||
|
<p style="margin:0">1.1 <a href="about-townengine.html#introduction">Introduction</a></p>
|
||||||
|
<p style="margin:0">1.2 <a href="about-townengine.html#wiki">Wiki</a></p>
|
||||||
|
</blockquote>
|
||||||
|
<p><a name="making-2dot5d-shooters"></a><strong>2. </strong><a href="making-2dot5d-shooters.html"><strong>Making 2.5D Shooters</strong></a></p>
|
||||||
|
<blockquote>
|
||||||
|
</blockquote>
|
||||||
|
</body>
|
||||||
|
</html>
|
19
docs/wiki/style.css
Normal file
19
docs/wiki/style.css
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
/* https://wiki.c2.com/?WikiStyle */
|
||||||
|
body { margin: 1em 2.3em 1em 1.5em; zoom: 150%; padding-bottom: 50px;}
|
||||||
|
h1 { font-size: 2.1em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
p { margin-left: 0.2em;
|
||||||
|
}
|
||||||
|
blockquote {
|
||||||
|
font-style: normal;
|
||||||
|
}
|
||||||
|
pre { margin: 0em 3em 0em 2em;
|
||||||
|
color: rgb(20%,20%,50%); background-color: rgb(100%,100%,100%);
|
||||||
|
border: 1px solid rgb(50%,50%,50%);
|
||||||
|
padding: 1em;
|
||||||
|
font-size: 0.85em;
|
||||||
|
white-space: pre;
|
||||||
|
}
|
||||||
|
hr { color: rgb(30%,30%,60%);
|
||||||
|
}
|
15
docs/wiki/template.html
Normal file
15
docs/wiki/template.html
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Townengine Wiki : {About}</title>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1 style="margin-bottom:0in;">1. {About}</h1>
|
||||||
|
<a href="index.html">Go back
|
||||||
|
<p><a name="{Section}"></a><strong>1.1 </strong><strong>{Section}</strong>
|
||||||
|
<blockquote>
|
||||||
|
<p>Text
|
||||||
|
</blockquote>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -259,9 +259,8 @@ void audio_play(const char *path,
|
|||||||
request.format = AUDIO_F32;
|
request.format = AUDIO_F32;
|
||||||
request.channels = 2;
|
request.channels = 2;
|
||||||
request.samples = 4096;
|
request.samples = 4096;
|
||||||
#ifndef TWN_FEATURE_PUSH_AUDIO
|
if (!ctx.push_audio_model)
|
||||||
request.callback = audio_callback;
|
request.callback = audio_callback;
|
||||||
#endif
|
|
||||||
/* TODO: check for errors */
|
/* TODO: check for errors */
|
||||||
ctx.audio_device = SDL_OpenAudioDevice(NULL, 0, &request, &got, 0);
|
ctx.audio_device = SDL_OpenAudioDevice(NULL, 0, &request, &got, 0);
|
||||||
ctx.audio_stream_format = got.format;
|
ctx.audio_stream_format = got.format;
|
||||||
@ -279,6 +278,8 @@ void audio_play(const char *path,
|
|||||||
ctx.audio_initialized = true;
|
ctx.audio_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_LockAudioDevice(ctx.audio_device);
|
||||||
|
|
||||||
if (channel) {
|
if (channel) {
|
||||||
AudioChannelItem *pair = shgetp_null(ctx.audio_channels, channel);
|
AudioChannelItem *pair = shgetp_null(ctx.audio_channels, channel);
|
||||||
|
|
||||||
@ -331,6 +332,8 @@ void audio_play(const char *path,
|
|||||||
|
|
||||||
arrpush(ctx.unnamed_audio_channels, new_channel);
|
arrpush(ctx.unnamed_audio_channels, new_channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SDL_UnlockAudioDevice(ctx.audio_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ typedef struct EngineContext {
|
|||||||
/* signals mouse focus, used to disable mouse capture */
|
/* signals mouse focus, used to disable mouse capture */
|
||||||
bool window_mouse_resident;
|
bool window_mouse_resident;
|
||||||
bool audio_initialized;
|
bool audio_initialized;
|
||||||
|
bool push_audio_model;
|
||||||
bool cull_faces;
|
bool cull_faces;
|
||||||
} EngineContext;
|
} EngineContext;
|
||||||
|
|
||||||
|
@ -24,46 +24,7 @@
|
|||||||
static SDL_Thread *opengl_load_thread;
|
static SDL_Thread *opengl_load_thread;
|
||||||
|
|
||||||
|
|
||||||
static int event_callback(void *userdata, SDL_Event *event) {
|
/* note: it drives most of IO implicitly, such as audio callbacks */
|
||||||
(void)userdata;
|
|
||||||
|
|
||||||
switch (event->type) {
|
|
||||||
case SDL_WINDOWEVENT:
|
|
||||||
if (event->window.windowID != ctx.window_id)
|
|
||||||
break;
|
|
||||||
|
|
||||||
switch (event->window.event) {
|
|
||||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
|
||||||
ctx.window_dims.x = (float)event->window.data1;
|
|
||||||
ctx.window_dims.y = (float)event->window.data2;
|
|
||||||
ctx.resync_flag = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SDL_WINDOWEVENT_FOCUS_LOST: {
|
|
||||||
ctx.window_mouse_resident = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case SDL_WINDOWEVENT_FOCUS_GAINED: {
|
|
||||||
ctx.window_mouse_resident = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ignored */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void poll_events(void) {
|
static void poll_events(void) {
|
||||||
SDL_Event e;
|
SDL_Event e;
|
||||||
|
|
||||||
@ -81,9 +42,22 @@ static void poll_events(void) {
|
|||||||
|
|
||||||
switch (e.window.event) {
|
switch (e.window.event) {
|
||||||
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
case SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||||
|
ctx.window_dims.x = (float)e.window.data1;
|
||||||
|
ctx.window_dims.y = (float)e.window.data2;
|
||||||
|
ctx.resync_flag = true;
|
||||||
ctx.window_size_has_changed = true;
|
ctx.window_size_has_changed = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case SDL_WINDOWEVENT_FOCUS_LOST: {
|
||||||
|
ctx.window_mouse_resident = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case SDL_WINDOWEVENT_FOCUS_GAINED: {
|
||||||
|
ctx.window_mouse_resident = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -226,8 +200,9 @@ static void main_loop(void) {
|
|||||||
input_state_update_postframe(&ctx.input);
|
input_state_update_postframe(&ctx.input);
|
||||||
|
|
||||||
/* TODO: make it works when ctx.ticks_per_second != 60 */
|
/* TODO: make it works when ctx.ticks_per_second != 60 */
|
||||||
#ifdef TWN_FEATURE_PUSH_AUDIO
|
if (ctx.push_audio_model) {
|
||||||
uint64_t const queued_frames = SDL_GetQueuedAudioSize(ctx.audio_device) / sizeof (float) / 2;
|
uint64_t const queued_frames = SDL_GetQueuedAudioSize(ctx.audio_device) / sizeof (float) / 2;
|
||||||
|
/* note: this is here to reduce drift which sometimes appears */
|
||||||
if (queued_frames >= 4096 * 2)
|
if (queued_frames >= 4096 * 2)
|
||||||
SDL_ClearQueuedAudio(ctx.audio_device);
|
SDL_ClearQueuedAudio(ctx.audio_device);
|
||||||
static uint8_t audio_buffer[(AUDIO_FREQUENCY / 60) * sizeof (float) * 2];
|
static uint8_t audio_buffer[(AUDIO_FREQUENCY / 60) * sizeof (float) * 2];
|
||||||
@ -236,7 +211,7 @@ static void main_loop(void) {
|
|||||||
if (SDL_QueueAudio(ctx.audio_device, audio_buffer, sizeof audio_buffer))
|
if (SDL_QueueAudio(ctx.audio_device, audio_buffer, sizeof audio_buffer))
|
||||||
CRY_SDL("Error queueing audio: ");
|
CRY_SDL("Error queueing audio: ");
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
|
|
||||||
/* TODO: ctx.game_copy = ctx.game should be placed after it, but it messes with state used in render() */
|
/* TODO: ctx.game_copy = ctx.game should be placed after it, but it messes with state used in render() */
|
||||||
preserve_persistent_ctx_fields();
|
preserve_persistent_ctx_fields();
|
||||||
@ -546,9 +521,6 @@ static bool initialize(void) {
|
|||||||
ctx.game.resolution.x = (float)ctx.base_render_width;
|
ctx.game.resolution.x = (float)ctx.base_render_width;
|
||||||
ctx.game.resolution.y = (float)ctx.base_render_height;
|
ctx.game.resolution.y = (float)ctx.base_render_height;
|
||||||
|
|
||||||
/* add a watcher for immediate updates on window size */
|
|
||||||
SDL_AddEventWatch(event_callback, NULL);
|
|
||||||
|
|
||||||
/* random seeding */
|
/* random seeding */
|
||||||
/* SDL_GetPerformanceCounter returns some platform-dependent number. */
|
/* SDL_GetPerformanceCounter returns some platform-dependent number. */
|
||||||
/* it should vary between game instances. i checked! random enough for me. */
|
/* it should vary between game instances. i checked! random enough for me. */
|
||||||
@ -583,8 +555,7 @@ static bool initialize(void) {
|
|||||||
ctx.time_averager[i] = ctx.desired_frametime;
|
ctx.time_averager[i] = ctx.desired_frametime;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* rendering */
|
/* engine configuration */
|
||||||
/* configuration */
|
|
||||||
{
|
{
|
||||||
toml_datum_t datum_texture_atlas_size = toml_int_in(engine, "texture_atlas_size");
|
toml_datum_t datum_texture_atlas_size = toml_int_in(engine, "texture_atlas_size");
|
||||||
if (!datum_texture_atlas_size.ok) {
|
if (!datum_texture_atlas_size.ok) {
|
||||||
@ -639,11 +610,10 @@ static bool initialize(void) {
|
|||||||
} else {
|
} else {
|
||||||
ctx.cull_faces = datum_cull_faces.u.b;
|
ctx.cull_faces = datum_cull_faces.u.b;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* these are dynamic arrays and will be allocated lazily by stb_ds */
|
toml_datum_t datum_audio_model = toml_string_in(engine, "audio_model");
|
||||||
ctx.render_queue_2d = NULL;
|
ctx.push_audio_model = datum_audio_model.ok ? SDL_strncmp(datum_audio_model.u.s, "push", sizeof "push" - 1) == 0 : false;
|
||||||
ctx.uncolored_mesh_batches = NULL;
|
SDL_free(datum_audio_model.u.s);
|
||||||
|
|
||||||
/* input */
|
/* input */
|
||||||
toml_datum_t datum_keybind_slots = toml_int_in(engine, "keybind_slots");
|
toml_datum_t datum_keybind_slots = toml_int_in(engine, "keybind_slots");
|
||||||
@ -656,6 +626,8 @@ static bool initialize(void) {
|
|||||||
ctx.keybind_slots = datum_keybind_slots.u.i;
|
ctx.keybind_slots = datum_keybind_slots.u.i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
input_state_init(&ctx.input);
|
input_state_init(&ctx.input);
|
||||||
|
|
||||||
ctx.render_double_buffered = true;
|
ctx.render_double_buffered = true;
|
||||||
@ -675,6 +647,11 @@ static bool initialize(void) {
|
|||||||
profile_end("opengl loading");
|
profile_end("opengl loading");
|
||||||
|
|
||||||
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
|
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
|
||||||
|
SDL_SetHint(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, "1");
|
||||||
|
SDL_SetHint(SDL_HINT_WAVE_FACT_CHUNK, "ignorezero");
|
||||||
|
SDL_SetHint(SDL_HINT_VIDEO_DOUBLE_BUFFER, "1");
|
||||||
|
if (ctx.game.debug)
|
||||||
|
SDL_SetHint(SDL_HINT_SHUTDOWN_DBUS_ON_QUIT, "1");
|
||||||
|
|
||||||
/* TODO: investigate viability of detached thread driver and window creation, as it's the worst load time offender */
|
/* TODO: investigate viability of detached thread driver and window creation, as it's the worst load time offender */
|
||||||
profile_start("window creation");
|
profile_start("window creation");
|
||||||
|
Loading…
Reference in New Issue
Block a user