summaryrefslogtreecommitdiff
path: root/gfx-iso/app
diff options
context:
space:
mode:
Diffstat (limited to 'gfx-iso/app')
-rw-r--r--gfx-iso/app/app.h11
-rw-r--r--gfx-iso/app/checkerboard.c120
-rw-r--r--gfx-iso/app/checkerboard.h9
-rw-r--r--gfx-iso/app/isogfx-demo.c67
-rw-r--r--gfx-iso/app/isogfx-demo.h9
-rw-r--r--gfx-iso/app/main.c185
6 files changed, 401 insertions, 0 deletions
diff --git a/gfx-iso/app/app.h b/gfx-iso/app/app.h
new file mode 100644
index 0000000..160da47
--- /dev/null
+++ b/gfx-iso/app/app.h
@@ -0,0 +1,11 @@
1#pragma once
2
3typedef struct IsoGfx IsoGfx;
4typedef struct IsoGfxApp IsoGfxApp;
5
6typedef struct IsoGfxApp {
7 void* state;
8 void (*shutdown)(IsoGfx*, void* state);
9 void (*update)(IsoGfx*, void* state, double t, double dt);
10 void (*render)(IsoGfx*, void* state);
11} IsoGfxApp;
diff --git a/gfx-iso/app/checkerboard.c b/gfx-iso/app/checkerboard.c
new file mode 100644
index 0000000..8b394c4
--- /dev/null
+++ b/gfx-iso/app/checkerboard.c
@@ -0,0 +1,120 @@
1#include "isogfx-demo.h"
2
3#include <gfx/gfx_app.h>
4#include <isogfx/isogfx.h>
5
6#include <assert.h>
7#include <stdbool.h>
8#include <stdio.h>
9#include <stdlib.h>
10
11static const int TILE_WIDTH = 64;
12static const int TILE_HEIGHT = TILE_WIDTH / 2;
13static const int WORLD_WIDTH = 20;
14static const int WORLD_HEIGHT = 20;
15
16static const TileDesc tile_set[] = {
17 {.type = TileFromColour,
18 .width = TILE_WIDTH,
19 .height = TILE_HEIGHT,
20 .colour = (Pixel){.r = 0x38, .g = 0x3b, .b = 0x46, .a = 0xff}},
21 {.type = TileFromColour,
22 .width = TILE_WIDTH,
23 .height = TILE_HEIGHT,
24 .colour = (Pixel){.r = 0xA5, .g = 0xb3, .b = 0xc0, .a = 0xff}},
25 {.type = TileFromColour,
26 .width = TILE_WIDTH,
27 .height = TILE_HEIGHT,
28 .colour = (Pixel){.r = 0xdc, .g = 0x76, .b = 0x84, .a = 0xff}},
29};
30
31typedef enum Colour {
32 Black,
33 White,
34 Red,
35} Colour;
36
37typedef struct State {
38 Tile red;
39 int xpick;
40 int ypick;
41} State;
42
43static void make_checkerboard(IsoGfx* iso, Tile black, Tile white) {
44 assert(iso);
45 for (int y = 0; y < isogfx_world_height(iso); ++y) {
46 for (int x = 0; x < isogfx_world_width(iso); ++x) {
47 const int odd_col = x & 1;
48 const int odd_row = y & 1;
49 const Tile value = (odd_row ^ odd_col) == 0 ? black : white;
50 isogfx_set_tile(iso, x, y, value);
51 }
52 }
53}
54
55static void shutdown(IsoGfx* iso, void* app_state) {
56 assert(iso);
57 if (app_state) {
58 free(app_state);
59 }
60}
61
62static void update(IsoGfx* iso, void* app_state, double t, double dt) {
63 assert(iso);
64 assert(app_state);
65 State* state = (State*)(app_state);
66
67 double mouse_x, mouse_y;
68 gfx_app_get_mouse_position(&mouse_x, &mouse_y);
69
70 isogfx_pick_tile(iso, mouse_x, mouse_y, &state->xpick, &state->ypick);
71
72 printf("Picked tile: (%d, %d)\n", state->xpick, state->ypick);
73}
74
75static void render(IsoGfx* iso, void* app_state) {
76 assert(iso);
77 assert(app_state);
78 State* state = (State*)(app_state);
79
80 isogfx_render(iso);
81 if ((state->xpick != -1) && (state->ypick != -1)) {
82 isogfx_draw_tile(iso, state->xpick, state->ypick, state->red);
83 }
84}
85
86bool make_checkerboard_app(IsoGfx* iso, IsoGfxApp* app) {
87 assert(iso);
88 assert(app);
89
90 State* state = calloc(1, sizeof(State));
91 if (!state) {
92 return false;
93 }
94
95 if (!isogfx_make_world(
96 iso, &(WorldDesc){
97 .tile_width = TILE_WIDTH,
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}
diff --git a/gfx-iso/app/checkerboard.h b/gfx-iso/app/checkerboard.h
new file mode 100644
index 0000000..61725a5
--- /dev/null
+++ b/gfx-iso/app/checkerboard.h
@@ -0,0 +1,9 @@
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.c b/gfx-iso/app/isogfx-demo.c
new file mode 100644
index 0000000..15ab6be
--- /dev/null
+++ b/gfx-iso/app/isogfx-demo.c
@@ -0,0 +1,67 @@
1#include "isogfx-demo.h"
2
3#include <gfx/gfx_app.h>
4#include <isogfx/isogfx.h>
5
6#include <assert.h>
7#include <stdbool.h>
8#include <stdio.h>
9#include <stdlib.h>
10
11typedef struct State {
12 int xpick;
13 int ypick;
14} State;
15
16static void shutdown(IsoGfx* iso, void* app_state) {
17 assert(iso);
18 if (app_state) {
19 free(app_state);
20 }
21}
22
23static void update(IsoGfx* iso, void* app_state, double t, double dt) {
24 assert(iso);
25 assert(app_state);
26 State* state = (State*)(app_state);
27
28 double mouse_x, mouse_y;
29 gfx_app_get_mouse_position(&mouse_x, &mouse_y);
30
31 isogfx_pick_tile(iso, mouse_x, mouse_y, &state->xpick, &state->ypick);
32
33 // printf("Picked tile: (%d, %d)\n", state->xpick, state->ypick);
34}
35
36static void render(IsoGfx* iso, void* app_state) {
37 assert(iso);
38 assert(app_state);
39 State* state = (State*)(app_state);
40
41 isogfx_render(iso);
42}
43
44bool make_demo_app(IsoGfx* iso, IsoGfxApp* app) {
45 assert(iso);
46 assert(app);
47
48 State* state = calloc(1, sizeof(State));
49 if (!state) {
50 return false;
51 }
52
53 if (!isogfx_load_world(iso, "/home/jeanne/assets/tilemaps/demo1.tm")) {
54 goto cleanup;
55 }
56
57 app->state = state;
58 app->shutdown = shutdown;
59 app->update = update;
60 app->render = render;
61
62 return true;
63
64cleanup:
65 free(state);
66 return false;
67}
diff --git a/gfx-iso/app/isogfx-demo.h b/gfx-iso/app/isogfx-demo.h
new file mode 100644
index 0000000..d099824
--- /dev/null
+++ b/gfx-iso/app/isogfx-demo.h
@@ -0,0 +1,9 @@
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/app/main.c b/gfx-iso/app/main.c
new file mode 100644
index 0000000..fa5a76b
--- /dev/null
+++ b/gfx-iso/app/main.c
@@ -0,0 +1,185 @@
1#include "app.h"
2#include "checkerboard.h"
3#include "isogfx-demo.h"
4
5#include <isogfx/isogfx.h>
6
7#include <gfx/gfx.h>
8#include <gfx/gfx_app.h>
9#include <gfx/render_backend.h>
10#include <gfx/renderer.h>
11#include <gfx/scene.h>
12#include <gfx/util/geometry.h>
13#include <gfx/util/shader.h>
14
15#include <assert.h>
16#include <stdbool.h>
17#include <stdlib.h>
18
19static const int SCREEN_WIDTH = 1408;
20static const int SCREEN_HEIGHT = 960;
21
22typedef struct State {
23 Gfx* gfx;
24 IsoGfx* iso;
25 IsoGfxApp app;
26 Texture* screen_texture;
27 Scene* scene;
28} State;
29
30static bool init(const GfxAppDesc* desc, void** app_state) {
31 State* state = calloc(1, sizeof(State));
32 if (!state) {
33 return false;
34 }
35
36 if (!(state->iso = isogfx_new(&(IsoGfxDesc){
37 .screen_width = SCREEN_WIDTH, .screen_height = SCREEN_HEIGHT}))) {
38 goto cleanup;
39 }
40 // if (!make_checkerboard_app(state->iso, &state->app)) {
41 // goto cleanup;
42 // }
43 if (!make_demo_app(state->iso, &state->app)) {
44 goto cleanup;
45 }
46 if (!(state->gfx = gfx_init())) {
47 goto cleanup;
48 }
49 RenderBackend* render_backend = gfx_get_render_backend(state->gfx);
50
51 if (!(state->screen_texture = gfx_make_texture(
52 render_backend, &(TextureDesc){
53 .width = SCREEN_WIDTH,
54 .height = SCREEN_HEIGHT,
55 .dimension = Texture2D,
56 .format = TextureSRGBA8,
57 .filtering = NearestFiltering,
58 .wrap = ClampToEdge,
59 .mipmaps = false}))) {
60 goto cleanup;
61 }
62
63 ShaderProgram* shader = gfx_make_view_texture_shader(render_backend);
64 if (!shader) {
65 goto cleanup;
66 }
67
68 Geometry* geometry = gfx_make_quad_11(render_backend);
69 if (!geometry) {
70 goto cleanup;
71 }
72
73 MaterialDesc material_desc = (MaterialDesc){.num_uniforms = 1};
74 material_desc.uniforms[0] = (ShaderUniform){
75 .type = UniformTexture,
76 .value.texture = state->screen_texture,
77 .name = sstring_make("Texture")};
78 Material* material = gfx_make_material(&material_desc);
79 if (!material) {
80 return false;
81 }
82
83 const MeshDesc mesh_desc =
84 (MeshDesc){.geometry = geometry, .material = material, .shader = shader};
85 Mesh* mesh = gfx_make_mesh(&mesh_desc);
86 if (!mesh) {
87 goto cleanup;
88 }
89
90 SceneObject* object = gfx_make_object();
91 if (!object) {
92 goto cleanup;
93 }
94 gfx_add_object_mesh(object, mesh);
95
96 state->scene = gfx_make_scene();
97 SceneNode* node = gfx_make_object_node(object);
98 SceneNode* root = gfx_get_scene_root(state->scene);
99 gfx_set_node_parent(node, root);
100
101 *app_state = state;
102 return true;
103
104cleanup:
105 if (state->gfx) {
106 gfx_destroy(&state->gfx);
107 }
108 free(state);
109 return false;
110}
111
112static void shutdown(void* app_state) {
113 assert(app_state);
114 State* state = (State*)(app_state);
115
116 if (state->app.state) {
117 assert(state->iso);
118 (*state->app.shutdown)(state->iso, state->app.state);
119 }
120 isogfx_del(&state->iso);
121 gfx_destroy(&state->gfx);
122 free(app_state);
123}
124
125static void update(void* app_state, double t, double dt) {
126 assert(app_state);
127 State* state = (State*)(app_state);
128
129 assert(state->app.update);
130 (*state->app.update)(state->iso, state->app.state, t, dt);
131}
132
133static void render(void* app_state) {
134 assert(app_state);
135 State* state = (State*)(app_state);
136
137 assert(state->app.render);
138 (*state->app.render)(state->iso, state->app.state);
139
140 const Pixel* screen = isogfx_get_screen_buffer(state->iso);
141 assert(screen);
142 gfx_update_texture(
143 state->screen_texture, &(TextureDataDesc){.pixels = screen});
144
145 RenderBackend* render_backend = gfx_get_render_backend(state->gfx);
146 Renderer* renderer = gfx_get_renderer(state->gfx);
147
148 gfx_start_frame(render_backend);
149 gfx_render_scene(
150 renderer, &(RenderSceneParams){
151 .mode = RenderDefault, .scene = state->scene, .camera = 0});
152 gfx_end_frame(render_backend);
153}
154
155static void resize(void* app_state, int width, int height) {
156 assert(app_state);
157 State* state = (State*)(app_state);
158
159 RenderBackend* render_backend = gfx_get_render_backend(state->gfx);
160 gfx_set_viewport(render_backend, width, height);
161}
162
163int main(int argc, const char** argv) {
164 const int initial_width = SCREEN_WIDTH;
165 const int initial_height = SCREEN_HEIGHT;
166 const int max_fps = 60;
167
168 gfx_app_run(
169 &(GfxAppDesc){
170 .argc = argc,
171 .argv = argv,
172 .width = initial_width,
173 .height = initial_height,
174 .max_fps = max_fps,
175 .update_delta_time = max_fps > 0 ? 1.0 / (double)max_fps : 0.0,
176 .title = "Isometric Renderer"},
177 &(GfxAppCallbacks){
178 .init = init,
179 .update = update,
180 .render = render,
181 .resize = resize,
182 .shutdown = shutdown});
183
184 return 0;
185}