A game engine for top-down 2D RPG games.
rpg game-engine raylib c99
at main 7.0 kB view raw
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 (void)is_new_state; 48 kf_window.state = state; 49 50 struct kf_world *world = NULL; 51 kf_timeit("load world", kf_world_load(&world, true, NULL)); 52 kf_window.room = world; 53 54 int idplayer = kf_actor_register("player"); 55 kf_actorregistry.serialize[idplayer] = kf_player_serialize; 56 kf_actorregistry.deserialize[idplayer] = kf_player_deserialize; 57 kf_actorregistry.sprite[idplayer] = kf_actor_loadspritesheet("data/res/img/char/template.png"); 58 kf_actorregistry.tick[idplayer] = kf_player_tick; 59 kf_actorregistry.draw[idplayer] = kf_player_draw; 60 61 int idplayer2 = kf_actor_register("player2"); 62 kf_actorregistry.serialize[idplayer2] = kf_player_serialize; 63 kf_actorregistry.deserialize[idplayer2] = kf_player_deserialize; 64 kf_actorregistry.sprite[idplayer2] = kf_actor_loadspritesheet("data/res/img/char/whom.png"); 65 kf_actorregistry.tick[idplayer2] = kf_player_tick; 66 kf_actorregistry.draw[idplayer2] = kf_player_draw; 67 68 if (!kf_exists("data/actors.bin")) 69 { 70 struct kf_actor *player = kf_actor_new("player"); 71 player->controlled = true; 72 player->pos.x = world->width * KF_TILE_SIZE_PX / 2.0f; 73 player->pos.y = world->width * KF_TILE_SIZE_PX / 2.0f; 74 75 struct kf_actor *player2 = kf_actor_new("player2"); 76 player2->pos.x = world->width * KF_TILE_SIZE_PX / 2.0f; 77 player2->pos.y = (world->width * KF_TILE_SIZE_PX / 2.0f) - 32; 78 79 kf_timeit("save actors", kf_saveactors()); 80 } 81 else 82 { 83 kf_timeit("load actors", kf_loadactors()); 84 } 85 86 kf_window.player = kf_actors; /* player should always be the first actor. */ 87 88 kf_window.cam.target.x = kf_window.player->pos.x + (kf_window.player->size.x / 2); 89 kf_window.cam.target.y = kf_window.player->pos.y + (kf_window.player->size.y / 2); 90 kf_window.cam.zoom = 2; 91 92 kf_setmodal(&kf_modal_play); 93} 94 95void kf_startwindow(void) 96{ 97 kf_window.running = 1; 98 kf_window.cam.offset.x = GetScreenWidth() / 2.0f; 99 kf_window.cam.offset.y = GetScreenHeight() / 2.0f; 100 101 while (!WindowShouldClose() && kf_window.running) 102 { 103 if (IsWindowResized()) 104 { 105 kf_window.cam.offset.x = GetScreenWidth() / 2.0f; 106 kf_window.cam.offset.y = GetScreenHeight() / 2.0f; 107 } 108 109 if (kf_window.modal && kf_window.modal->render_world) 110 kf_window.modal->update(); 111 if (kf_window.menu && kf_window.menu->render_world) 112 kf_window.menu->update(); 113 114 BeginDrawing(); 115 ClearBackground(BLACK); 116 { 117 BeginMode2D(kf_window.cam); 118 { 119 if (kf_window.modal && kf_window.modal->render_world) 120 kf_window.modal->render_world(); 121 if (kf_window.menu && kf_window.menu->render_world) 122 kf_window.menu->render_world(); 123 } 124 EndMode2D(); 125 126 if (kf_window.modal && kf_window.modal->render_ui) 127 kf_window.modal->render_ui(); 128 if (kf_window.menu && kf_window.menu->render_ui) 129 kf_window.menu->render_ui(); 130 } 131 EndDrawing(); 132 133 kf_frame++; 134 kf_dts = GetFrameTime(); 135 kf_dtms = kf_dts * 1000; 136 kf_s += kf_dts; 137 } 138 139 kf_setmenu(NULL); 140 kf_setmodal(NULL); 141 142 kf_saveactors(); 143 144 kf_state_save(kf_window.state); 145 146 free(kf_window.player); 147 free(kf_window.state); 148 free(kf_window.room); 149 150 CloseWindow(); 151} 152 153void kf_closewindow(void) 154{ 155 kf_window.running = false; 156} 157 158void kf_settargetfps(int fps) 159{ 160 SetTargetFPS(kf_window.target_fps = fps); 161} 162 163void kf_setmodal(struct kf_modal *modal) 164{ 165 if (kf_window.modal && kf_window.modal->exit) 166 { 167 kf_window.modal->exit(); 168 kf_window.modal->exit = NULL; 169 } 170 kf_window.modal = modal; 171 if (kf_window.modal && kf_window.modal->init) 172 kf_window.modal->init(); 173} 174 175void kf_setmenu(struct kf_modal *menu) 176{ 177 if (kf_window.menu && kf_window.menu->exit) 178 { 179 kf_window.menu->exit(); 180 kf_window.menu->exit = NULL; 181 } 182 kf_window.menu = menu; 183 if (kf_window.menu && kf_window.menu->init) 184 kf_window.menu->init(); 185} 186 187static 188void _kf_modal_play_update(void) 189{ 190 // kf_window.player->tick(kf_window.player); 191 for (struct kf_actor *actor = kf_actors ; actor != NULL ; actor = actor->next) 192 kf_actorregistry.tick[actor->id](actor); 193 194 Vector2 v = GetScreenToWorld2D(GetMousePosition(), kf_window.cam); 195 kf_window.select.x = v.x / KF_TILE_SIZE_PX; 196 kf_window.select.y = v.y / KF_TILE_SIZE_PX; 197 198 if (kf_checkinputpress(kf_inputbind_cancel) && kf_window.menu == NULL) 199 kf_window.running = 0; 200 else if (kf_checkinputpress(kf_inputbind_zoom_reset)) 201 kf_window.cam.zoom = 2; 202 else if (kf_checkinputpress(kf_inputbind_zoom_in) && kf_window.cam.zoom < 3.50f) 203 kf_window.cam.zoom += 0.25f; 204 else if (kf_checkinputpress(kf_inputbind_zoom_out) && kf_window.cam.zoom > 1.00f) 205 kf_window.cam.zoom -= 0.25f; 206 else if (kf_checkinputpress(kf_inputbind_toggle_fps_limit)) 207 kf_settargetfps(kf_window.target_fps != 60 ? 60 : 0); 208 else if (kf_checkinputpress(kf_inputbind_toggle_editor)) 209 { 210 if (kf_window.modal == &kf_modal_edit) 211 kf_setmodal(&kf_modal_play); 212 else 213 kf_setmodal(&kf_modal_edit); 214 } 215} 216 217static 218void _kf_modal_play_render_world(void) 219{ 220 kf_world_draw(kf_window.room, kf_window.cam); 221 // kf_world_drawcolliders(world, player, cam); 222 // kf_window.player->draw(kf_window.player); 223 for (struct kf_actor *actor = kf_actors ; actor != NULL ; actor = actor->next) 224 kf_actorregistry.draw[actor->id](actor); 225} 226 227static 228void _kf_modal_play_render_ui(void) 229{ 230 const int dy = kf_window.fontsize + 4; 231 int y = -dy + 4; /* start at -dy so that the FPS starts at 0,0. */ 232 y += 8; /* add a bit of padding */ 233 int x = 8; 234 235 const Color d = GRAY; /* default colour */ 236 Color c = d; 237 238 /* "curry" some arguments */ 239# define line(FMT, ...) \ 240 do \ 241 { \ 242 char *t = (char *)TextFormat(FMT __VA_OPT__(,) __VA_ARGS__); \ 243 kf_drawtextshadowed(c, x, y+=dy, kf_window.fontsize, t); \ 244 } \ 245 while (0) 246 247 line("--time--"); 248 c = GetFPS() >= kf_window.target_fps ? GREEN : RED; 249 line("fps: %d", GetFPS()); 250 line("dts: %f", kf_dts); 251 c = d; 252 line("sec: %f", kf_s); 253 254 line("--modals--"); 255 c = kf_window.modal ? ORANGE : d; 256 line("mode: %s", kf_window.modal ? kf_window.modal->name : "n/a"); 257 c = kf_window.menu ? ORANGE : d; 258 line("menu: %s", kf_window.menu ? kf_window.menu->name : "n/a"); 259 260# undef line 261} 262 263struct kf_modal kf_modal_play = { 264 .name = "play", 265 .update = _kf_modal_play_update, 266 .render_world = _kf_modal_play_render_world, 267 .render_ui = _kf_modal_play_render_ui, 268};