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};