summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author3gg <3gg@shellblade.net>2024-03-09 08:43:26 -0800
committer3gg <3gg@shellblade.net>2024-03-09 08:43:26 -0800
commitadbd2511beec8f1caa1752bdfd755cc2f62ba425 (patch)
tree8fde167e9d9951b43e571a2417ae55f9572bea28
parent4bc4ca2796bd434880b77d3c4bcbb56107456777 (diff)
Make isogfx a library instead of an executable.
-rw-r--r--game/src/game.c27
-rw-r--r--gfx-app/include/gfx/gfx_app.h53
-rw-r--r--gfx-app/src/gfx_app.c6
-rw-r--r--gfx-iso/CMakeLists.txt29
-rw-r--r--gfx-iso/app/app.h12
-rw-r--r--gfx-iso/app/checkerboard.h9
-rw-r--r--gfx-iso/app/isogfx-demo.h9
-rw-r--r--gfx-iso/demos/CMakeLists.txt2
-rw-r--r--gfx-iso/demos/checkerboard/CMakeLists.txt15
-rw-r--r--gfx-iso/demos/checkerboard/checkerboard.c (renamed from gfx-iso/app/checkerboard.c)92
-rw-r--r--gfx-iso/demos/isomap/CMakeLists.txt15
-rw-r--r--gfx-iso/demos/isomap/isomap.c (renamed from gfx-iso/app/isogfx-demo.c)91
-rw-r--r--gfx-iso/include/isogfx/app.h22
-rw-r--r--gfx-iso/src/app.c (renamed from gfx-iso/app/main.c)111
-rw-r--r--gfx-iso/tools/mkasset.py (renamed from gfx-iso/asset/mkasset.py)0
15 files changed, 259 insertions, 234 deletions
diff --git a/game/src/game.c b/game/src/game.c
index c720656..dc4ab84 100644
--- a/game/src/game.c
+++ b/game/src/game.c
@@ -39,6 +39,10 @@ static const int WIDTH = 1350;
39static const int HEIGHT = 900; 39static const int HEIGHT = 900;
40static const int MAX_FPS = 60; 40static const int MAX_FPS = 60;
41 41
42typedef struct GfxAppState {
43 Game game;
44} GfxAppState;
45
42/// Initialize the game's plugin. 46/// Initialize the game's plugin.
43static bool init_plugin(Game* game) { 47static bool init_plugin(Game* game) {
44 assert(game); 48 assert(game);
@@ -113,17 +117,11 @@ static void resize_plugin(Game* game, int width, int height) {
113 117
114void app_end(Game* game); 118void app_end(Game* game);
115 119
116bool app_init(const GfxAppDesc* desc, void** app_state) { 120bool app_init(Game* game, int argc, const char** argv) {
117 assert(desc); 121 assert(game);
118
119 if (desc->argc <= 1) {
120 LOGE("Usage: %s <plugin> [plugin args]", desc->argv[0]);
121 return false;
122 }
123 122
124 Game* game = calloc(1, sizeof(Game)); 123 if (argc <= 1) {
125 if (!game) { 124 LOGE("Usage: %s <plugin> [plugin args]", argv[0]);
126 LOGE("Failed to allocate game state");
127 return false; 125 return false;
128 } 126 }
129 127
@@ -131,8 +129,8 @@ bool app_init(const GfxAppDesc* desc, void** app_state) {
131 // 129 //
132 // Here we consume the <plugin> arg so that plugins receive the remainder 130 // Here we consume the <plugin> arg so that plugins receive the remainder
133 // args starting from 0. 131 // args starting from 0.
134 game->argc = desc->argc - 1; 132 game->argc = argc - 1;
135 game->argv = desc->argv + 1; 133 game->argv = argv + 1;
136 134
137 char exe_path_buf[NAME_MAX] = {0}; 135 char exe_path_buf[NAME_MAX] = {0};
138 if (readlink("/proc/self/exe", exe_path_buf, sizeof(exe_path_buf)) == -1) { 136 if (readlink("/proc/self/exe", exe_path_buf, sizeof(exe_path_buf)) == -1) {
@@ -152,7 +150,7 @@ bool app_init(const GfxAppDesc* desc, void** app_state) {
152 goto cleanup; 150 goto cleanup;
153 } 151 }
154 152
155 const char* plugin = desc->argv[1]; 153 const char* plugin = argv[1];
156 if (!(game->plugin = load_plugin(game->plugin_engine, plugin))) { 154 if (!(game->plugin = load_plugin(game->plugin_engine, plugin))) {
157 goto cleanup; 155 goto cleanup;
158 } 156 }
@@ -168,7 +166,6 @@ bool app_init(const GfxAppDesc* desc, void** app_state) {
168 goto cleanup; 166 goto cleanup;
169 } 167 }
170 168
171 *app_state = game;
172 return true; 169 return true;
173 170
174cleanup: 171cleanup:
@@ -223,4 +220,4 @@ void app_resize(Game* game, int width, int height) {
223 resize_plugin(game, width, height); 220 resize_plugin(game, width, height);
224} 221}
225 222
226GFX_APP_MAIN(WIDTH, HEIGHT, MAX_FPS); 223GFX_APP_MAIN(WIDTH, HEIGHT, MAX_FPS, "Game");
diff --git a/gfx-app/include/gfx/gfx_app.h b/gfx-app/include/gfx/gfx_app.h
index 86c502a..ffff4bc 100644
--- a/gfx-app/include/gfx/gfx_app.h
+++ b/gfx-app/include/gfx/gfx_app.h
@@ -2,6 +2,8 @@
2 2
3#include <stdbool.h> 3#include <stdbool.h>
4 4
5typedef struct GfxAppState GfxAppState;
6
5/// Application settings. 7/// Application settings.
6typedef struct GfxAppDesc { 8typedef struct GfxAppDesc {
7 int argc; // Number of application arguments. 9 int argc; // Number of application arguments.
@@ -11,21 +13,22 @@ typedef struct GfxAppDesc {
11 int max_fps; // Desired maximum display framerate. 0 to disable. 13 int max_fps; // Desired maximum display framerate. 0 to disable.
12 double update_delta_time; // Desired delta time between frame updates. 14 double update_delta_time; // Desired delta time between frame updates.
13 const char* title; // Window title. 15 const char* title; // Window title.
16 GfxAppState* app_state;
14} GfxAppDesc; 17} GfxAppDesc;
15 18
16typedef bool (*GfxAppInit)(const GfxAppDesc*, void** app_state); 19typedef bool (*GfxAppInit)(GfxAppState*, int argc, const char** argv);
17typedef void (*GfxAppUpdate)(void* app_state, double t, double dt); 20typedef void (*GfxAppShutdown)(GfxAppState*);
18typedef void (*GfxAppRender)(void* app_state); 21typedef void (*GfxAppUpdate)(GfxAppState*, double t, double dt);
19typedef void (*GfxAppResize)(void* app_state, int width, int height); 22typedef void (*GfxAppRender)(GfxAppState*);
20typedef void (*GfxAppShutdown)(void* app_state); 23typedef void (*GfxAppResize)(GfxAppState*, int width, int height);
21 24
22/// Application callback functions. 25/// Application callback functions.
23typedef struct GfxAppCallbacks { 26typedef struct GfxAppCallbacks {
24 GfxAppInit init; 27 GfxAppInit init;
28 GfxAppShutdown shutdown;
25 GfxAppUpdate update; 29 GfxAppUpdate update;
26 GfxAppRender render; 30 GfxAppRender render;
27 GfxAppResize resize; 31 GfxAppResize resize;
28 GfxAppShutdown shutdown;
29} GfxAppCallbacks; 32} GfxAppCallbacks;
30 33
31typedef enum Key { 34typedef enum Key {
@@ -68,21 +71,25 @@ bool gfx_is_key_pressed(Key);
68 71
69/// Define a main function that initializes and puts the application in a loop. 72/// Define a main function that initializes and puts the application in a loop.
70/// See also: gfx_app_run(). 73/// See also: gfx_app_run().
71#define GFX_APP_MAIN(WIDTH, HEIGHT, MAX_FPS) \ 74#define GFX_APP_MAIN(WIDTH, HEIGHT, MAX_FPS, TITLE) \
72 int main(int argc, const char** argv) { \ 75 int main(int argc, const char** argv) { \
73 gfx_app_run( \ 76 GfxAppState app_state = {0}; \
74 &(GfxAppDesc){ \ 77 gfx_app_run( \
75 .argc = argc, \ 78 &(GfxAppDesc){ \
76 .argv = argv, \ 79 .argc = argc, \
77 .width = WIDTH, \ 80 .argv = argv, \
78 .height = HEIGHT, \ 81 .width = WIDTH, \
79 .max_fps = MAX_FPS, \ 82 .height = HEIGHT, \
80 .update_delta_time = MAX_FPS > 0 ? 1.0 / (double)MAX_FPS : 0.0}, \ 83 .max_fps = MAX_FPS, \
81 &(GfxAppCallbacks){ \ 84 .update_delta_time = MAX_FPS > 0 ? 1.0 / (double)MAX_FPS : 0.0, \
82 .init = (GfxAppInit)app_init, \ 85 .title = TITLE, \
83 .update = (GfxAppUpdate)app_update, \ 86 .app_state = &app_state, \
84 .render = (GfxAppRender)app_render, \ 87 }, \
85 .resize = (GfxAppResize)app_resize, \ 88 &(GfxAppCallbacks){ \
86 .shutdown = (GfxAppShutdown)app_end}); \ 89 .init = (GfxAppInit)app_init, \
87 return 0; \ 90 .update = (GfxAppUpdate)app_update, \
91 .render = (GfxAppRender)app_render, \
92 .resize = (GfxAppResize)app_resize, \
93 .shutdown = (GfxAppShutdown)app_end}); \
94 return 0; \
88 } 95 }
diff --git a/gfx-app/src/gfx_app.c b/gfx-app/src/gfx_app.c
index e0211b1..a93756c 100644
--- a/gfx-app/src/gfx_app.c
+++ b/gfx-app/src/gfx_app.c
@@ -9,7 +9,7 @@
9 9
10/// Application state. 10/// Application state.
11typedef struct GfxApp { 11typedef struct GfxApp {
12 void* app_state; 12 GfxAppState* app_state;
13 GfxAppCallbacks callbacks; 13 GfxAppCallbacks callbacks;
14 int max_fps; 14 int max_fps;
15 double update_delta_time; 15 double update_delta_time;
@@ -79,6 +79,7 @@ bool gfx_app_run(const GfxAppDesc* desc, const GfxAppCallbacks* callbacks) {
79 79
80 bool success = false; 80 bool success = false;
81 81
82 g_gfx_app.app_state = desc->app_state;
82 g_gfx_app.callbacks = *callbacks; 83 g_gfx_app.callbacks = *callbacks;
83 g_gfx_app.max_fps = desc->max_fps; 84 g_gfx_app.max_fps = desc->max_fps;
84 g_gfx_app.update_delta_time = desc->update_delta_time; 85 g_gfx_app.update_delta_time = desc->update_delta_time;
@@ -110,7 +111,8 @@ bool gfx_app_run(const GfxAppDesc* desc, const GfxAppCallbacks* callbacks) {
110 glfwMakeContextCurrent(g_gfx_app.window); 111 glfwMakeContextCurrent(g_gfx_app.window);
111 112
112 // Initialize the application's state before setting any callbacks. 113 // Initialize the application's state before setting any callbacks.
113 if (!(*g_gfx_app.callbacks.init)(desc, &g_gfx_app.app_state)) { 114 if (!(*g_gfx_app.callbacks.init)(
115 g_gfx_app.app_state, desc->argc, desc->argv)) {
114 LOGE("Failed to initialize application"); 116 LOGE("Failed to initialize application");
115 goto cleanup; 117 goto cleanup;
116 } 118 }
diff --git a/gfx-iso/CMakeLists.txt b/gfx-iso/CMakeLists.txt
index 993bbb3..673cb68 100644
--- a/gfx-iso/CMakeLists.txt
+++ b/gfx-iso/CMakeLists.txt
@@ -2,33 +2,42 @@ cmake_minimum_required(VERSION 3.0)
2 2
3project(isogfx) 3project(isogfx)
4 4
5set(CMAKE_C_STANDARD 11) 5set(CMAKE_C_STANDARD 17)
6set(CMAKE_C_STANDARD_REQUIRED On) 6set(CMAKE_C_STANDARD_REQUIRED On)
7set(CMAKE_C_EXTENSIONS Off) 7set(CMAKE_C_EXTENSIONS Off)
8 8
9# isogfx
10
9add_library(isogfx 11add_library(isogfx
10 src/isogfx.c) 12 src/isogfx.c)
11 13
12target_include_directories(isogfx PUBLIC 14target_include_directories(isogfx PUBLIC
13 include) 15 include)
14 16
15target_link_libraries(isogfx PRIVATE 17target_link_libraries(isogfx PUBLIC
16 filesystem 18 filesystem
17 mem 19 mem
18 mempool) 20 mempool)
19 21
20target_compile_options(isogfx PRIVATE -Wall -Wextra -Wpedantic) 22target_compile_options(isogfx PRIVATE -Wall -Wextra -Wpedantic)
21 23
22# Demo 24# App
23 25
24project(isogfx-app) 26add_library(isogfx-app
27 src/app.c)
25 28
26add_executable(isogfx-app 29target_include_directories(isogfx-app PUBLIC
27 app/checkerboard.c 30 include)
28 app/isogfx-demo.c
29 app/main.c)
30 31
31target_link_libraries(isogfx-app PRIVATE 32target_link_libraries(isogfx-app PUBLIC
32 gfx
33 gfx-app 33 gfx-app
34 isogfx) 34 isogfx)
35
36target_link_libraries(isogfx-app PRIVATE
37 gfx)
38
39target_compile_options(isogfx-app PRIVATE -Wall -Wextra -Wpedantic)
40
41# Demos
42
43add_subdirectory(demos)
diff --git a/gfx-iso/app/app.h b/gfx-iso/app/app.h
deleted file mode 100644
index 25e55eb..0000000
--- a/gfx-iso/app/app.h
+++ /dev/null
@@ -1,12 +0,0 @@
1#pragma once
2
3typedef struct IsoGfx IsoGfx;
4typedef struct IsoGfxApp IsoGfxApp;
5
6typedef struct IsoGfxApp {
7 int pixel_scale; // 0 or 1 for 1:1 scale.
8 void* state;
9 void (*shutdown)(IsoGfx*, void* state);
10 void (*update)(IsoGfx*, void* state, double t, double dt);
11 void (*render)(IsoGfx*, void* state);
12} IsoGfxApp;
diff --git a/gfx-iso/app/checkerboard.h b/gfx-iso/app/checkerboard.h
deleted file mode 100644
index 61725a5..0000000
--- a/gfx-iso/app/checkerboard.h
+++ /dev/null
@@ -1,9 +0,0 @@
1#pragma once
2
3#include "app.h"
4
5#include <stdbool.h>
6
7typedef struct IsoGfxApp IsoGfxApp;
8
9bool make_checkerboard_app(IsoGfx*, IsoGfxApp*);
diff --git a/gfx-iso/app/isogfx-demo.h b/gfx-iso/app/isogfx-demo.h
deleted file mode 100644
index d099824..0000000
--- a/gfx-iso/app/isogfx-demo.h
+++ /dev/null
@@ -1,9 +0,0 @@
1#pragma once
2
3#include "app.h"
4
5#include <stdbool.h>
6
7typedef struct IsoGfxApp IsoGfxApp;
8
9bool make_demo_app(IsoGfx*, IsoGfxApp*);
diff --git a/gfx-iso/demos/CMakeLists.txt b/gfx-iso/demos/CMakeLists.txt
new file mode 100644
index 0000000..c0a4101
--- /dev/null
+++ b/gfx-iso/demos/CMakeLists.txt
@@ -0,0 +1,2 @@
1add_subdirectory(checkerboard)
2add_subdirectory(isomap)
diff --git a/gfx-iso/demos/checkerboard/CMakeLists.txt b/gfx-iso/demos/checkerboard/CMakeLists.txt
new file mode 100644
index 0000000..f178262
--- /dev/null
+++ b/gfx-iso/demos/checkerboard/CMakeLists.txt
@@ -0,0 +1,15 @@
1cmake_minimum_required(VERSION 3.0)
2
3project(checkerboard)
4
5set(CMAKE_C_STANDARD 17)
6set(CMAKE_C_STANDARD_REQUIRED On)
7set(CMAKE_C_EXTENSIONS Off)
8
9add_executable(checkerboard
10 checkerboard.c)
11
12target_link_libraries(checkerboard PRIVATE
13 isogfx-app)
14
15target_compile_options(checkerboard PRIVATE -Wall -Wextra -Wpedantic)
diff --git a/gfx-iso/app/checkerboard.c b/gfx-iso/demos/checkerboard/checkerboard.c
index 8b394c4..9730aea 100644
--- a/gfx-iso/app/checkerboard.c
+++ b/gfx-iso/demos/checkerboard/checkerboard.c
@@ -1,12 +1,9 @@
1#include "isogfx-demo.h" 1#include <isogfx/app.h>
2
3#include <gfx/gfx_app.h>
4#include <isogfx/isogfx.h> 2#include <isogfx/isogfx.h>
5 3
6#include <assert.h> 4#include <assert.h>
7#include <stdbool.h> 5#include <stdbool.h>
8#include <stdio.h> 6#include <stdio.h>
9#include <stdlib.h>
10 7
11static const int TILE_WIDTH = 64; 8static const int TILE_WIDTH = 64;
12static const int TILE_HEIGHT = TILE_WIDTH / 2; 9static const int TILE_HEIGHT = TILE_WIDTH / 2;
@@ -34,11 +31,11 @@ typedef enum Colour {
34 Red, 31 Red,
35} Colour; 32} Colour;
36 33
37typedef struct State { 34typedef struct IsoGfxAppState {
38 Tile red; 35 Tile red;
39 int xpick; 36 int xpick;
40 int ypick; 37 int ypick;
41} State; 38} IsoGfxAppState;
42 39
43static void make_checkerboard(IsoGfx* iso, Tile black, Tile white) { 40static void make_checkerboard(IsoGfx* iso, Tile black, Tile white) {
44 assert(iso); 41 assert(iso);
@@ -52,17 +49,36 @@ static void make_checkerboard(IsoGfx* iso, Tile black, Tile white) {
52 } 49 }
53} 50}
54 51
55static void shutdown(IsoGfx* iso, void* app_state) { 52static bool init(
53 IsoGfxAppState* state, IsoGfx* iso, int argc, const char** argv) {
54 assert(state);
56 assert(iso); 55 assert(iso);
57 if (app_state) { 56
58 free(app_state); 57 if (!isogfx_make_world(
58 iso, &(WorldDesc){
59 .tile_width = TILE_WIDTH,
60 .tile_height = TILE_HEIGHT,
61 .world_width = WORLD_WIDTH,
62 .world_height = WORLD_HEIGHT})) {
63 return false;
59 } 64 }
65
66 const Tile black = isogfx_make_tile(iso, &tile_set[Black]);
67 const Tile white = isogfx_make_tile(iso, &tile_set[White]);
68 state->red = isogfx_make_tile(iso, &tile_set[Red]);
69 make_checkerboard(iso, black, white);
70
71 return true;
60} 72}
61 73
62static void update(IsoGfx* iso, void* app_state, double t, double dt) { 74static void shutdown(IsoGfxAppState* state, IsoGfx* iso) {
75 assert(state);
76 assert(iso);
77}
78
79static void update(IsoGfxAppState* state, IsoGfx* iso, double t, double dt) {
80 assert(state);
63 assert(iso); 81 assert(iso);
64 assert(app_state);
65 State* state = (State*)(app_state);
66 82
67 double mouse_x, mouse_y; 83 double mouse_x, mouse_y;
68 gfx_app_get_mouse_position(&mouse_x, &mouse_y); 84 gfx_app_get_mouse_position(&mouse_x, &mouse_y);
@@ -72,49 +88,27 @@ static void update(IsoGfx* iso, void* app_state, double t, double dt) {
72 printf("Picked tile: (%d, %d)\n", state->xpick, state->ypick); 88 printf("Picked tile: (%d, %d)\n", state->xpick, state->ypick);
73} 89}
74 90
75static void render(IsoGfx* iso, void* app_state) { 91static void render(IsoGfxAppState* state, IsoGfx* iso) {
92 assert(state);
76 assert(iso); 93 assert(iso);
77 assert(app_state);
78 State* state = (State*)(app_state);
79 94
80 isogfx_render(iso); 95 isogfx_render(iso);
96
81 if ((state->xpick != -1) && (state->ypick != -1)) { 97 if ((state->xpick != -1) && (state->ypick != -1)) {
82 isogfx_draw_tile(iso, state->xpick, state->ypick, state->red); 98 isogfx_draw_tile(iso, state->xpick, state->ypick, state->red);
83 } 99 }
84} 100}
85 101
86bool make_checkerboard_app(IsoGfx* iso, IsoGfxApp* app) { 102int main(int argc, const char** argv) {
87 assert(iso); 103 IsoGfxAppState state = {0};
88 assert(app); 104 iso_run(
89 105 argc, argv,
90 State* state = calloc(1, sizeof(State)); 106 &(IsoGfxApp){
91 if (!state) { 107 .state = &state,
92 return false; 108 .init = init,
93 } 109 .shutdown = shutdown,
94 110 .update = update,
95 if (!isogfx_make_world( 111 .render = render,
96 iso, &(WorldDesc){ 112 });
97 .tile_width = TILE_WIDTH, 113 return 0;
98 .tile_height = TILE_HEIGHT,
99 .world_width = WORLD_WIDTH,
100 .world_height = WORLD_HEIGHT})) {
101 goto cleanup;
102 }
103
104 const Tile black = isogfx_make_tile(iso, &tile_set[Black]);
105 const Tile white = isogfx_make_tile(iso, &tile_set[White]);
106 state->red = isogfx_make_tile(iso, &tile_set[Red]);
107 make_checkerboard(iso, black, white);
108 isogfx_render(iso);
109
110 app->state = state;
111 app->shutdown = shutdown;
112 app->update = update;
113 app->render = render;
114
115 return true;
116
117cleanup:
118 free(state);
119 return false;
120} 114}
diff --git a/gfx-iso/demos/isomap/CMakeLists.txt b/gfx-iso/demos/isomap/CMakeLists.txt
new file mode 100644
index 0000000..13edcc7
--- /dev/null
+++ b/gfx-iso/demos/isomap/CMakeLists.txt
@@ -0,0 +1,15 @@
1cmake_minimum_required(VERSION 3.0)
2
3project(isomap)
4
5set(CMAKE_C_STANDARD 17)
6set(CMAKE_C_STANDARD_REQUIRED On)
7set(CMAKE_C_EXTENSIONS Off)
8
9add_executable(isomap
10 isomap.c)
11
12target_link_libraries(isomap PRIVATE
13 isogfx-app)
14
15target_compile_options(isomap PRIVATE -Wall -Wextra -Wpedantic)
diff --git a/gfx-iso/app/isogfx-demo.c b/gfx-iso/demos/isomap/isomap.c
index 9889275..d204d28 100644
--- a/gfx-iso/app/isogfx-demo.c
+++ b/gfx-iso/demos/isomap/isomap.c
@@ -1,31 +1,45 @@
1#include "isogfx-demo.h" 1#include <isogfx/app.h>
2
3#include <gfx/gfx_app.h>
4#include <isogfx/isogfx.h> 2#include <isogfx/isogfx.h>
5 3
6#include <assert.h> 4#include <assert.h>
7#include <stdbool.h> 5#include <stdbool.h>
8#include <stdio.h>
9#include <stdlib.h>
10 6
11typedef struct State { 7typedef struct IsoGfxAppState {
12 int xpick; 8 int xpick;
13 int ypick; 9 int ypick;
14 SpriteSheet stag_sheet; 10 SpriteSheet stag_sheet;
15 Sprite stag; 11 Sprite stag;
16} State; 12} IsoGfxAppState;
17 13
18static void shutdown(IsoGfx* iso, void* app_state) { 14static bool init(
15 IsoGfxAppState* state, IsoGfx* iso, int argc, const char** argv) {
16 assert(state);
19 assert(iso); 17 assert(iso);
20 if (app_state) { 18
21 free(app_state); 19 if (!isogfx_load_world(iso, "/home/jeanne/assets/tilemaps/demo1.tm")) {
20 return false;
21 }
22
23 if (!isogfx_load_sprite_sheet(
24 iso, "/home/jeanne/assets/tilesets/scrabling/critters/stag/stag.ss",
25 &state->stag_sheet)) {
26 return false;
22 } 27 }
28
29 state->stag = isogfx_make_sprite(iso, state->stag_sheet);
30 isogfx_set_sprite_position(iso, state->stag, 5, 4);
31
32 return true;
23} 33}
24 34
25static void update(IsoGfx* iso, void* app_state, double t, double dt) { 35static void shutdown(IsoGfxAppState* state, IsoGfx* iso) {
36 assert(state);
37 assert(iso);
38}
39
40static void update(IsoGfxAppState* state, IsoGfx* iso, double t, double dt) {
41 assert(state);
26 assert(iso); 42 assert(iso);
27 assert(app_state);
28 State* state = (State*)(app_state);
29 43
30 double mouse_x, mouse_y; 44 double mouse_x, mouse_y;
31 gfx_app_get_mouse_position(&mouse_x, &mouse_y); 45 gfx_app_get_mouse_position(&mouse_x, &mouse_y);
@@ -35,45 +49,24 @@ static void update(IsoGfx* iso, void* app_state, double t, double dt) {
35 // printf("Picked tile: (%d, %d)\n", state->xpick, state->ypick); 49 // printf("Picked tile: (%d, %d)\n", state->xpick, state->ypick);
36} 50}
37 51
38static void render(IsoGfx* iso, void* app_state) { 52static void render(IsoGfxAppState* state, IsoGfx* iso) {
53 assert(state);
39 assert(iso); 54 assert(iso);
40 assert(app_state);
41 State* state = (State*)(app_state);
42 55
43 isogfx_render(iso); 56 isogfx_render(iso);
44} 57}
45 58
46bool make_demo_app(IsoGfx* iso, IsoGfxApp* app) { 59int main(int argc, const char** argv) {
47 assert(iso); 60 IsoGfxAppState state = {0};
48 assert(app); 61 iso_run(
49 62 argc, argv,
50 State* state = calloc(1, sizeof(State)); 63 &(IsoGfxApp){
51 if (!state) { 64 .pixel_scale = 2,
52 return false; 65 .state = &state,
53 } 66 .init = init,
54 67 .shutdown = shutdown,
55 if (!isogfx_load_world(iso, "/home/jeanne/assets/tilemaps/demo1.tm")) { 68 .update = update,
56 goto cleanup; 69 .render = render,
57 } 70 });
58 71 return 0;
59 if (!isogfx_load_sprite_sheet(
60 iso, "/home/jeanne/assets/tilesets/scrabling/critters/stag/stag.ss",
61 &state->stag_sheet)) {
62 goto cleanup;
63 }
64
65 state->stag = isogfx_make_sprite(iso, state->stag_sheet);
66 isogfx_set_sprite_position(iso, state->stag, 5, 4);
67
68 app->pixel_scale = 2;
69 app->state = state;
70 app->shutdown = shutdown;
71 app->update = update;
72 app->render = render;
73
74 return true;
75
76cleanup:
77 free(state);
78 return false;
79} 72}
diff --git a/gfx-iso/include/isogfx/app.h b/gfx-iso/include/isogfx/app.h
new file mode 100644
index 0000000..0a0fcc1
--- /dev/null
+++ b/gfx-iso/include/isogfx/app.h
@@ -0,0 +1,22 @@
1#pragma once
2
3#include <gfx/gfx_app.h>
4
5#include <stdbool.h>
6
7typedef struct IsoGfx IsoGfx;
8typedef struct IsoGfxApp IsoGfxApp;
9
10typedef struct IsoGfxAppState IsoGfxAppState;
11
12typedef struct IsoGfxApp {
13 int pixel_scale; // 0 or 1 for 1:1 scale.
14 IsoGfxAppState* state;
15
16 bool (*init)(IsoGfxAppState*, IsoGfx*, int argc, const char** argv);
17 void (*shutdown)(IsoGfxAppState*, IsoGfx*);
18 void (*update)(IsoGfxAppState*, IsoGfx*, double t, double dt);
19 void (*render)(IsoGfxAppState*, IsoGfx*);
20} IsoGfxApp;
21
22void iso_run(int argc, const char** argv, IsoGfxApp*);
diff --git a/gfx-iso/app/main.c b/gfx-iso/src/app.c
index 050a42f..079ac96 100644
--- a/gfx-iso/app/main.c
+++ b/gfx-iso/src/app.c
@@ -1,7 +1,4 @@
1#include "app.h" 1#include <isogfx/app.h>
2#include "checkerboard.h"
3#include "isogfx-demo.h"
4
5#include <isogfx/isogfx.h> 2#include <isogfx/isogfx.h>
6 3
7#include <gfx/gfx.h> 4#include <gfx/gfx.h>
@@ -18,37 +15,40 @@
18 15
19static const int SCREEN_WIDTH = 1408; 16static const int SCREEN_WIDTH = 1408;
20static const int SCREEN_HEIGHT = 960; 17static const int SCREEN_HEIGHT = 960;
18static const int MAX_FPS = 60;
21 19
22typedef struct State { 20typedef struct AppState {
23 Gfx* gfx; 21 Gfx* gfx;
24 IsoGfx* iso; 22 IsoGfx* iso;
25 IsoGfxApp app; 23 IsoGfxApp* app;
26 Texture* screen_texture; 24 Texture* screen_texture;
27 Scene* scene; 25 Scene* scene;
28} State; 26} AppState;
29 27
30static bool init(const GfxAppDesc* desc, void** app_state) { 28typedef struct GfxAppState {
31 State* state = calloc(1, sizeof(State)); 29 AppState state;
32 if (!state) { 30} GfxAppState;
33 return false; 31
34 } 32static bool init(GfxAppState* gfx_app_state, int argc, const char** argv) {
33 assert(gfx_app_state);
34 AppState* state = &gfx_app_state->state;
35
36 IsoGfxApp* app = state->app;
35 37
36 if (!(state->iso = isogfx_new(&(IsoGfxDesc){ 38 if (!(state->iso = isogfx_new(&(IsoGfxDesc){
37 .screen_width = SCREEN_WIDTH, .screen_height = SCREEN_HEIGHT}))) { 39 .screen_width = SCREEN_WIDTH, .screen_height = SCREEN_HEIGHT}))) {
38 goto cleanup; 40 goto cleanup;
39 } 41 }
40 // if (!make_checkerboard_app(state->iso, &state->app)) { 42
41 // goto cleanup; 43 if (!(*app->init)(app->state, state->iso, argc, argv)) {
42 // }
43 if (!make_demo_app(state->iso, &state->app)) {
44 goto cleanup; 44 goto cleanup;
45 } 45 }
46 46
47 // Apply pixel scaling if requested by the app. 47 // Apply pixel scaling if requested by the app.
48 int texture_width, texture_height; 48 int texture_width, texture_height;
49 if (state->app.pixel_scale > 1) { 49 if (app->pixel_scale > 1) {
50 texture_width = SCREEN_WIDTH / state->app.pixel_scale; 50 texture_width = SCREEN_WIDTH / app->pixel_scale;
51 texture_height = SCREEN_HEIGHT / state->app.pixel_scale; 51 texture_height = SCREEN_HEIGHT / app->pixel_scale;
52 isogfx_resize(state->iso, texture_width, texture_height); 52 isogfx_resize(state->iso, texture_width, texture_height);
53 } else { 53 } else {
54 texture_width = SCREEN_WIDTH; 54 texture_width = SCREEN_WIDTH;
@@ -110,7 +110,6 @@ static bool init(const GfxAppDesc* desc, void** app_state) {
110 SceneNode* root = gfx_get_scene_root(state->scene); 110 SceneNode* root = gfx_get_scene_root(state->scene);
111 gfx_set_node_parent(node, root); 111 gfx_set_node_parent(node, root);
112 112
113 *app_state = state;
114 return true; 113 return true;
115 114
116cleanup: 115cleanup:
@@ -121,35 +120,35 @@ cleanup:
121 return false; 120 return false;
122} 121}
123 122
124static void shutdown(void* app_state) { 123static void shutdown(GfxAppState* gfx_app_state) {
125 assert(app_state); 124 assert(gfx_app_state);
126 State* state = (State*)(app_state); 125 AppState* state = &gfx_app_state->state;
127 126
128 if (state->app.state) { 127 if (state->app) {
129 assert(state->iso); 128 assert(state->iso);
130 (*state->app.shutdown)(state->iso, state->app.state); 129 (*state->app->shutdown)(state->app->state, state->iso);
131 } 130 }
131
132 isogfx_del(&state->iso); 132 isogfx_del(&state->iso);
133 gfx_destroy(&state->gfx); 133 gfx_destroy(&state->gfx);
134 free(app_state);
135} 134}
136 135
137static void update(void* app_state, double t, double dt) { 136static void update(GfxAppState* gfx_app_state, double t, double dt) {
138 assert(app_state); 137 assert(gfx_app_state);
139 State* state = (State*)(app_state); 138 AppState* state = &gfx_app_state->state;
140 139
141 isogfx_update(state->iso, t); 140 isogfx_update(state->iso, t);
142 141
143 assert(state->app.update); 142 assert(state->app->update);
144 (*state->app.update)(state->iso, state->app.state, t, dt); 143 (*state->app->update)(state->app->state, state->iso, t, dt);
145} 144}
146 145
147static void render(void* app_state) { 146static void render(GfxAppState* gfx_app_state) {
148 assert(app_state); 147 assert(gfx_app_state);
149 State* state = (State*)(app_state); 148 AppState* state = &gfx_app_state->state;
150 149
151 assert(state->app.render); 150 assert(state->app->render);
152 (*state->app.render)(state->iso, state->app.state); 151 (*state->app->render)(state->app->state, state->iso);
153 152
154 const Pixel* screen = isogfx_get_screen_buffer(state->iso); 153 const Pixel* screen = isogfx_get_screen_buffer(state->iso);
155 assert(screen); 154 assert(screen);
@@ -166,34 +165,34 @@ static void render(void* app_state) {
166 gfx_end_frame(render_backend); 165 gfx_end_frame(render_backend);
167} 166}
168 167
169static void resize(void* app_state, int width, int height) { 168static void resize(GfxAppState* gfx_app_state, int width, int height) {
170 assert(app_state); 169 assert(gfx_app_state);
171 State* state = (State*)(app_state); 170 AppState* state = &gfx_app_state->state;
172 171
173 RenderBackend* render_backend = gfx_get_render_backend(state->gfx); 172 RenderBackend* render_backend = gfx_get_render_backend(state->gfx);
174 gfx_set_viewport(render_backend, width, height); 173 gfx_set_viewport(render_backend, width, height);
175} 174}
176 175
177int main(int argc, const char** argv) { 176void iso_run(int argc, const char** argv, IsoGfxApp* app) {
178 const int initial_width = SCREEN_WIDTH; 177 GfxAppState app_state = {
179 const int initial_height = SCREEN_HEIGHT; 178 .state = (AppState){
180 const int max_fps = 60; 179 .app = app,
181 180 }
181 };
182 gfx_app_run( 182 gfx_app_run(
183 &(GfxAppDesc){ 183 &(GfxAppDesc){
184 .argc = argc, 184 .argc = argc,
185 .argv = argv, 185 .argv = argv,
186 .width = initial_width, 186 .width = SCREEN_WIDTH,
187 .height = initial_height, 187 .height = SCREEN_HEIGHT,
188 .max_fps = max_fps, 188 .max_fps = MAX_FPS,
189 .update_delta_time = max_fps > 0 ? 1.0 / (double)max_fps : 0.0, 189 .update_delta_time = MAX_FPS > 0 ? 1.0 / (double)MAX_FPS : 0.0,
190 .title = "Isometric Renderer"}, 190 .title = "Isometric Renderer",
191 .app_state = &app_state},
191 &(GfxAppCallbacks){ 192 &(GfxAppCallbacks){
192 .init = init, 193 .init = init,
193 .update = update, 194 .update = update,
194 .render = render, 195 .render = render,
195 .resize = resize, 196 .resize = resize,
196 .shutdown = shutdown}); 197 .shutdown = shutdown});
197
198 return 0;
199} 198}
diff --git a/gfx-iso/asset/mkasset.py b/gfx-iso/tools/mkasset.py
index 3ca8a1d..3ca8a1d 100644
--- a/gfx-iso/asset/mkasset.py
+++ b/gfx-iso/tools/mkasset.py