A game engine for top-down 2D RPG games.
rpg game-engine raylib c99

Refactor to massively clean up main.c

+3
include/keraforge.h
··· 7 7 #include <keraforge/log.h> 8 8 9 9 #include <keraforge/actor.h> 10 + #include <keraforge/editor.h> 10 11 #include <keraforge/error.h> 11 12 #include <keraforge/fs.h> 12 13 #include <keraforge/graphics.h> 13 14 #include <keraforge/input.h> 15 + #include <keraforge/inputbinds.h> 14 16 #include <keraforge/math.h> 17 + #include <keraforge/player.h> 15 18 #include <keraforge/sprites.h> 16 19 #include <keraforge/state.h> 17 20 #include <keraforge/ui.h>
+2 -2
include/keraforge/actor.h
··· 38 38 /* If the actor is running. This will not increase their speed, you are expected to yourself. */ 39 39 bool running; 40 40 /* Called every frame to update the actor. Don't forget about deltatime (kf_dts, kf_dtms)! */ 41 - void (*tick)(struct kf_world *world, struct kf_actor *self); 41 + void (*tick)(struct kf_actor *self); 42 42 /* Called every frame to render the actor. */ 43 - void (*draw)(struct kf_world *world, struct kf_actor *self); 43 + void (*draw)(struct kf_actor *self); 44 44 }; 45 45 46 46
+22
include/keraforge/editor.h
··· 1 + #ifndef __kf_editor__ 2 + #define __kf_editor__ 3 + 4 + 5 + #include <keraforge/_header.h> 6 + #include <keraforge/world.h> 7 + 8 + 9 + /* State for the world editor */ 10 + struct kf_editor 11 + { 12 + /* The tile that the player is "holding." */ 13 + kf_tileid_t selected_tile; 14 + /* If the world has been changed or not. */ 15 + bool dirty; 16 + }; 17 + 18 + extern struct kf_modal kf_modal_edit; 19 + extern struct kf_modal kf_menu_palette; 20 + 21 + 22 + #endif
+69
include/keraforge/graphics.h
··· 3 3 4 4 5 5 #include <keraforge/_header.h> 6 + #include <keraforge/math.h> 7 + #include <raylib.h> 6 8 7 9 10 + /* Represents either a model or a menu. */ 11 + struct kf_modal 12 + { 13 + char *name; 14 + void (*exit)(void); 15 + void (*init)(void); 16 + void (*update)(void); 17 + void (*render_world)(void); 18 + void (*render_ui)(void); 19 + void *data; 20 + }; 21 + 22 + /* Stores data about the window and graphics. None of this data is stored between saves/loads. */ 23 + struct kf_window 24 + { 25 + /* World camera. */ 26 + Camera2D cam; 27 + /* Target FPS. Do not mutate this yourself, use kf_settargetfps(). */ 28 + int target_fps; 29 + /* Indicates whether or not a window is open. */ 30 + bool running; 31 + 32 + /* Pointer to the current state. */ 33 + struct kf_state *state; 34 + /* Pointer to the current room. */ 35 + struct kf_world *room; 36 + /* Pointer to the current player. */ 37 + struct kf_actor *player; 38 + 39 + /* X,Y coords of the selected tile */ 40 + struct kf_vec2(u32) select; 41 + 42 + /* Current modal. Do not mutate this yourself, use kf_setmodal(). */ 43 + struct kf_modal *modal; 44 + /* Current menu. Do not mutate this yourself, use kf_setmenu(). */ 45 + struct kf_modal *menu; 46 + 47 + /* Font used for kf_drawtext functions. */ 48 + Font font; 49 + /* Base font size to use. */ 50 + int fontsize; 51 + }; 52 + 53 + /* Global window instance. */ 54 + extern struct kf_window kf_window; 8 55 /* Number of frames since the game opened. 9 56 Not consistent enough for precise timing! Use deltatime (kf_dts/kf_dtms) instead. */ 10 57 extern u64 kf_frame; ··· 14 61 extern f32 kf_dtms; 15 62 /* Deltatime in seconds. */ 16 63 extern f32 kf_dts; 64 + 65 + 66 + int kf_measuretext(int size, char *text); 67 + void kf_drawtext(Color c, int x, int y, int size, char *text); 68 + void kf_drawtextshadowed(Color c, int x, int y, int size, char *text); 69 + 70 + 71 + /* Open a window via Raylib. This should only be called once! */ 72 + void kf_openwindow(char *title); 73 + /* Start the render loop. */ 74 + void kf_startwindow(void); 75 + /* Close the window. */ 76 + void kf_closewindow(void); 77 + /* Set the target FPS. Prefer this over manually setting kf_window.target_fps. */ 78 + void kf_settargetfps(int fps); 79 + /* Set the current modal. */ 80 + void kf_setmodal(struct kf_modal *modal); 81 + /* Set the current menu. */ 82 + void kf_setmenu(struct kf_modal *menu); 83 + 84 + /* Default modal. */ 85 + extern struct kf_modal kf_modal_play; 17 86 18 87 19 88 #endif
+39
include/keraforge/inputbinds.h
··· 1 + #ifndef __kf_inputbinds__ 2 + #define __kf_inputbinds__ 3 + 4 + 5 + #include <keraforge/_header.h> 6 + #include <keraforge/input.h> 7 + 8 + 9 + /* Keraforge default keybinds. */ 10 + extern kf_inputbind_t 11 + kf_inputbind_move_up, 12 + kf_inputbind_move_down, 13 + kf_inputbind_move_left, 14 + kf_inputbind_move_right, 15 + kf_inputbind_run, 16 + 17 + kf_inputbind_ui_up, 18 + kf_inputbind_ui_down, 19 + kf_inputbind_ui_left, 20 + kf_inputbind_ui_right, 21 + kf_inputbind_select, 22 + kf_inputbind_cancel, 23 + 24 + kf_inputbind_pause, 25 + kf_inputbind_palette, 26 + 27 + kf_inputbind_zoom_reset, 28 + kf_inputbind_zoom_in, 29 + kf_inputbind_zoom_out, 30 + 31 + kf_inputbind_toggle_fps_limit, 32 + kf_inputbind_toggle_editor 33 + ; 34 + 35 + 36 + void kf_loaddefaultbinds(void); 37 + 38 + 39 + #endif
+13
include/keraforge/player.h
··· 1 + #ifndef __kf_player__ 2 + #define __kf_player__ 3 + 4 + 5 + #include <keraforge/_header.h> 6 + #include <keraforge/actor.h> 7 + 8 + 9 + void kf_player_tick(struct kf_actor *self); 10 + void kf_player_draw(struct kf_actor *self); 11 + 12 + 13 + #endif
+5 -2
include/keraforge/ui.h
··· 21 21 /* Padding for the panel. */ 22 22 int xpadding, ypadding; 23 23 }; 24 + /* Global UI config. */ 25 + extern struct kf_uiconfig kf_uiconfig; 24 26 25 - /* Get a pointer to the global UI config. */ 26 - struct kf_uiconfig *kf_ui_getconfig(void); 27 + /* Performs non-compile-time initialization for kf_uiconfig. 28 + This is called automatically by kf_openwindow. */ 29 + void kf_ui_init(void); 27 30 28 31 /* Draw a panel with the given title. Returns the Y position for the next line of text. 29 32 title: Title of the panel, drawn at the top of the panel. Must be null-terminated. */
+143
src/editor.c
··· 1 + #include "keraforge/editor.h" 2 + #include "keraforge/graphics.h" 3 + #include "keraforge/world.h" 4 + #include <keraforge.h> 5 + 6 + 7 + static 8 + void _kf_modal_edit_init(void) 9 + { 10 + struct kf_editor *editor = malloc(sizeof(struct kf_editor)); 11 + editor->selected_tile = 0; 12 + editor->dirty = false; 13 + kf_window.modal->data = editor; 14 + } 15 + 16 + static 17 + void _kf_modal_edit_exit(void) 18 + { 19 + bool d = ((struct kf_editor *)kf_window.modal->data)->dirty; 20 + 21 + kf_logdbg("exiting editor, world is %s", d ? "dirty" : "not dirty"); 22 + 23 + if (d) 24 + kf_world_save(kf_window.room, true); 25 + 26 + free(kf_window.modal->data); 27 + kf_window.modal->data = NULL; 28 + } 29 + 30 + static 31 + void _kf_modal_edit_update(void) 32 + { 33 + /* Inherit from kf_modal_play. */ 34 + kf_modal_play.update(); 35 + 36 + if (kf_checkinputpress(kf_inputbind_palette) && kf_window.modal == &kf_modal_edit) 37 + kf_setmenu(&kf_menu_palette); 38 + } 39 + 40 + static 41 + void _kf_modal_edit_render_world(void) 42 + { 43 + /* Inherit from kf_modal_play. */ 44 + kf_modal_play.render_world(); 45 + 46 + if (kf_window.menu) 47 + return; 48 + 49 + struct kf_vec2(u32) select = kf_window.select; 50 + 51 + if (select.x >= kf_window.room->width || select.y >= kf_window.room->height) 52 + return; 53 + 54 + struct kf_editor *data = (struct kf_editor *)kf_window.modal->data; 55 + struct kf_tile *t = kf_world_gettile(kf_window.room, select.x, select.y); 56 + if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) 57 + { 58 + t->id = data->selected_tile; 59 + data->dirty = true; 60 + kf_world_updatetile(kf_window.room, select.x, select.y, true); 61 + } 62 + else if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) 63 + { 64 + t->subid = data->selected_tile; 65 + data->dirty = true; 66 + } 67 + else if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE)) 68 + { 69 + data->selected_tile = t->id; 70 + } 71 + 72 + DrawRectangleLines(select.x * KF_TILE_SIZE_PX, select.y * KF_TILE_SIZE_PX, KF_TILE_SIZE_PX, KF_TILE_SIZE_PX, WHITE); 73 + char *text = (char *)TextFormat("%d [%d] (%d,%d)", t->id, t->data, select.x, select.y); 74 + int s = kf_window.fontsize / kf_window.cam.zoom; 75 + kf_drawtext( 76 + BLACK, 77 + select.x * KF_TILE_SIZE_PX, 78 + select.y * KF_TILE_SIZE_PX - s, 79 + s, 80 + text 81 + ); 82 + } 83 + 84 + static 85 + void _kf_modal_edit_render_ui() 86 + { 87 + /* Inherit from kf_modal_play. */ 88 + kf_modal_play.render_ui(); 89 + } 90 + 91 + struct kf_modal kf_modal_edit = { 92 + .name = "map editor", 93 + .init = _kf_modal_edit_init, 94 + .exit = _kf_modal_edit_exit, 95 + .update = _kf_modal_edit_update, 96 + .render_world = _kf_modal_edit_render_world, 97 + .render_ui = _kf_modal_edit_render_ui, 98 + .data = NULL, 99 + }; 100 + 101 + 102 + static 103 + void _kf_menu_palette_render_ui(void) 104 + { 105 + kf_tileid_t *selected = &((struct kf_editor *)kf_window.modal->data)->selected_tile; 106 + 107 + int px = 80, py = 80; 108 + DrawRectangle(px, py, 400, 400, BLACK); 109 + kf_drawtextshadowed(WHITE, px + 10, py + 10, kf_window.fontsize, "tiles :3"); 110 + py += 40; 111 + int x = 0, y = 0; 112 + int s = KF_TILE_SIZE_PX * 2; 113 + for (int i = 1 ; i <= kf_tiles.count ; i++) 114 + { 115 + Rectangle r = {px + x*s, py + y*s, s, s}; 116 + kf_drawsprite_wh(kf_tiles.sheet[i], r.x, r.y, r.width, r.height, kf_tiles.sprite[i].x + 0, kf_tiles.sprite[i].y + 3); 117 + 118 + if (*selected == i) 119 + DrawRectangleLinesEx(r, 1, GOLD); 120 + 121 + if (CheckCollisionPointRec(GetMousePosition(), r)) 122 + { 123 + DrawRectangleLinesEx(r, 1, WHITE); 124 + if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) 125 + *selected = i; 126 + } 127 + 128 + x += 1; 129 + if (x >= 8) 130 + { 131 + x = 0; 132 + y++; 133 + } 134 + } 135 + 136 + if (kf_checkinputpress(kf_inputbind_cancel)) 137 + kf_setmenu(NULL); 138 + }; 139 + 140 + struct kf_modal kf_menu_palette = { 141 + .name = "tile palette", 142 + .render_ui = _kf_menu_palette_render_ui, 143 + };
+233
src/graphics.c
··· 1 1 #include <keraforge.h> 2 + #include <raylib.h> 2 3 3 4 4 5 u64 kf_frame = 0; 5 6 f64 kf_s = 0; 6 7 f32 kf_dtms = 0; 7 8 f32 kf_dts = 0; 9 + struct kf_window kf_window = {0}; 10 + 11 + 12 + int kf_measuretext(int size, char *text) 13 + { 14 + return MeasureTextEx(kf_window.font, text, size, 2).x; 15 + } 16 + 17 + void 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 + 22 + void 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 + 29 + void 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 + 73 + void 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 + 129 + void kf_closewindow(void) 130 + { 131 + kf_window.running = false; 132 + } 133 + 134 + void kf_settargetfps(int fps) 135 + { 136 + SetTargetFPS(kf_window.target_fps = fps); 137 + } 138 + 139 + void 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 + 151 + void 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 + 163 + static 164 + void _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 + 191 + static 192 + void _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 + 199 + static 200 + void _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 + 235 + struct 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 + };
-1
src/input.c
··· 1 1 #include <keraforge.h> 2 2 #include <raylib.h> 3 - #include <stdio.h> 4 3 #include <string.h> 5 4 6 5
+55
src/inputbinds.c
··· 1 + #include <keraforge.h> 2 + 3 + 4 + kf_inputbind_t 5 + kf_inputbind_move_up, 6 + kf_inputbind_move_down, 7 + kf_inputbind_move_left, 8 + kf_inputbind_move_right, 9 + kf_inputbind_run, 10 + 11 + kf_inputbind_ui_up, 12 + kf_inputbind_ui_down, 13 + kf_inputbind_ui_left, 14 + kf_inputbind_ui_right, 15 + kf_inputbind_select, 16 + kf_inputbind_cancel, 17 + 18 + kf_inputbind_pause, 19 + kf_inputbind_palette, 20 + 21 + kf_inputbind_zoom_reset, 22 + kf_inputbind_zoom_in, 23 + kf_inputbind_zoom_out, 24 + 25 + kf_inputbind_toggle_fps_limit, 26 + kf_inputbind_toggle_editor 27 + ; 28 + 29 + 30 + void kf_loaddefaultbinds(void) 31 + { 32 + kf_inputbind_move_up = kf_addinput("move_up", KEY_W, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_Y); 33 + kf_inputbind_move_down = kf_addinput("move_down", KEY_S, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_Y); 34 + kf_inputbind_move_left = kf_addinput("move_left", KEY_A, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_X); 35 + kf_inputbind_move_right = kf_addinput("move_right", KEY_D, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_X); 36 + kf_inputbind_run = kf_addinput("run", KEY_LEFT_SHIFT, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT, GAMEPAD_AXIS_UNKNOWN); 37 + 38 + kf_inputbind_ui_up = kf_addinput("ui_up", KEY_W, KEY_UP, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_UP, GAMEPAD_AXIS_UNKNOWN); 39 + kf_inputbind_ui_down = kf_addinput("ui_down", KEY_S, KEY_DOWN, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_DOWN, GAMEPAD_AXIS_UNKNOWN); 40 + kf_inputbind_ui_left = kf_addinput("ui_left", KEY_A, KEY_LEFT, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_LEFT, GAMEPAD_AXIS_UNKNOWN); 41 + kf_inputbind_ui_right = kf_addinput("ui_right", KEY_D, KEY_RIGHT, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_RIGHT, GAMEPAD_AXIS_UNKNOWN); 42 + 43 + kf_inputbind_select = kf_addinput("select", KEY_E, KEY_ENTER, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_RIGHT_FACE_DOWN, GAMEPAD_AXIS_UNKNOWN); 44 + kf_inputbind_cancel = kf_addinput("cancel", KEY_Q, KEY_ESCAPE, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT, GAMEPAD_AXIS_UNKNOWN); 45 + 46 + kf_inputbind_pause = kf_addinput("pause", KEY_ESCAPE, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_MIDDLE_RIGHT, GAMEPAD_AXIS_UNKNOWN); 47 + kf_inputbind_palette = kf_addinput("palette", KEY_TAB, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_RIGHT_FACE_UP, GAMEPAD_AXIS_UNKNOWN); 48 + 49 + kf_inputbind_zoom_reset = kf_addinput("zoom_reset", KEY_ZERO, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 50 + kf_inputbind_zoom_in = kf_addinput("zoom_in", KEY_EQUAL, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 51 + kf_inputbind_zoom_out = kf_addinput("zoom_out", KEY_MINUS, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 52 + 53 + kf_inputbind_toggle_fps_limit = kf_addinput("toggle_fps_limit", KEY_NINE, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 54 + kf_inputbind_toggle_editor = kf_addinput("toggle_editor", KEY_EIGHT, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 55 + }
+4 -330
src/main.c
··· 1 - #include "keraforge/world.h" 2 1 #include <keraforge.h> 3 2 #include <raylib.h> 4 3 #include <raymath.h> 5 - #include <stdio.h> 6 - #include <stdlib.h> 7 - 8 - 9 - static Camera2D cam; 10 - static struct kf_vec2(u32) select = { 0, 0 }; 11 - static int selected_tile = 0; 12 - static enum { 13 - menu_none, 14 - menu_palette, 15 - } menu; 16 - static int target_fps = 60; 17 - static enum { 18 - modal_play, 19 - modal_edit, 20 - } modal; 21 - static char *modals[] = { "play", "edit" }; 22 - static bool dirty = false; 23 - 24 - static kf_inputbind_t 25 - inputbind_move_up, 26 - inputbind_move_down, 27 - inputbind_move_left, 28 - inputbind_move_right, 29 - inputbind_run, 30 - inputbind_ui_up, 31 - inputbind_ui_down, 32 - inputbind_ui_left, 33 - inputbind_ui_right, 34 - inputbind_select, 35 - inputbind_cancel, 36 - inputbind_pause, 37 - inputbind_palette, 38 - inputbind_zoom_reset, 39 - inputbind_zoom_in, 40 - inputbind_zoom_out, 41 - inputbind_toggle_fps_limit, 42 - inputbind_toggle_editor 43 - ; 44 4 45 5 46 6 static 47 - void loadbinds(void) 48 - { 49 - inputbind_move_up = kf_addinput("move_up", KEY_W, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_Y); 50 - inputbind_move_down = kf_addinput("move_down", KEY_S, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_Y); 51 - inputbind_move_left = kf_addinput("move_left", KEY_A, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_X); 52 - inputbind_move_right = kf_addinput("move_right", KEY_D, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_X); 53 - inputbind_run = kf_addinput("run", KEY_LEFT_SHIFT, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT, GAMEPAD_AXIS_UNKNOWN); 54 - 55 - inputbind_ui_up = kf_addinput("ui_up", KEY_W, KEY_UP, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_UP, GAMEPAD_AXIS_UNKNOWN); 56 - inputbind_ui_down = kf_addinput("ui_down", KEY_S, KEY_DOWN, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_DOWN, GAMEPAD_AXIS_UNKNOWN); 57 - inputbind_ui_left = kf_addinput("ui_left", KEY_A, KEY_LEFT, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_LEFT, GAMEPAD_AXIS_UNKNOWN); 58 - inputbind_ui_right = kf_addinput("ui_right", KEY_D, KEY_RIGHT, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_RIGHT, GAMEPAD_AXIS_UNKNOWN); 59 - 60 - inputbind_select = kf_addinput("select", KEY_E, KEY_ENTER, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_RIGHT_FACE_DOWN, GAMEPAD_AXIS_UNKNOWN); 61 - inputbind_cancel = kf_addinput("cancel", KEY_Q, KEY_ESCAPE, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT, GAMEPAD_AXIS_UNKNOWN); 62 - 63 - inputbind_pause = kf_addinput("pause", KEY_ESCAPE, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_MIDDLE_RIGHT, GAMEPAD_AXIS_UNKNOWN); 64 - inputbind_palette = kf_addinput("palette", KEY_TAB, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_RIGHT_FACE_UP, GAMEPAD_AXIS_UNKNOWN); 65 - 66 - inputbind_zoom_reset = kf_addinput("zoom_reset", KEY_ZERO, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 67 - inputbind_zoom_in = kf_addinput("zoom_in", KEY_EQUAL, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 68 - inputbind_zoom_out = kf_addinput("zoom_out", KEY_MINUS, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 69 - 70 - inputbind_toggle_fps_limit = kf_addinput("toggle_fps_limit", KEY_NINE, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 71 - inputbind_toggle_editor = kf_addinput("toggle_editor", KEY_EIGHT, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 72 - } 73 - 74 - static 75 7 void loadtiles(struct kf_spritesheet *terrain) 76 8 { 77 9 KF_ADDTILE( ··· 128 60 kf_logdbg("loaded %d tiles", kf_tiles.count); 129 61 } 130 62 131 - static 132 - void setmenu(int m) 133 - { 134 - menu = m; 135 - } 136 - 137 - static 138 - void _player_tick_move(struct kf_actor *self) 139 - { 140 - struct kf_vec2(f32) v = {0, 0}; 141 - 142 - /* gamepad axis movement */ 143 - f32 gpx = kf_getgamepadaxis(inputbind_move_left); 144 - f32 gpy = kf_getgamepadaxis(inputbind_move_up); 145 - if (gpx > kf_deadzone || gpx < -kf_deadzone || gpy > kf_deadzone || gpy < -kf_deadzone) 146 - { 147 - v.y = gpy; 148 - v.x = gpx; 149 - 150 - f32 angle = Vector2LineAngle(Vector2Zero(), (Vector2){gpx, gpy}) * RAD2DEG; 151 - angle /= 90; 152 - switch ((int)roundf(angle)) 153 - { 154 - case 0: self->pointing = kf_east; break; 155 - case 1: self->pointing = kf_north; break; 156 - case -2: /* fallthrough */ 157 - case 2: self->pointing = kf_west; break; 158 - case -1: self->pointing = kf_south; break; 159 - } 160 - 161 - goto done; 162 - } 163 - 164 - /* non-axis movement */ 165 - bool w = kf_checkinputdown(inputbind_move_up); 166 - bool s = kf_checkinputdown(inputbind_move_down); 167 - bool a = kf_checkinputdown(inputbind_move_left); 168 - bool d = kf_checkinputdown(inputbind_move_right); 169 - 170 - if (a && d) { v.x = 0; } 171 - else if (a) { v.x = -1; self->pointing = kf_west; } 172 - else if (d) { v.x = 1; self->pointing = kf_east; } 173 - 174 - if (w && s) { v.y = 0; } 175 - else if (w) { v.y = -1; self->pointing = kf_north; } 176 - else if (s) { v.y = 1; self->pointing = kf_south; } 177 - 178 - v = kf_normalize_vec2(f32)(v); 179 - 180 - done: 181 - if (v.x || v.y) 182 - kf_actor_addforce(self, v); 183 - } 184 - 185 - static 186 - void _player_tick(struct kf_world *world, struct kf_actor *self) 187 - { 188 - if (menu == menu_none) 189 - { 190 - _player_tick_move(self); 191 - 192 - if (kf_checkinputpress(inputbind_run)) 193 - { 194 - self->running = true; 195 - self->speedmod = 1.5; 196 - } 197 - else if (kf_checkinputrelease(inputbind_run)) 198 - { 199 - self->running = false; 200 - self->speedmod = 1; 201 - } 202 - } 203 - 204 - kf_actor_move(world, self, kf_dts); 205 - } 206 - 207 - static 208 - void _player_draw(struct kf_world *world, struct kf_actor *self) 209 - { 210 - (void)world; 211 - kf_actor_draw(self); 212 - 213 - cam.target.x = self->pos.x + (self->size.x / 2); 214 - cam.target.y = self->pos.y + (self->size.y / 2); 215 - } 216 - 217 - static 218 - void draw_palette(int *selected) 219 - { 220 - int px = 80, py = 80; 221 - DrawRectangle(px, py, 400, 400, BLACK); 222 - DrawText("tiles :3", px + 10, py + 10, 20, WHITE); 223 - py += 40; 224 - int x = 0, y = 0; 225 - int s = KF_TILE_SIZE_PX * 2; 226 - for (int i = 1 ; i <= kf_tiles.count ; i++) 227 - { 228 - Rectangle r = {px + x*s, py + y*s, s, s}; 229 - kf_drawsprite_wh(kf_tiles.sheet[i], r.x, r.y, r.width, r.height, kf_tiles.sprite[i].x + 0, kf_tiles.sprite[i].y + 3); 230 - 231 - if (*selected == i) 232 - DrawRectangleLinesEx(r, 1, GOLD); 233 - 234 - if (CheckCollisionPointRec(GetMousePosition(), r)) 235 - { 236 - DrawRectangleLinesEx(r, 1, WHITE); 237 - if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) 238 - *selected = i; 239 - } 240 - 241 - x += 1; 242 - if (x >= 8) 243 - { 244 - x = 0; 245 - y++; 246 - } 247 - } 248 - 249 - if (kf_checkinputpress(inputbind_cancel)) 250 - setmenu(menu_none); 251 - }; 252 - 253 63 254 64 int main(int argc, const char *argv[]) 255 65 { 256 66 (void)argc; 257 67 (void)argv; 258 68 259 - SetTraceLogLevel(LOG_WARNING); 260 - InitWindow(800, 600, "Keraforge"); 261 - SetTargetFPS(target_fps); 262 - SetExitKey(KEY_NULL); 69 + kf_openwindow("Keraforge"); 263 70 264 - loadbinds(); 71 + kf_window.font = LoadFont("data/res/font/MyDearestBit.ttf"); 72 + kf_window.fontsize = 16; 265 73 266 74 struct kf_spritesheet terrain = kf_loadspritesheet("data/res/img/tile/terrain.png", 16, 16); 267 75 loadtiles(&terrain); 268 76 269 - struct kf_uiconfig *uiconfig = kf_ui_getconfig(); 270 - uiconfig->select = inputbind_select; 271 - uiconfig->cancel = inputbind_cancel; 272 - uiconfig->up = inputbind_ui_up; 273 - uiconfig->down = inputbind_ui_down; 274 - 275 - if (!DirectoryExists("data")) 276 - MakeDirectory("data"); 277 - 278 - struct kf_state *state = NULL; 279 - int is_new_state = kf_state_load(&state); 280 - 281 - struct kf_world *world = NULL; 282 - kf_world_load(&world, true); 283 - if (!world) 284 - KF_THROW("failed to load world"); 285 - 286 - struct kf_actor *player = kf_actor_new(kf_actor_loadspritesheet("data/res/img/char/template.png"), 10, 10, true); 287 - player->sizeoffset.y = 6; 288 - player->tick = _player_tick; 289 - player->draw = _player_draw; 290 - player->controlled = true; 291 - if (is_new_state) 292 - { 293 - state->player.pos.x = world->width * KF_TILE_SIZE_PX / 2.0f; 294 - state->player.pos.y = world->width * KF_TILE_SIZE_PX / 2.0f; 295 - } 296 - player->pos.x = state->player.pos.x; 297 - player->pos.y = state->player.pos.y; 298 - kf_loginfo("pos: %f,%f", player->pos.x, player->pos.y); 299 - 300 - cam = (Camera2D){0}; 301 - cam.offset.x = GetScreenWidth() / 2.0f; 302 - cam.offset.y = GetScreenHeight() / 2.0f; 303 - cam.target.x = player->pos.x + (player->size.x / 2); 304 - cam.target.y = player->pos.y + (player->size.y / 2); 305 - cam.zoom = 2; 306 - 307 - int running = 1; 308 - while (!WindowShouldClose() && running) 309 - { 310 - if (IsWindowResized()) 311 - { 312 - cam.offset.x = GetScreenWidth() / 2.0f; 313 - cam.offset.y = GetScreenHeight() / 2.0f; 314 - } 315 - 316 - player->tick(world, player); 317 - 318 - Vector2 v = GetScreenToWorld2D(GetMousePosition(), cam); 319 - select.x = v.x / KF_TILE_SIZE_PX; 320 - select.y = v.y / KF_TILE_SIZE_PX; 321 - 322 - if (kf_checkinputpress(inputbind_palette) && modal == modal_edit) 323 - setmenu(menu_palette); 324 - else if (kf_checkinputpress(inputbind_cancel) && menu == menu_none) 325 - running = 0; 326 - else if (kf_checkinputpress(inputbind_zoom_reset)) 327 - cam.zoom = 2; 328 - else if (kf_checkinputpress(inputbind_zoom_in) && cam.zoom < 3.50f) 329 - cam.zoom += 0.25f; 330 - else if (kf_checkinputpress(inputbind_zoom_out) && cam.zoom > 1.00f) 331 - cam.zoom -= 0.25f; 332 - else if (kf_checkinputpress(inputbind_toggle_fps_limit)) 333 - { 334 - target_fps = target_fps <= 0 ? 60 : 0; 335 - SetTargetFPS(target_fps); 336 - } 337 - else if (kf_checkinputpress(inputbind_toggle_editor)) 338 - { 339 - if (modal == modal_edit) 340 - modal = modal_play; 341 - else 342 - { 343 - modal = modal_edit; 344 - dirty = true; 345 - } 346 - } 347 - 348 - BeginDrawing(); 349 - ClearBackground(BLACK); 350 - 351 - BeginMode2D(cam); 352 - kf_world_draw(world, cam); 353 - // kf_world_drawcolliders(world, player, cam); 354 - if (modal == modal_edit && menu == menu_none && select.x < world->width && select.y < world->height) 355 - { 356 - struct kf_tile *t = kf_world_gettile(world, select.x, select.y); 357 - if (IsMouseButtonDown(MOUSE_BUTTON_LEFT)) 358 - { 359 - t->id = (kf_tileid_t)selected_tile; 360 - kf_world_updatetile(world, select.x, select.y, true); 361 - } 362 - else if (IsMouseButtonDown(MOUSE_BUTTON_RIGHT)) 363 - t->subid = (kf_tileid_t)selected_tile; 364 - else if (IsMouseButtonPressed(MOUSE_BUTTON_MIDDLE)) 365 - selected_tile = t->id; 366 - 367 - DrawRectangleLines(select.x * KF_TILE_SIZE_PX, select.y * KF_TILE_SIZE_PX, KF_TILE_SIZE_PX, KF_TILE_SIZE_PX, WHITE); 368 - DrawText(TextFormat("%d [%d] (%d,%d)", t->id, t->data, select.x, select.y), select.x * KF_TILE_SIZE_PX, select.y * KF_TILE_SIZE_PX - 10, 10, BLACK); 369 - } 370 - player->draw(world, player); 371 - EndMode2D(); 372 - 373 - switch (menu) 374 - { 375 - case menu_none: 376 - break; 377 - case menu_palette: 378 - draw_palette(&selected_tile); 379 - break; 380 - } 381 - 382 - DrawFPS(0, 0); 383 - DrawText(TextFormat("%f", kf_dts), 0, 20, 20, RED); 384 - DrawText(TextFormat("%f", kf_s), 0, 40, 20, RED); 385 - DrawText(TextFormat("%s", modals[modal]), 0, 60, 20, ORANGE); 386 - 387 - EndDrawing(); 388 - 389 - kf_frame++; 390 - kf_dts = GetFrameTime(); 391 - kf_dtms = kf_dts * 1000; 392 - kf_s += kf_dts; 393 - } 394 - 395 - state->player.pos = player->pos; 396 - kf_state_save(state); 397 - free(state); 398 - 399 - if (dirty) 400 - kf_world_save(world, true); 401 - free(world); 402 - 403 - CloseWindow(); 77 + kf_startwindow(); 404 78 405 79 return 0; 406 80 }
+79
src/player.c
··· 1 + #include <keraforge.h> 2 + 3 + 4 + static 5 + void _player_tick_move(struct kf_actor *self) 6 + { 7 + struct kf_vec2(f32) v = {0, 0}; 8 + 9 + /* gamepad axis movement */ 10 + f32 gpx = kf_getgamepadaxis(kf_inputbind_move_left); 11 + f32 gpy = kf_getgamepadaxis(kf_inputbind_move_up); 12 + if (gpx > kf_deadzone || gpx < -kf_deadzone || gpy > kf_deadzone || gpy < -kf_deadzone) 13 + { 14 + v.y = gpy; 15 + v.x = gpx; 16 + 17 + f32 angle = Vector2LineAngle(Vector2Zero(), (Vector2){gpx, gpy}) * RAD2DEG; 18 + angle /= 90; 19 + switch ((int)roundf(angle)) 20 + { 21 + case 0: self->pointing = kf_east; break; 22 + case 1: self->pointing = kf_north; break; 23 + case -2: /* fallthrough */ 24 + case 2: self->pointing = kf_west; break; 25 + case -1: self->pointing = kf_south; break; 26 + } 27 + 28 + goto done; 29 + } 30 + 31 + /* non-axis movement */ 32 + bool w = kf_checkinputdown(kf_inputbind_move_up); 33 + bool s = kf_checkinputdown(kf_inputbind_move_down); 34 + bool a = kf_checkinputdown(kf_inputbind_move_left); 35 + bool d = kf_checkinputdown(kf_inputbind_move_right); 36 + 37 + if (a && d) { v.x = 0; } 38 + else if (a) { v.x = -1; self->pointing = kf_west; } 39 + else if (d) { v.x = 1; self->pointing = kf_east; } 40 + 41 + if (w && s) { v.y = 0; } 42 + else if (w) { v.y = -1; self->pointing = kf_north; } 43 + else if (s) { v.y = 1; self->pointing = kf_south; } 44 + 45 + v = kf_normalize_vec2(f32)(v); 46 + 47 + done: 48 + if (v.x || v.y) 49 + kf_actor_addforce(self, v); 50 + } 51 + 52 + void kf_player_tick(struct kf_actor *self) 53 + { 54 + if (!kf_window.menu) 55 + { 56 + _player_tick_move(self); 57 + 58 + if (kf_checkinputpress(kf_inputbind_run)) 59 + { 60 + self->running = true; 61 + self->speedmod = 1.5; 62 + } 63 + else if (kf_checkinputrelease(kf_inputbind_run)) 64 + { 65 + self->running = false; 66 + self->speedmod = 1; 67 + } 68 + } 69 + 70 + kf_actor_move(kf_window.room, self, kf_dts); 71 + } 72 + 73 + void kf_player_draw(struct kf_actor *self) 74 + { 75 + kf_actor_draw(self); 76 + 77 + kf_window.cam.target.x = self->pos.x + (self->size.x / 2); 78 + kf_window.cam.target.y = self->pos.y + (self->size.y / 2); 79 + }
+22 -18
src/ui.c
··· 1 + #include "keraforge/graphics.h" 1 2 #include <keraforge.h> 2 3 #include <raylib.h> 3 4 4 5 5 - static 6 - struct kf_uiconfig _kf_uiconfig = { 6 + struct kf_uiconfig kf_uiconfig = { 7 7 .select = KF_INPUTBIND_NONE, 8 8 .cancel = KF_INPUTBIND_NONE, 9 9 .up = KF_INPUTBIND_NONE, ··· 19 19 }; 20 20 21 21 22 - struct kf_uiconfig *kf_ui_getconfig(void) 22 + void kf_ui_init(void) 23 23 { 24 - return &_kf_uiconfig; 24 + kf_uiconfig.select = kf_inputbind_select; 25 + kf_uiconfig.cancel = kf_inputbind_cancel; 26 + kf_uiconfig.up = kf_inputbind_ui_up; 27 + kf_uiconfig.down = kf_inputbind_ui_down; 28 + kf_uiconfig.fontsize = kf_window.fontsize; 25 29 } 26 30 27 31 int kf_ui_panel(char *title) 28 32 { 29 - int y = GetScreenHeight() - _kf_uiconfig.panelheight; 30 - DrawRectangle(0, y, GetScreenWidth(), _kf_uiconfig.panelheight, _kf_uiconfig.bg); 33 + int y = GetScreenHeight() - kf_uiconfig.panelheight; 34 + DrawRectangle(0, y, GetScreenWidth(), kf_uiconfig.panelheight, kf_uiconfig.bg); 31 35 32 36 if (title) 33 37 { 34 - y += _kf_uiconfig.ypadding; 35 - DrawText(title, _kf_uiconfig.xpadding, y, _kf_uiconfig.fontsize, _kf_uiconfig.fg); 36 - y += _kf_uiconfig.fontsize; 38 + y += kf_uiconfig.ypadding; 39 + kf_drawtextshadowed(kf_uiconfig.fg, kf_uiconfig.xpadding, y, kf_uiconfig.fontsize, title); 40 + y += kf_uiconfig.fontsize; 37 41 } 38 42 39 43 return y; ··· 50 54 { 51 55 char *c = choices[i]; 52 56 53 - DrawText( 54 - TextFormat(i == *choice ? _kf_uiconfig.selectfmt : _kf_uiconfig.fmt, c), 55 - _kf_uiconfig.xpadding, 57 + kf_drawtextshadowed( 58 + kf_uiconfig.fg, 59 + kf_uiconfig.xpadding, 56 60 y, 57 - _kf_uiconfig.fontsize, 58 - _kf_uiconfig.fg 61 + kf_uiconfig.fontsize, 62 + (char *)TextFormat(i == *choice ? kf_uiconfig.selectfmt : kf_uiconfig.fmt, c) 59 63 ); 60 64 61 - y += _kf_uiconfig.fontsize; 65 + y += kf_uiconfig.fontsize; 62 66 if (y >= GetScreenHeight()) 63 67 break; 64 68 } 65 69 66 70 skip_text: 67 71 68 - if (kf_checkinputpress(_kf_uiconfig.select) || kf_checkinputpress(_kf_uiconfig.cancel)) 72 + if (kf_checkinputpress(kf_uiconfig.select) || kf_checkinputpress(kf_uiconfig.cancel)) 69 73 return 1; 70 - else if (kf_checkinputpress(_kf_uiconfig.down) && *choice < nchoices - 1) 74 + else if (kf_checkinputpress(kf_uiconfig.down) && *choice < nchoices - 1) 71 75 (*choice)++; 72 - else if (kf_checkinputpress(_kf_uiconfig.up) && *choice > 0) 76 + else if (kf_checkinputpress(kf_uiconfig.up) && *choice > 0) 73 77 (*choice)--; 74 78 75 79 return 0;