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