summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonAki <konaki@anokonaki.org>2026-10-09 17:51:49 +0800
committerKonAki <konaki@anokonaki.org>2026-10-09 17:51:49 +0800
commiteca47efac07ffa6c4e35708031dea8a7da4e7ed8 (patch)
tree5d16ccd0309b97c77a3960c20c1a3137753678bd
parent3e4acddeb4df4d21ad89b8926aa2eafc634daa25 (diff)
Add konprogram and use it in engine.c
-rw-r--r--Makefile2
-rwxr-xr-xbuild.sh23
-rw-r--r--kon/konprogram.c227
-rw-r--r--kon/konprogram.h83
-rw-r--r--src/engine.c205
5 files changed, 367 insertions, 173 deletions
diff --git a/Makefile b/Makefile
index e9c1bc0..ffec53e 100644
--- a/Makefile
+++ b/Makefile
@@ -26,7 +26,7 @@ EXAMPLES = modelview
EXAMPLEBINS = $(EXAMPLES:%=$(OBJDIR)/%$(EXE))
PACKFILE = $(OBJDIR)/data.kpk
CORE = $(OBJDIR)/engine.o $(OBJDIR)/konwinlib.o $(OBJDIR)/konsofren.o \
- $(OBJDIR)/kontime.o $(OBJDIR)/koninput.o
+ $(OBJDIR)/kontime.o $(OBJDIR)/koninput.o $(OBJDIR)/konprogram.o
OBJS = $(CORE) $(MODOBJS)
all: $(BIN)
diff --git a/build.sh b/build.sh
index 5bdd541..b5cb78e 100755
--- a/build.sh
+++ b/build.sh
@@ -93,15 +93,20 @@ for m in $modules; do
esac
done
-case " $modules " in
-*" assets "*|*" model "*) addobj konpack ;;
-esac
-case " $modules " in
-*" ui "*) addobj konfont ;;
-esac
-case " $modules " in
-*" debug "*) addobj konfont; addobj konassets; addobj konpack ;;
-esac
+need()
+{
+ case " $DEFS " in
+ *" -DKON_MODULE_$(echo "$1" | tr 'a-z' 'A-Z') "*) ;;
+ *) DEFS="$DEFS -DKON_MODULE_$(echo "$1" | tr 'a-z' 'A-Z')" ;;
+ esac
+ addobj "kon$1"
+}
+
+# modules that use other modules
+case " $modules " in *" debug "*) need font; need assets ;; esac
+case " $modules " in *" ui "*) need font ;; esac
+case " $modules " in *" model "*) need assets ;; esac
+case " $DEFS " in *" -DKON_MODULE_ASSETS "*) need pack ;; esac
case " $modules " in
*" debug "*) [ $developer = 1 ] || echo "note: debug module does nothing without -d or -D" ;;
diff --git a/kon/konprogram.c b/kon/konprogram.c
new file mode 100644
index 0000000..33e1f15
--- /dev/null
+++ b/kon/konprogram.c
@@ -0,0 +1,227 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * konprogram.c
+ *
+ * Copyright (c) 2026 KonAki
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+/* the debug functions only exist with the debug module, without KON_DEVELOPER the header gives empty ones instead */
+#if defined(KON_DEVELOPER) && !defined(KON_MODULE_DEBUG)
+#undef KON_DEVELOPER
+#endif
+
+#include "konprogram.h"
+#include "kontime.h"
+
+/*** definition ***/
+
+typedef struct kon_programState {
+ kon_program_t pub;
+ kon_programConfig_t config;
+ kon_time last;
+ float shakeLeft;
+ int shakeX, shakeY;
+} kon_programState_t;
+
+/*** console commands ***/
+
+#ifdef KON_DEVELOPER
+
+static void kon_cmdOpacity_(kon_debug_t *debug, void *user, int argc, char **argv) {
+ kon_programState_t *state = user;
+
+ (void)debug;
+ if (argc > 1) kon_setWindowOpacity(state->pub.window, (float)atof(argv[1]));
+}
+
+static void kon_cmdTopmost_(kon_debug_t *debug, void *user, int argc, char **argv) {
+ kon_programState_t *state = user;
+
+ (void)debug;
+ if (argc > 1) kon_setWindowTopmost(state->pub.window, atoi(argv[1]) != 0);
+}
+
+static void kon_cmdBorderless_(kon_debug_t *debug, void *user, int argc, char **argv) {
+ kon_programState_t *state = user;
+
+ (void)debug;
+ if (argc > 1) kon_setWindowDecorated(state->pub.window, atoi(argv[1]) == 0);
+}
+
+static void kon_cmdClickThrough_(kon_debug_t *debug, void *user, int argc, char **argv) {
+ kon_programState_t *state = user;
+
+ (void)debug;
+ if (argc > 1) kon_setWindowClickThrough(state->pub.window, atoi(argv[1]) != 0);
+}
+
+static void kon_cmdMessage_(kon_debug_t *debug, void *user, int argc, char **argv) {
+ (void)debug; (void)user;
+ kon_messageBox("konengine", argc > 1 ? argv[1] : "hello", KON_MESSAGE_INFO);
+}
+
+static void kon_cmdShake_(kon_debug_t *debug, void *user, int argc, char **argv) {
+ kon_programState_t *state = user;
+
+ (void)debug; (void)argc; (void)argv;
+ kon_getWindowPos(state->pub.window, &state->shakeX, &state->shakeY);
+ state->shakeLeft = 0.5f;
+}
+
+static void kon_addWindowCommands_(kon_programState_t *state) {
+ kon_debug_t *debug = state->pub.debug;
+
+ kon_debugCommand(debug, "opacity", "window opacity 0 to 1", kon_cmdOpacity_, state);
+ kon_debugCommand(debug, "topmost", "topmost 0 or 1", kon_cmdTopmost_, state);
+ kon_debugCommand(debug, "borderless", "borderless 0 or 1", kon_cmdBorderless_, state);
+ kon_debugCommand(debug, "clickthrough", "clickthrough 0 or 1", kon_cmdClickThrough_, state);
+ kon_debugCommand(debug, "message", "message \"text\"", kon_cmdMessage_, state);
+ kon_debugCommand(debug, "shake", "shake the window", kon_cmdShake_, state);
+}
+
+#endif
+
+/*** loop ***/
+
+static void kon_frame_(void *data) {
+ kon_programState_t *state = data;
+ kon_program_t *program = &state->pub;
+ const kon_programConfig_t *config = &state->config;
+ kon_display_t *display = program->display;
+ kon_event_t ev;
+ kon_time now, dt;
+
+ while (kon_pollEvent(program->window, &ev)) {
+ if (kon_debugFeedEvent(program->debug, &ev)) continue;
+ if (ev.type == KON_EVENT_RESIZE) kon_resizeDisplay(display, ev.width, ev.height);
+ if (config->event) config->event(program, &ev, config->user);
+ }
+
+ now = kon_getTime();
+ dt = now - state->last;
+ state->last = now;
+ /* a long stall, like dragging the window, shouldn't make the game jump */
+ if (dt > 0.25) dt = 0.25;
+ program->time += dt;
+
+ if (state->shakeLeft > 0.0f) {
+ state->shakeLeft -= (float)dt;
+ if (state->shakeLeft > 0.0f) kon_setWindowPos(program->window, state->shakeX + rand() % 21 - 10, state->shakeY + rand() % 21 - 10);
+ else kon_setWindowPos(program->window, state->shakeX, state->shakeY);
+ }
+
+ if (config->update) config->update(program, dt, config->user);
+ kon_clearFramebuffer(display->game, KON_BACKGROUND_COLOR);
+ if (config->draw) config->draw(program, display->game, config->user);
+
+ kon_presentDisplay(display);
+ if (config->drawScreen) config->drawScreen(program, display->screen, config->user);
+ kon_debugFrame(program->debug);
+ if (kon_debugQuitRequested(program->debug)) kon_setShouldClose(program->window, true);
+ kon_debugDraw(program->debug, display->screen);
+ kon_blitPixels(program->window, display->screen->data, display->screen->width, display->screen->height);
+ kon_sleep(0.008);
+}
+
+void kon_programQuit(kon_program_t *program) {
+ if (program) kon_setShouldClose(program->window, true);
+}
+
+int kon_programRun(const kon_programConfig_t *config) {
+ kon_programState_t *state;
+ kon_program_t *program;
+ int gameWidth, gameHeight, windowWidth, windowHeight;
+
+ if (!config) return 1;
+ state = calloc(1, sizeof *state);
+ if (!state) return 1;
+ program = &state->pub;
+ state->config = *config;
+
+ gameWidth = config->gameWidth > 0 ? config->gameWidth : 320;
+ gameHeight = config->gameHeight > 0 ? config->gameHeight : 180;
+ windowWidth = config->windowWidth > 0 ? config->windowWidth : gameWidth * 3;
+ windowHeight = config->windowHeight > 0 ? config->windowHeight : gameHeight * 3;
+
+ if (!kon_init()) goto fail;
+ program->window = kon_createWindow(config->title ? config->title : "konengine", 0, 0, windowWidth, windowHeight, KON_WINDOW_CENTER | KON_WINDOW_RESIZABLE);
+ if (!program->window) goto fail;
+#ifdef KON_DEVELOPER
+ kon_setExitKey(program->window, KON_KEY_F10);
+#else
+ kon_setExitKey(program->window, KON_KEY_ESCAPE);
+#endif
+ program->display = kon_createDisplay(gameWidth, gameHeight, windowWidth, windowHeight);
+ if (!program->display) goto fail;
+
+#ifdef KON_MODULE_PACK
+ if (config->packPath) program->pack = kon_packOpen(config->packPath, NULL);
+#endif
+#ifdef KON_MODULE_ASSETS
+ program->assets = kon_assetsCreate(program->pack, config->assetDir ? config->assetDir : "assets");
+#endif
+#ifdef KON_MODULE_FONT
+ {
+ kon_blob_t *ttf = program->assets ? kon_assetBlob(program->assets, "font.ttf") : NULL;
+
+ if (ttf) program->font = kon_loadFont(ttf->data, ttf->size, 14.0f);
+ if (!program->font) program->font = kon_loadBuiltinFont(1);
+ }
+#endif
+#ifdef KON_MODULE_DEBUG
+ program->debug = kon_debugCreate(program->font);
+ kon_debugSetAssets(program->debug, program->assets);
+#ifdef KON_DEVELOPER
+ kon_addWindowCommands_(state);
+#endif
+#endif
+
+ state->last = kon_getTime();
+ if (config->init && !config->init(program, config->user)) goto fail;
+
+ kon_runMainLoop(program->window, kon_frame_, state);
+
+ if (config->shutdown) config->shutdown(program, config->user);
+ kon_debugDestroy(program->debug);
+#ifdef KON_MODULE_FONT
+ kon_freeFont(program->font);
+#endif
+#ifdef KON_MODULE_ASSETS
+ kon_assetsDestroy(program->assets);
+#endif
+#ifdef KON_MODULE_PACK
+ if (program->pack) kon_packClose(program->pack);
+#endif
+ kon_freeDisplay(program->display);
+ kon_destroyWindow(program->window);
+ kon_deinit();
+ free(state);
+ return 0;
+
+fail:
+ if (program->display) kon_freeDisplay(program->display);
+ if (program->window) kon_destroyWindow(program->window);
+ free(state);
+ return 1;
+}
diff --git a/kon/konprogram.h b/kon/konprogram.h
new file mode 100644
index 0000000..f0a29b3
--- /dev/null
+++ b/kon/konprogram.h
@@ -0,0 +1,83 @@
+/* SPDX-License-Identifier: MIT */
+/*
+ * konprogram.h
+ *
+ * Copyright (c) 2026 KonAki
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#ifndef KONPROGRAM_H
+#define KONPROGRAM_H
+
+#include <stdint.h>
+
+#include "konwinlib.h"
+#include "konsofren.h"
+#include "konpack.h"
+#include "konassets.h"
+#include "konfont.h"
+#include "kondebug.h"
+
+/*** definition ***/
+
+typedef struct kon_program kon_program_t;
+
+/* every field can be left at 0. the callbacks are all optional too */
+typedef struct kon_programConfig {
+ const char *title; /* "konengine" */
+ int gameWidth, gameHeight; /* the size you draw at, 320 x 180 */
+ int windowWidth, windowHeight; /* 3 times the game size */
+ const char *assetDir; /* folder with loose files, "assets". only used with KON_DEVELOPER */
+ const char *packPath; /* pack file to read assets from, none if NULL */
+ void *user; /* given back to every callback */
+
+ /* return 0 to quit before the loop starts */
+ int (*init)(kon_program_t *program, void *user);
+ /* gets every event the console didn't take, resizes are already handled. return 1 if you used it */
+ int (*event)(kon_program_t *program, const kon_event_t *event, void *user);
+ void (*update)(kon_program_t *program, double dt, void *user);
+ /* draw into the game framebuffer, it is scaled to the window afterwards */
+ void (*draw)(kon_program_t *program, kon_framebuffer_t *game, void *user);
+ /* draw at window resolution on top of the scaled game, for text and UI that has to stay sharp */
+ void (*drawScreen)(kon_program_t *program, kon_framebuffer_t *screen, void *user);
+ void (*shutdown)(kon_program_t *program, void *user);
+} kon_programConfig_t;
+
+/* what is not built is NULL, so assets is NULL without the assets module and debug is NULL without the debug module.
+ font is the font.ttf from your assets if there is one, otherwise the built in one, and it is NULL without the font module */
+struct kon_program {
+ kon_window_t *window;
+ kon_display_t *display;
+ kon_pack_t *pack;
+ kon_assets_t *assets;
+ kon_font_t *font;
+ kon_debug_t *debug;
+ double time; /* seconds since the loop started */
+};
+
+/*** declarations ***/
+
+/* does everything from opening the window to cleaning up and returns when the program is closed.
+ returns 0, or 1 if something failed to start. a program that wants its own loop doesn't need this */
+int kon_programRun(const kon_programConfig_t *config);
+
+void kon_programQuit(kon_program_t *program);
+
+#endif
diff --git a/src/engine.c b/src/engine.c
index 15fae3d..1594032 100644
--- a/src/engine.c
+++ b/src/engine.c
@@ -1,187 +1,66 @@
-#include "konwinlib.h"
-#include "konsofren.h"
-#include <stdlib.h>
+#include "konprogram.h"
-#include "kontime.h"
-
-#ifdef KON_MODULE_DEBUG
-#include "konassets.h"
-#include "konfont.h"
-#include "kondebug.h"
-#endif
-
-#define GAME_WIDTH 320
-#define GAME_HEIGHT 180
-
-typedef struct program {
- kon_window_t *window;
- kon_display_t *display;
+typedef struct demo {
kon_camera_t camera;
kon_material_t material;
kon_light_t light;
- kon_time last;
float angle;
-#ifdef KON_MODULE_DEBUG
- kon_assets_t *assets;
- kon_font_t *font;
- kon_debug_t *debug;
- float shakeLeft;
- int baseX, baseY;
-#endif
-} program_t;
+ int ortho;
+} demo_t;
-#ifdef KON_MODULE_DEBUG
-static void cmdOpacity(kon_debug_t *debug, void *user, int argc, char **argv)
+static int init(kon_program_t *program, void *user)
{
- program_t *program = user;
-
- (void)debug;
- if (argc > 1) kon_setWindowOpacity(program->window, (float)atof(argv[1]));
+ demo_t *demo = user;
+
+ (void)program;
+ demo->camera = kon_cameraDefault();
+ demo->camera.position = KON_VEC3(3, 3, 6);
+ demo->material = kon_materialColor(0xFFC8C8FF);
+ demo->light = kon_lightDefault();
+ return 1;
}
-static void cmdTopmost(kon_debug_t *debug, void *user, int argc, char **argv)
+static int event(kon_program_t *program, const kon_event_t *ev, void *user)
{
- program_t *program = user;
+ demo_t *demo = user;
- (void)debug;
- if (argc > 1) kon_setWindowTopmost(program->window, atoi(argv[1]) != 0);
-}
-
-static void cmdBorderless(kon_debug_t *debug, void *user, int argc, char **argv)
-{
- program_t *program = user;
-
- (void)debug;
- if (argc > 1) kon_setWindowDecorated(program->window, atoi(argv[1]) == 0);
+ (void)program;
+ if (ev->type == KON_EVENT_KEY_DOWN && ev->key == KON_KEY_O) {
+ demo->ortho = !demo->ortho;
+ demo->camera.projection = demo->ortho ? KON_PROJECTION_ORTHOGRAPHIC : KON_PROJECTION_PERSPECTIVE;
+ return 1;
+ }
+ return 0;
}
-static void cmdClickThrough(kon_debug_t *debug, void *user, int argc, char **argv)
+static void update(kon_program_t *program, double dt, void *user)
{
- program_t *program = user;
+ demo_t *demo = user;
- (void)debug;
- if (argc > 1) kon_setWindowClickThrough(program->window, atoi(argv[1]) != 0);
+ (void)program;
+ demo->angle += (float)dt;
}
-static void cmdMessage(kon_debug_t *debug, void *user, int argc, char **argv)
+static void draw(kon_program_t *program, kon_framebuffer_t *game, void *user)
{
- (void)debug; (void)user;
- kon_messageBox("konengine", argc > 1 ? argv[1] : "hello", KON_MESSAGE_INFO);
-}
+ demo_t *demo = user;
+ kon_mat4_t model = kon_mat4Rotate(kon_mat4Identity(), KON_VEC3(demo->angle * 0.5f, demo->angle, 0));
+ kon_mat4_t viewProjection = kon_cameraViewProjection(&demo->camera, game->width, game->height);
-static void cmdShake(kon_debug_t *debug, void *user, int argc, char **argv)
-{
- program_t *program = user;
-
- (void)debug; (void)argc; (void)argv;
- kon_getWindowPos(program->window, &program->baseX, &program->baseY);
- program->shakeLeft = 0.5f;
-}
-#endif
-
-static void frame(void *data)
-{
- program_t *program = (program_t *)data;
- kon_display_t *display = program->display;
- kon_event_t ev;
- kon_time now, dt;
- kon_mat4_t model, viewProjection;
-
- while (kon_pollEvent(program->window, &ev)) {
-#ifdef KON_MODULE_DEBUG
- if (kon_debugFeedEvent(program->debug, &ev)) continue;
-#endif
- if (ev.type == KON_EVENT_RESIZE) {
- kon_resizeDisplay(display, ev.width, ev.height);
- }
- if (ev.type == KON_EVENT_KEY_DOWN && ev.key == KON_KEY_O) {
- program->camera.projection = (program->camera.projection == KON_PROJECTION_PERSPECTIVE)
- ? KON_PROJECTION_ORTHOGRAPHIC : KON_PROJECTION_PERSPECTIVE;
- }
- }
-
- now = kon_getTime();
- dt = now - program->last;
- program->angle += (float)dt;
- program->last = now;
-
-#ifdef KON_MODULE_DEBUG
- if (program->shakeLeft > 0.0f) {
- program->shakeLeft -= (float)dt;
- if (program->shakeLeft > 0.0f) kon_setWindowPos(program->window, program->baseX + rand() % 21 - 10, program->baseY + rand() % 21 - 10);
- else kon_setWindowPos(program->window, program->baseX, program->baseY);
- }
-#endif
-
- model = kon_mat4Identity();
- model = kon_mat4Rotate(model, KON_VEC3(program->angle * 0.5f, program->angle, 0));
- viewProjection = kon_cameraViewProjection(&program->camera, display->game->width, display->game->height);
-
- kon_clearFramebuffer(display->game, KON_BACKGROUND_COLOR);
- kon_drawMesh(display->game, viewProjection, model, &kon_cubeMesh, &program->material, &program->light, KON_RENDER_DEFAULT);
-
- kon_presentDisplay(display);
-#ifdef KON_MODULE_DEBUG
- kon_debugFrame(program->debug);
- if (kon_debugQuitRequested(program->debug)) kon_setShouldClose(program->window, true);
- kon_debugDraw(program->debug, display->screen);
-#endif
- kon_blitPixels(program->window, display->screen->data, display->screen->width, display->screen->height);
- kon_sleep(0.008);
+ (void)program;
+ kon_drawMesh(game, viewProjection, model, &kon_cubeMesh, &demo->material, &demo->light, KON_RENDER_DEFAULT);
}
int main(void)
{
- program_t program = {0};
-
- if (!kon_init()) return 1;
-
- program.window = kon_createWindow("engine", 0, 0, 800, 600, KON_WINDOW_CENTER | KON_WINDOW_RESIZABLE);
- if (!program.window) return 1;
-#ifdef KON_DEVELOPER
- kon_setExitKey(program.window, KON_KEY_F10);
-#else
- kon_setExitKey(program.window, KON_KEY_ESCAPE);
-#endif
-
- program.display = kon_createDisplay(GAME_WIDTH, GAME_HEIGHT, 800, 600);
- if (!program.display) return 1;
-
- program.camera = kon_cameraDefault();
- program.camera.position = KON_VEC3(3, 3, 6);
- program.material = kon_materialColor(0xFFC8C8FF);
- program.light = kon_lightDefault();
- program.last = kon_getTime();
-
-#ifdef KON_MODULE_DEBUG
- program.assets = kon_assetsCreate(NULL, "assets");
- {
- kon_blob_t *ttf = kon_assetBlob(program.assets, "font.ttf");
-
- if (ttf) program.font = kon_loadFont(ttf->data, ttf->size, 14.0f);
- if (!program.font) program.font = kon_loadBuiltinFont(1);
- program.debug = kon_debugCreate(program.font);
- kon_debugSetAssets(program.debug, program.assets);
- kon_debugCommand(program.debug, "opacity", "window opacity 0 to 1", cmdOpacity, &program);
- kon_debugCommand(program.debug, "topmost", "topmost 0 or 1", cmdTopmost, &program);
- kon_debugCommand(program.debug, "borderless", "borderless 0 or 1", cmdBorderless, &program);
- kon_debugCommand(program.debug, "clickthrough", "clickthrough 0 or 1", cmdClickThrough, &program);
- kon_debugCommand(program.debug, "message", "message \"text\"", cmdMessage, &program);
- kon_debugCommand(program.debug, "shake", "shake the window", cmdShake, &program);
- kon_debugLog(program.debug, ttf ? "loaded font.ttf" : "no assets/font.ttf, using the built in font");
- }
-#endif
-
- kon_runMainLoop(program.window, frame, &program);
-
-#ifdef KON_MODULE_DEBUG
- kon_debugDestroy(program.debug);
- kon_freeFont(program.font);
- kon_assetsDestroy(program.assets);
-#endif
-
- kon_freeDisplay(program.display);
- kon_destroyWindow(program.window);
- kon_deinit();
- return 0;
+ demo_t demo = {0};
+ kon_programConfig_t config = {0};
+
+ config.title = "engine";
+ config.user = &demo;
+ config.init = init;
+ config.event = event;
+ config.update = update;
+ config.draw = draw;
+ return kon_programRun(&config);
}