A game engine for top-down 2D RPG games.
rpg
game-engine
raylib
c99
1#include <keraforge.h>
2#include <raylib.h>
3
4
5u64 kf_frame = 0;
6f64 kf_s = 0;
7f32 kf_dtms = 0;
8f32 kf_dts = 0;
9struct kf_window kf_window = {0};
10
11
12int kf_measuretext(int size, char *text)
13{
14 return MeasureTextEx(kf_window.font, text, size, 2).x;
15}
16
17void kf_drawtext(Color c, int x, int y, int size, char *text)
18{
19 DrawTextEx(kf_window.font, text, (Vector2){x, y}, size, 2, c);
20}
21
22void kf_drawtextshadowed(Color c, int x, int y, int size, char *text)
23{
24 kf_drawtext(BLACK, x+1, y+1, size, text);
25 kf_drawtext(c, x, y, size, text);
26}
27
28
29void kf_openwindow(char *title)
30{
31 kf_window.target_fps = 60;
32
33 SetTraceLogLevel(LOG_WARNING);
34 InitWindow(800, 600, title);
35 SetTargetFPS(kf_window.target_fps);
36 SetExitKey(KEY_NULL);
37
38 kf_window.font = GetFontDefault();
39 kf_window.fontsize = 20;
40
41 kf_loaddefaultbinds();
42 kf_ui_init();
43
44 struct kf_state *state = NULL;
45 int is_new_state = kf_state_load(&state);
46 kf_window.state = state;
47
48 struct kf_world *world = NULL;
49 kf_world_load(&world, true);
50 kf_window.room = world;
51
52 struct kf_actor *player = kf_actor_new(kf_actor_loadspritesheet("data/res/img/char/template.png"), 10, 10, true);
53 player->sizeoffset.y = 6;
54 player->tick = kf_player_tick;
55 player->draw = kf_player_draw;
56 player->controlled = true;
57 if (is_new_state) /* place the player in the centre of the room */
58 {
59 state->player.pos.x = world->width * KF_TILE_SIZE_PX / 2.0f;
60 state->player.pos.y = world->width * KF_TILE_SIZE_PX / 2.0f;
61 }
62 player->pos.x = state->player.pos.x;
63 player->pos.y = state->player.pos.y;
64 kf_window.player = player;
65
66 kf_window.cam.target.x = player->pos.x + (player->size.x / 2);
67 kf_window.cam.target.y = player->pos.y + (player->size.y / 2);
68 kf_window.cam.zoom = 2;
69
70 kf_setmodal(&kf_modal_play);
71}
72
73void kf_startwindow(void)
74{
75 kf_window.running = 1;
76 kf_window.cam.offset.x = GetScreenWidth() / 2.0f;
77 kf_window.cam.offset.y = GetScreenHeight() / 2.0f;
78 while (!WindowShouldClose() && kf_window.running)
79 {
80 if (IsWindowResized())
81 {
82 kf_window.cam.offset.x = GetScreenWidth() / 2.0f;
83 kf_window.cam.offset.y = GetScreenHeight() / 2.0f;
84 }
85
86 if (kf_window.modal && kf_window.modal->render_world)
87 kf_window.modal->update();
88 if (kf_window.menu && kf_window.menu->render_world)
89 kf_window.menu->update();
90
91 BeginDrawing();
92 ClearBackground(BLACK);
93 {
94 BeginMode2D(kf_window.cam);
95 {
96 if (kf_window.modal && kf_window.modal->render_world)
97 kf_window.modal->render_world();
98 if (kf_window.menu && kf_window.menu->render_world)
99 kf_window.menu->render_world();
100 }
101 EndMode2D();
102
103 if (kf_window.modal && kf_window.modal->render_ui)
104 kf_window.modal->render_ui();
105 if (kf_window.menu && kf_window.menu->render_ui)
106 kf_window.menu->render_ui();
107 }
108 EndDrawing();
109
110 kf_frame++;
111 kf_dts = GetFrameTime();
112 kf_dtms = kf_dts * 1000;
113 kf_s += kf_dts;
114 }
115
116 kf_setmenu(NULL);
117 kf_setmodal(NULL);
118
119 kf_window.state->player.pos = kf_window.player->pos;
120 kf_state_save(kf_window.state);
121
122 free(kf_window.player);
123 free(kf_window.state);
124 free(kf_window.room);
125
126 CloseWindow();
127}
128
129void kf_closewindow(void)
130{
131 kf_window.running = false;
132}
133
134void kf_settargetfps(int fps)
135{
136 SetTargetFPS(kf_window.target_fps = fps);
137}
138
139void kf_setmodal(struct kf_modal *modal)
140{
141 if (kf_window.modal && kf_window.modal->exit)
142 {
143 kf_window.modal->exit();
144 kf_window.modal->exit = NULL;
145 }
146 kf_window.modal = modal;
147 if (kf_window.modal && kf_window.modal->init)
148 kf_window.modal->init();
149}
150
151void kf_setmenu(struct kf_modal *menu)
152{
153 if (kf_window.menu && kf_window.menu->exit)
154 {
155 kf_window.menu->exit();
156 kf_window.menu->exit = NULL;
157 }
158 kf_window.menu = menu;
159 if (kf_window.menu && kf_window.menu->init)
160 kf_window.menu->init();
161}
162
163static
164void _kf_modal_play_update(void)
165{
166 kf_window.player->tick(kf_window.player);
167
168 Vector2 v = GetScreenToWorld2D(GetMousePosition(), kf_window.cam);
169 kf_window.select.x = v.x / KF_TILE_SIZE_PX;
170 kf_window.select.y = v.y / KF_TILE_SIZE_PX;
171
172 if (kf_checkinputpress(kf_inputbind_cancel) && kf_window.menu == NULL)
173 kf_window.running = 0;
174 else if (kf_checkinputpress(kf_inputbind_zoom_reset))
175 kf_window.cam.zoom = 2;
176 else if (kf_checkinputpress(kf_inputbind_zoom_in) && kf_window.cam.zoom < 3.50f)
177 kf_window.cam.zoom += 0.25f;
178 else if (kf_checkinputpress(kf_inputbind_zoom_out) && kf_window.cam.zoom > 1.00f)
179 kf_window.cam.zoom -= 0.25f;
180 else if (kf_checkinputpress(kf_inputbind_toggle_fps_limit))
181 kf_settargetfps(kf_window.target_fps != 60 ? 60 : 0);
182 else if (kf_checkinputpress(kf_inputbind_toggle_editor))
183 {
184 if (kf_window.modal == &kf_modal_edit)
185 kf_setmodal(&kf_modal_play);
186 else
187 kf_setmodal(&kf_modal_edit);
188 }
189}
190
191static
192void _kf_modal_play_render_world(void)
193{
194 kf_world_draw(kf_window.room, kf_window.cam);
195 // kf_world_drawcolliders(world, player, cam);
196 kf_window.player->draw(kf_window.player);
197}
198
199static
200void _kf_modal_play_render_ui(void)
201{
202 const int dy = kf_window.fontsize + 4;
203 int y = -dy + 4; /* start at -dy so that the FPS starts at 0,0. */
204 y += 8; /* add a bit of padding */
205 int x = 8;
206
207 const Color d = GRAY; /* default colour */
208 Color c = d;
209
210 /* "curry" some arguments */
211# define line(FMT, ...) \
212 do \
213 { \
214 char *t = (char *)TextFormat(FMT __VA_OPT__(,) __VA_ARGS__); \
215 kf_drawtextshadowed(c, x, y+=dy, kf_window.fontsize, t); \
216 } \
217 while (0)
218
219 line("--time--");
220 c = GetFPS() >= kf_window.target_fps ? GREEN : RED;
221 line("fps: %d", GetFPS());
222 line("dts: %f", kf_dts);
223 c = d;
224 line("sec: %f", kf_s);
225
226 line("--modals--");
227 c = kf_window.modal ? ORANGE : d;
228 line("mode: %s", kf_window.modal ? kf_window.modal->name : "n/a");
229 c = kf_window.menu ? ORANGE : d;
230 line("menu: %s", kf_window.menu ? kf_window.menu->name : "n/a");
231
232# undef line
233}
234
235struct kf_modal kf_modal_play = {
236 .name = "play",
237 .update = _kf_modal_play_update,
238 .render_world = _kf_modal_play_render_world,
239 .render_ui = _kf_modal_play_render_ui,
240};