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

Cleanup and add alt keybinds

+2
include/keraforge.h
··· 1 1 #ifndef __kf__ 2 2 #define __kf__ 3 3 4 + 4 5 #include <keraforge/_header.h> 5 6 #include <keraforge/actor.h> 6 7 #include <keraforge/fs.h> ··· 10 11 #include <keraforge/sprites.h> 11 12 #include <keraforge/ui.h> 12 13 #include <keraforge/world.h> 14 + 13 15 14 16 #endif
+3
include/keraforge/_header.h
··· 1 1 #ifndef __kf__header__ 2 2 #define __kf__header__ 3 3 4 + 4 5 #include <stdint.h> 5 6 #include <stddef.h> 6 7 #include <stdbool.h> 8 + 7 9 8 10 typedef int8_t i8; 9 11 typedef int16_t i16; ··· 17 19 18 20 typedef float f32; 19 21 typedef double f64; 22 + 20 23 21 24 #endif
+28 -3
include/keraforge/actor.h
··· 1 1 #ifndef __kf_actor__ 2 2 #define __kf_actor__ 3 3 4 + 4 5 #include <keraforge/_header.h> 5 6 #include <keraforge/math.h> 6 7 #include <keraforge/world.h> ··· 8 9 #include <keraforge/sprites.h> 9 10 #include <raylib.h> 10 11 12 + 13 + /* Represents any kinematic body in the world (players, NPCs, etc). */ 11 14 struct kf_actor 12 15 { 16 + /* Spritesheet for the actor. */ 13 17 struct kf_spritesheet sprites; 14 - struct kf_vec2(f32) pos, vel, size, sizeoffset; 15 - f32 speed, speedmod, friction; 16 - bool collide, controlled; 18 + /* The actor's position. */ 19 + struct kf_vec2(f32) pos; 20 + /* The actor's velocity. */ 21 + struct kf_vec2(f32) vel; 22 + /* The actor's size. Default origin is 0,0. */ 23 + struct kf_vec2(f32) size; 24 + /* An offset to apply to the actor's collision rect. */ 25 + struct kf_vec2(f32) sizeoffset; 26 + /* Actor's speed. */ 27 + f32 speed; 28 + /* Speed modifier for the actor. Gets multiplied by the actor's speed when moving. */ 29 + f32 speedmod; 30 + /* Friction to apply to the actor while moving. */ 31 + f32 friction; 32 + /* Indicates if collision processing should be applied to this actor. */ 33 + bool collide; 34 + /* When true, the actor's `pointing` field is expected to be updated manually. */ 35 + bool controlled; 36 + /* The direction that the actor is pointing. */ 17 37 enum kf_direction pointing; 38 + /* Called every frame to update the actor. Don't forget about deltatime (kf_dts, kf_dtms)! */ 18 39 void (*tick)(struct kf_world *world, struct kf_actor *self); 40 + /* Called every frame to render the actor. */ 19 41 void (*draw)(struct kf_world *world, struct kf_actor *self); 20 42 }; 21 43 44 + 45 + /* Create a new actor. */ 22 46 struct kf_actor *kf_actor_new(struct kf_spritesheet sprites, f32 width, f32 height, bool collides); 23 47 24 48 /* Load a spritesheet, filling in the details for loading character spritesheets. */ ··· 32 56 void kf_actor_move(struct kf_world *world, struct kf_actor *actor, f32 deltatime); 33 57 /* Draw the actor. */ 34 58 void kf_actor_draw(struct kf_actor *actor); 59 + 35 60 36 61 #endif
+3
include/keraforge/fs.h
··· 1 1 #ifndef __kf_fs__ 2 2 #define __kf_fs__ 3 3 4 + 4 5 #include <keraforge/_header.h> 6 + 5 7 6 8 /* Check if a file exists. */ 7 9 int kf_exists(char *filename); ··· 10 12 u8 *kf_readbin(char *filename, size_t *plen); 11 13 /* Write binary file contents. */ 12 14 int kf_writebin(char *filename, u8 *data, size_t len); 15 + 13 16 14 17 #endif
+3
include/keraforge/graphics.h
··· 1 1 #ifndef __kf_graphics__ 2 2 #define __kf_graphics__ 3 3 4 + 4 5 #include <keraforge/_header.h> 6 + 5 7 6 8 /* Number of frames since the game opened. 7 9 You should only use this for animations! ··· 11 13 extern f32 kf_dtms; 12 14 /* Deltatime in seconds. */ 13 15 extern f32 kf_dts; 16 + 14 17 15 18 #endif
+26 -2
include/keraforge/input.h
··· 1 1 #ifndef __kf_input__ 2 2 #define __kf_input__ 3 3 4 + 4 5 #include <keraforge/_header.h> 5 6 #include <raylib.h> 7 + 6 8 7 9 #define MOUSE_BUTTON_UNKNOWN ((MouseButton)-1) 8 10 #define GAMEPAD_AXIS_UNKNOWN ((GamepadAxis)-1) ··· 11 13 typedef u8 kf_inputbind_t; 12 14 #define KF_INPUTBIND_NONE ((kf_inputbind_t)0) 13 15 16 + 17 + /* Struct-of-Arrays for keybindings. */ 14 18 struct _kf_inputbinds 15 19 { 16 20 kf_inputbind_t count; /* must start at 1. 0 is the `none` keybind. */ 17 21 char *id[KF_INPUTBIND_MAX]; 18 22 KeyboardKey key[KF_INPUTBIND_MAX]; 23 + KeyboardKey alt[KF_INPUTBIND_MAX]; 19 24 MouseButton mouse[KF_INPUTBIND_MAX]; 20 25 GamepadButton gamepad[KF_INPUTBIND_MAX]; 21 26 GamepadAxis axis[KF_INPUTBIND_MAX]; 22 27 }; 23 28 29 + 24 30 /* Deadzone for gamepads. Default is 0.2f. */ 25 31 extern f32 kf_deadzone; 26 - 32 + /* Input binding struct-of-arrays. You should not mutate this directly (use kf_addinput). */ 27 33 extern struct _kf_inputbinds kf_inputbinds; 34 + 28 35 29 36 /* Add a new input binding. */ 30 - kf_inputbind_t kf_addinput(char *id, KeyboardKey key, MouseButton mouse, GamepadButton gamepad, GamepadAxis axis); 37 + kf_inputbind_t kf_addinput(char *id, KeyboardKey key, KeyboardKey alt, MouseButton mouse, GamepadButton gamepad, GamepadAxis axis); 31 38 /* Get an input's index by it's translation key. */ 32 39 kf_inputbind_t kf_getinput(char *id); 33 40 41 + /* Check if the given key was pressed this frame. */ 34 42 int kf_checkkeypress(kf_inputbind_t id); 43 + /* Check if the given key was released this frame. */ 35 44 int kf_checkkeyrelease(kf_inputbind_t id); 45 + /* Check if the given key is down. */ 36 46 int kf_checkkeydown(kf_inputbind_t id); 47 + /* Check if the given key is up. */ 37 48 int kf_checkkeyup(kf_inputbind_t id); 49 + /* Check if the given mouse button was pressed this frame. */ 38 50 int kf_checkmousepress(kf_inputbind_t id); 51 + /* Check if the given mouse button was released this frame. */ 39 52 int kf_checkmouserelease(kf_inputbind_t id); 53 + /* Check if the given mouse button is down. */ 40 54 int kf_checkmousedown(kf_inputbind_t id); 55 + /* Check if the given mouse button is up. */ 41 56 int kf_checkmouseup(kf_inputbind_t id); 57 + /* Check if the given gamepad button was pressed this frame. */ 42 58 int kf_checkgamepadpress(kf_inputbind_t id); 59 + /* Check if the given gamepad button was released this frame. */ 43 60 int kf_checkgamepadrelease(kf_inputbind_t id); 61 + /* Check if the given gamepad button is down. */ 44 62 int kf_checkgamepaddown(kf_inputbind_t id); 63 + /* Check if the given gamepad button is up. */ 45 64 int kf_checkgamepadup(kf_inputbind_t id); 65 + /* Get the given gamepad axis' value (-1 to +1). */ 46 66 float kf_getgamepadaxis(kf_inputbind_t id); 47 67 68 + /* Check if the given input binding was pressed this frame. */ 48 69 int kf_checkinputpress(kf_inputbind_t id); 70 + /* Check if the given input binding was released this frame. */ 49 71 int kf_checkinputrelease(kf_inputbind_t id); 72 + /* Check if the given input binding is down. */ 50 73 int kf_checkinputdown(kf_inputbind_t id); 74 + /* Check if the given input binding is up. */ 51 75 int kf_checkinputup(kf_inputbind_t id); 52 76 53 77
+9
include/keraforge/math.h
··· 1 1 #ifndef __kf_math__ 2 2 #define __kf_math__ 3 3 4 + 4 5 #include <keraforge/_header.h> 5 6 #include <raylib.h> 6 7 #include <raymath.h> 8 + 7 9 8 10 #define _kf_mathdef(x) \ 9 11 x(i8); \ ··· 51 53 _kf_mathdef(x) 52 54 #undef x 53 55 56 + 57 + /* Represents a NESW direction. */ 54 58 enum kf_direction 55 59 { 56 60 kf_north, ··· 59 63 kf_west, 60 64 }; 61 65 66 + 67 + /* Rotate a direction clockwise. */ 62 68 enum kf_direction kf_rotatecw(enum kf_direction dir); 69 + /* Rotate a direction counterclockwise. */ 63 70 enum kf_direction kf_rotateccw(enum kf_direction dir); 71 + /* Get a vec2(f32) representing the direction. */ 64 72 struct kf_vec2(f32) kf_dtov2(enum kf_direction dir); 73 + 65 74 66 75 #endif
+7
include/keraforge/sprites.h
··· 1 1 #ifndef __kf_sprites__ 2 2 #define __kf_sprites__ 3 3 4 + 4 5 #include <keraforge/_header.h> 5 6 #include <raylib.h> 6 7 8 + 9 + /* Represents a single texture containing multiple sprites. 10 + Can be used for animations or texture atlases. */ 7 11 struct kf_spritesheet 8 12 { 9 13 Texture2D texture; ··· 11 15 u32 nsprites; 12 16 }; 13 17 18 + 19 + /* Load a sprite sheet with the given sprite width/height. */ 14 20 struct kf_spritesheet kf_loadspritesheet(char *filename, int spritewidth, int spriteheight); 21 + /* Draw a single sprite from the sheet at the given coordinates. */ 15 22 void kf_drawsprite(struct kf_spritesheet *sheet, f32 x, f32 y, int spritex, int spritey); 16 23 17 24 #endif
+28 -1
include/keraforge/ui.h
··· 1 1 #ifndef __kf_ui__ 2 2 #define __kf_ui__ 3 3 4 + 4 5 #include <keraforge/input.h> 5 6 7 + 8 + /* Holds global config settings for UIs. */ 6 9 struct kf_uiconfig 7 10 { 11 + /* Keybindings to navigate UIs. */ 8 12 kf_inputbind_t select, cancel, up, down; 9 - char *fmt, *selectfmt; 13 + /* Format string for choices. */ 14 + char *fmt; 15 + /* Format string for selected choices. */ 16 + char *selectfmt; 10 17 int fontsize; 11 18 Color bg, fg; 19 + /* Height of the UI panel. */ 12 20 int panelheight; 21 + /* Padding for the panel. */ 13 22 int xpadding, ypadding; 14 23 }; 15 24 25 + /* Get a pointer to the global UI config. */ 16 26 struct kf_uiconfig *kf_ui_getconfig(void); 17 27 28 + /* Draw a panel with the given title. Returns the Y position for the next line of text. 29 + title: Title of the panel, drawn at the top of the panel. Must be null-terminated. */ 18 30 int kf_ui_panel(char *title); 19 31 32 + /* Present the player with a choice menu. 33 + title: Panel title. Must be null-terminated. 34 + choices: Array of possible choices. Must be null-terminated. 35 + nchoices: Length of the array. 36 + choice: Pointer to the selected choice. This will be mutated. 37 + Returns: 1 if the user has made a choice, otherwise 0. */ 20 38 int kf_ui_choice(char *title, char **choices, int nchoices, int *choice); 39 + /* Present the player with a yes/no menu. 40 + title: Panel title. Must be null-terminated. 41 + choice: Pointer to the selected choice. This will be mutated. 1 is yes, 0 is no. 42 + Returns: 1 if the user has made a choice, otherwise 0. */ 21 43 int kf_ui_yesno(char *title, int *choice); 44 + /* Present the player with a text input menu. 45 + title: Panel title. Must be null-terminated. 46 + text: The inputted text. If NULL, it will be malloc'd automatically. 47 + If it needs to be grown, it will be realloc'd. 48 + Returns: 1 if the user has made a choice, otherwise 0. */ 22 49 int kf_ui_textinput(char *title, char *text); 23 50 24 51 #endif
+23 -3
include/keraforge/world.h
··· 1 1 #ifndef __kf_world__ 2 2 #define __kf_world__ 3 3 4 + 4 5 #include <keraforge/_header.h> 6 + #include <keraforge/math.h> 5 7 #include <raylib.h> 6 8 9 + 7 10 #define KF_TILEID_MAX UINT16_MAX 8 11 typedef u16 kf_tileid_t; 9 12 #define KF_TILE_SIZE_PX 16 10 13 14 + 15 + struct kf_actor; /* Forward declaration */ 16 + 17 + 18 + /* Represents a world (or a subworld, often called "rooms"). */ 11 19 struct kf_world 12 20 { 13 - /* Never ever reorder `revision` to be after anything. 21 + /* Marks the version of this map, used for migrating from one engine version to another. 22 + Never ever reorder `revision` to be after anything. 14 23 If you add something before it or move it then the 15 24 version checker will compare the first u32 in the 16 25 map's binary to the expected revision, which will 17 26 almost always be wrong. */ 18 27 u32 revision; 28 + /* Width of the map. */ 19 29 u32 width; 30 + /* Height of the map. */ 20 31 u32 height; 32 + /* Array of tiles in the map. Use kf_gettile to get a tile using an X/Y position. */ 21 33 kf_tileid_t map[]; 22 34 }; 23 35 36 + /* Struct-of-arrays for tiles. See: kf_tiles */ 24 37 struct _kf_tiles 25 38 { 26 39 kf_tileid_t count; 40 + /* Translation key of the tile. */ 27 41 char *key[KF_TILEID_MAX]; 28 - Color color[KF_TILEID_MAX]; 42 + /* The tile's colour on a world map. */ 43 + Color mapcol[KF_TILEID_MAX]; 44 + /* The spritesheet this tile's sprite belongs to. */ 45 + struct kf_spritesheet *sheet[KF_TILEID_MAX]; 46 + /* Spritesheet coords. */ 47 + struct kf_vec2(u32) sprite[KF_TILEID_MAX]; 48 + /* Whether or not this tile has collision. */ 29 49 bool collide[KF_TILEID_MAX]; 30 50 }; 51 + /* Struct-of-arrays for tiles. */ 31 52 extern struct _kf_tiles kf_tiles; 32 53 33 54 /* Create a world using the given width and height. ··· 41 62 kf_tileid_t *kf_world_gettile(struct kf_world *world, u32 x, u32 y); 42 63 43 64 /* Draw visible collision rectangles. */ 44 - struct kf_actor; 45 65 void kf_world_drawcolliders(struct kf_world *world, struct kf_actor *player, Camera2D camera); 46 66 47 67 /* Draw the part of the world visible to the given camera. */
+1
src/actor.c
··· 2 2 #include <stdlib.h> 3 3 #include <raymath.h> 4 4 5 + 5 6 struct kf_actor *kf_actor_new(struct kf_spritesheet sprites, f32 width, f32 height, bool collides) 6 7 { 7 8 struct kf_actor *actor = calloc(1, sizeof(struct kf_actor));
+1
src/fs.c
··· 2 2 #include <stdio.h> 3 3 #include <stdlib.h> 4 4 5 + 5 6 int kf_exists(char *filename) 6 7 { 7 8 FILE *fp = fopen(filename, "r");
+1
src/graphics.c
··· 1 1 #include <keraforge.h> 2 2 3 + 3 4 u64 kf_frame = 0; 4 5 f32 kf_dtms = 0; 5 6 f32 kf_dts = 0;
+79 -15
src/input.c
··· 3 3 #include <stdio.h> 4 4 #include <string.h> 5 5 6 + 6 7 f32 kf_deadzone = 0.2f; 7 8 8 9 struct _kf_inputbinds kf_inputbinds = { 9 10 .count = 1, 10 11 }; 11 12 12 - kf_inputbind_t kf_addinput(char *id, KeyboardKey key, MouseButton mouse, GamepadButton gamepad, GamepadAxis axis) 13 + 14 + kf_inputbind_t kf_addinput(char *id, KeyboardKey key, KeyboardKey alt, MouseButton mouse, GamepadButton gamepad, GamepadAxis axis) 13 15 { 14 16 kf_inputbind_t i = kf_inputbinds.count; 15 17 if (i >= KF_INPUTBIND_MAX) ··· 19 21 } 20 22 kf_inputbinds.count++; 21 23 22 - printf("add keybind: %d: %s (k=%d m=%d g=%d x=%d)\n", i, id, key, mouse, gamepad, axis); 24 + printf("add keybind: %d: %s (k=%d a=%d m=%d g=%d x=%d)\n", i, id, key, alt, mouse, gamepad, axis); 23 25 kf_inputbinds.id[i] = id; 24 26 kf_inputbinds.key[i] = key; 27 + kf_inputbinds.alt[i] = alt; 25 28 kf_inputbinds.mouse[i] = mouse; 26 29 kf_inputbinds.gamepad[i] = gamepad; 27 30 kf_inputbinds.axis[i] = axis; ··· 42 45 return KF_INPUTBIND_NONE; 43 46 } 44 47 45 - int kf_checkkeypress(kf_inputbind_t id) { return kf_inputbinds.key[id] != KEY_NULL && IsKeyPressed(kf_inputbinds.key[id]); } 46 - int kf_checkkeyrelease(kf_inputbind_t id) { return kf_inputbinds.key[id] != KEY_NULL && IsKeyReleased(kf_inputbinds.key[id]); } 47 - int kf_checkkeydown(kf_inputbind_t id) { return kf_inputbinds.key[id] != KEY_NULL && IsKeyDown(kf_inputbinds.key[id]); } 48 - int kf_checkkeyup(kf_inputbind_t id) { return kf_inputbinds.key[id] != KEY_NULL && IsKeyUp(kf_inputbinds.key[id]); } 49 - int kf_checkmousepress(kf_inputbind_t id) { return kf_inputbinds.mouse[id] != MOUSE_BUTTON_UNKNOWN && IsMouseButtonPressed(kf_inputbinds.mouse[id]); } 50 - int kf_checkmouserelease(kf_inputbind_t id) { return kf_inputbinds.mouse[id] != MOUSE_BUTTON_UNKNOWN && IsMouseButtonReleased(kf_inputbinds.mouse[id]); } 51 - int kf_checkmousedown(kf_inputbind_t id) { return kf_inputbinds.mouse[id] != MOUSE_BUTTON_UNKNOWN && IsMouseButtonDown(kf_inputbinds.mouse[id]); } 52 - int kf_checkmouseup(kf_inputbind_t id) { return kf_inputbinds.mouse[id] != MOUSE_BUTTON_UNKNOWN && IsMouseButtonUp(kf_inputbinds.mouse[id]); } 53 - int kf_checkgamepadpress(kf_inputbind_t id) { return kf_inputbinds.gamepad[id] != GAMEPAD_BUTTON_UNKNOWN && IsGamepadButtonPressed(0, kf_inputbinds.gamepad[id]); } 54 - int kf_checkgamepadrelease(kf_inputbind_t id) { return kf_inputbinds.gamepad[id] != GAMEPAD_BUTTON_UNKNOWN && IsGamepadButtonReleased(0, kf_inputbinds.gamepad[id]); } 55 - int kf_checkgamepaddown(kf_inputbind_t id) { return kf_inputbinds.gamepad[id] != GAMEPAD_BUTTON_UNKNOWN && IsGamepadButtonDown(0, kf_inputbinds.gamepad[id]); } 56 - int kf_checkgamepadup(kf_inputbind_t id) { return kf_inputbinds.gamepad[id] != GAMEPAD_BUTTON_UNKNOWN && IsGamepadButtonUp(0, kf_inputbinds.gamepad[id]); } 57 - float kf_getgamepadaxis(kf_inputbind_t id) { return kf_inputbinds.axis[id] != GAMEPAD_AXIS_UNKNOWN ? GetGamepadAxisMovement(0, kf_inputbinds.gamepad[id]) : 0; } 48 + 49 + int kf_checkkeypress(kf_inputbind_t id) 50 + { 51 + return 52 + (kf_inputbinds.key[id] != KEY_NULL && IsKeyPressed(kf_inputbinds.key[id])) || 53 + (kf_inputbinds.alt[id] != KEY_NULL && IsKeyPressed(kf_inputbinds.alt[id])); 54 + } 55 + 56 + int kf_checkkeyrelease(kf_inputbind_t id) 57 + { 58 + return 59 + (kf_inputbinds.key[id] != KEY_NULL && IsKeyReleased(kf_inputbinds.key[id])) || 60 + (kf_inputbinds.alt[id] != KEY_NULL && IsKeyReleased(kf_inputbinds.alt[id])); 61 + } 62 + 63 + int kf_checkkeydown(kf_inputbind_t id) 64 + { 65 + return 66 + (kf_inputbinds.key[id] != KEY_NULL && IsKeyDown(kf_inputbinds.key[id])) || 67 + (kf_inputbinds.alt[id] != KEY_NULL && IsKeyDown(kf_inputbinds.alt[id])); 68 + } 69 + 70 + int kf_checkkeyup(kf_inputbind_t id) 71 + { 72 + return 73 + (kf_inputbinds.key[id] != KEY_NULL && IsKeyUp(kf_inputbinds.key[id])) || 74 + (kf_inputbinds.alt[id] != KEY_NULL && IsKeyUp(kf_inputbinds.alt[id])); 75 + } 76 + 77 + int kf_checkmousepress(kf_inputbind_t id) 78 + { 79 + return kf_inputbinds.mouse[id] != MOUSE_BUTTON_UNKNOWN && IsMouseButtonPressed(kf_inputbinds.mouse[id]); 80 + } 81 + 82 + int kf_checkmouserelease(kf_inputbind_t id) 83 + { 84 + return kf_inputbinds.mouse[id] != MOUSE_BUTTON_UNKNOWN && IsMouseButtonReleased(kf_inputbinds.mouse[id]); 85 + } 86 + 87 + int kf_checkmousedown(kf_inputbind_t id) 88 + { 89 + return kf_inputbinds.mouse[id] != MOUSE_BUTTON_UNKNOWN && IsMouseButtonDown(kf_inputbinds.mouse[id]); 90 + } 91 + 92 + int kf_checkmouseup(kf_inputbind_t id) 93 + { 94 + return kf_inputbinds.mouse[id] != MOUSE_BUTTON_UNKNOWN && IsMouseButtonUp(kf_inputbinds.mouse[id]); 95 + } 96 + 97 + int kf_checkgamepadpress(kf_inputbind_t id) 98 + { 99 + return kf_inputbinds.gamepad[id] != GAMEPAD_BUTTON_UNKNOWN && IsGamepadButtonPressed(0, kf_inputbinds.gamepad[id]); 100 + } 101 + 102 + int kf_checkgamepadrelease(kf_inputbind_t id) 103 + { 104 + return kf_inputbinds.gamepad[id] != GAMEPAD_BUTTON_UNKNOWN && IsGamepadButtonReleased(0, kf_inputbinds.gamepad[id]); 105 + } 106 + 107 + int kf_checkgamepaddown(kf_inputbind_t id) 108 + { 109 + return kf_inputbinds.gamepad[id] != GAMEPAD_BUTTON_UNKNOWN && IsGamepadButtonDown(0, kf_inputbinds.gamepad[id]); 110 + } 111 + 112 + int kf_checkgamepadup(kf_inputbind_t id) 113 + { 114 + return kf_inputbinds.gamepad[id] != GAMEPAD_BUTTON_UNKNOWN && IsGamepadButtonUp(0, kf_inputbinds.gamepad[id]); 115 + } 116 + 117 + float kf_getgamepadaxis(kf_inputbind_t id) 118 + { 119 + return kf_inputbinds.axis[id] != GAMEPAD_AXIS_UNKNOWN ? GetGamepadAxisMovement(0, kf_inputbinds.gamepad[id]) : 0; 120 + } 121 + 58 122 59 123 int kf_checkinputpress(kf_inputbind_t id) 60 124 {
+55 -35
src/main.c
··· 5 5 #include <stdio.h> 6 6 #include <stdlib.h> 7 7 8 + 8 9 static Camera2D cam; 9 10 static struct kf_vec2(u32) select = { 0, 0 }; 10 11 static int selected_tile = 0; 11 - 12 - enum { 12 + static bool selected_menu_this_frame = false; 13 + static enum { 13 14 menu_none, 14 15 menu_palette, 15 16 menu_escape ··· 33 34 inputbind_zoom_out 34 35 ; 35 36 36 - static void loadbinds() 37 + 38 + static 39 + void loadbinds() 37 40 { 38 - inputbind_move_up = kf_addinput("move_up", KEY_W, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_Y); 39 - inputbind_move_down = kf_addinput("move_down", KEY_S, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_Y); 40 - inputbind_move_left = kf_addinput("move_left", KEY_A, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_X); 41 - inputbind_move_right = kf_addinput("move_right", KEY_D, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_X); 41 + inputbind_move_up = kf_addinput("move_up", KEY_W, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_Y); 42 + inputbind_move_down = kf_addinput("move_down", KEY_S, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_Y); 43 + inputbind_move_left = kf_addinput("move_left", KEY_A, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_X); 44 + inputbind_move_right = kf_addinput("move_right", KEY_D, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_X); 42 45 43 - inputbind_ui_up = kf_addinput("ui_up", KEY_W, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_UP, GAMEPAD_AXIS_UNKNOWN); 44 - inputbind_ui_down = kf_addinput("ui_down", KEY_S, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_DOWN, GAMEPAD_AXIS_UNKNOWN); 45 - inputbind_ui_left = kf_addinput("ui_left", KEY_A, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_LEFT, GAMEPAD_AXIS_UNKNOWN); 46 - inputbind_ui_right = kf_addinput("ui_right", KEY_D, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_RIGHT, GAMEPAD_AXIS_UNKNOWN); 46 + inputbind_ui_up = kf_addinput("ui_up", KEY_W, KEY_UP, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_UP, GAMEPAD_AXIS_UNKNOWN); 47 + inputbind_ui_down = kf_addinput("ui_down", KEY_S, KEY_DOWN, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_DOWN, GAMEPAD_AXIS_UNKNOWN); 48 + inputbind_ui_left = kf_addinput("ui_left", KEY_A, KEY_LEFT, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_LEFT, GAMEPAD_AXIS_UNKNOWN); 49 + inputbind_ui_right = kf_addinput("ui_right", KEY_D, KEY_RIGHT, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_RIGHT, GAMEPAD_AXIS_UNKNOWN); 47 50 48 - inputbind_select = kf_addinput("select", KEY_F, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_RIGHT_FACE_DOWN, GAMEPAD_AXIS_UNKNOWN); 49 - inputbind_cancel = kf_addinput("cancel", KEY_Q, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT, GAMEPAD_AXIS_UNKNOWN); 51 + inputbind_select = kf_addinput("select", KEY_E, KEY_ENTER, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_RIGHT_FACE_DOWN, GAMEPAD_AXIS_UNKNOWN); 52 + inputbind_cancel = kf_addinput("cancel", KEY_Q, KEY_ESCAPE, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_RIGHT_FACE_RIGHT, GAMEPAD_AXIS_UNKNOWN); 50 53 51 - inputbind_pause = kf_addinput("pause", KEY_ESCAPE, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_MIDDLE_RIGHT, GAMEPAD_AXIS_UNKNOWN); 52 - inputbind_palette = kf_addinput("palette", KEY_TAB, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_RIGHT_FACE_UP, GAMEPAD_AXIS_UNKNOWN); 54 + inputbind_pause = kf_addinput("pause", KEY_ESCAPE, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_MIDDLE_RIGHT, GAMEPAD_AXIS_UNKNOWN); 55 + inputbind_palette = kf_addinput("palette", KEY_TAB, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_RIGHT_FACE_UP, GAMEPAD_AXIS_UNKNOWN); 53 56 54 - inputbind_zoom_reset = kf_addinput("zoom_reset", KEY_ZERO, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 55 - inputbind_zoom_in = kf_addinput("zoom_in", KEY_EQUAL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 56 - inputbind_zoom_out = kf_addinput("zoom_out", KEY_MINUS, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 57 + inputbind_zoom_reset = kf_addinput("zoom_reset", KEY_ZERO, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 58 + inputbind_zoom_in = kf_addinput("zoom_in", KEY_EQUAL, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 59 + inputbind_zoom_out = kf_addinput("zoom_out", KEY_MINUS, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_UNKNOWN); 57 60 } 58 61 59 - static void _player_tick_move(struct kf_actor *self) 62 + static 63 + void setmenu(int m) 64 + { 65 + menu = m; 66 + selected_menu_this_frame = true; 67 + } 68 + 69 + static 70 + void _player_tick_move(struct kf_actor *self) 60 71 { 61 72 struct kf_vec2(f32) v = {0, 0}; 62 73 ··· 105 116 kf_actor_addforce(self, v); 106 117 } 107 118 108 - static void _player_tick(struct kf_world *world, struct kf_actor *self) 119 + static 120 + void _player_tick(struct kf_world *world, struct kf_actor *self) 109 121 { 110 122 if (menu == menu_none) 111 123 _player_tick_move(self); ··· 113 125 kf_actor_move(world, self, kf_dts); 114 126 } 115 127 116 - static void _player_draw(struct kf_world *world, struct kf_actor *self) 128 + static 129 + void _player_draw(struct kf_world *world, struct kf_actor *self) 117 130 { 118 131 (void)world; 119 - // DrawRectangleLines(self->pos.x + self->size.x/2 + self->sizeoffset.x, self->pos.y + self->size.y/2 + self->sizeoffset.y, self->size.x, self->size.y, RED); 120 132 kf_actor_draw(self); 121 133 122 134 cam.target.x = self->pos.x + (self->size.x / 2); 123 135 cam.target.y = self->pos.y + (self->size.y / 2); 124 136 } 137 + 125 138 126 139 int main(int argc, const char *argv[]) 127 140 { ··· 136 149 loadbinds(); 137 150 138 151 kf_tiles.key[0] = "grass"; 139 - kf_tiles.color[0] = GREEN; 152 + kf_tiles.mapcol[0] = GREEN; 140 153 kf_tiles.key[1] = "dirt"; 141 - kf_tiles.color[1] = BROWN; 154 + kf_tiles.mapcol[1] = BROWN; 142 155 kf_tiles.key[2] = "stone"; 143 - kf_tiles.color[2] = GRAY; 156 + kf_tiles.mapcol[2] = GRAY; 144 157 kf_tiles.collide[2] = true; 145 158 kf_tiles.count = 3; 146 159 ··· 212 225 select.y = v.y / KF_TILE_SIZE_PX; 213 226 214 227 if (kf_checkinputpress(inputbind_palette)) 215 - menu = menu_palette; 216 - else if (kf_checkinputpress(inputbind_pause) && menu == menu_none) 217 - menu = menu_escape; 228 + setmenu(menu_palette); 229 + else if (kf_checkinputpress(inputbind_cancel) && menu == menu_none) 230 + setmenu(menu_escape); 218 231 else if (kf_checkinputpress(inputbind_zoom_reset)) 219 232 cam.zoom = 2; 220 233 else if (kf_checkinputpress(inputbind_zoom_in) && cam.zoom < 3.50f) ··· 227 240 228 241 BeginMode2D(cam); 229 242 kf_world_draw(world, cam); 230 - kf_world_drawcolliders(world, player, cam); 243 + // kf_world_drawcolliders(world, player, cam); 231 244 if (select.x < world->width && select.y < world->height) 232 245 { 233 246 if (IsMouseButtonPressed(MOUSE_BUTTON_LEFT)) ··· 240 253 player->draw(world, player); 241 254 EndMode2D(); 242 255 243 - switch (menu) 256 + if (selected_menu_this_frame) 257 + { 258 + selected_menu_this_frame = false; 259 + } 260 + else 244 261 { 262 + switch (menu) 263 + { 245 264 case menu_none: 246 265 break; 247 266 case menu_palette: 248 267 if (kf_ui_choice("Select tile", &kf_tiles.key[0], kf_tiles.count, &selected_tile)) 249 - menu = menu_none; 268 + setmenu(menu_none); 250 269 break; 251 270 case menu_escape: 252 - { 253 - static int result = 0; 271 + { 272 + static int result = 1; 254 273 if (kf_ui_yesno("Exit game?", &result)) 255 274 { 256 275 menu = menu_none; 257 - if (result == 0) 276 + if (result) 258 277 running = 0; 259 - result = 0; 278 + result = 1; 260 279 } 261 280 break; 281 + } 262 282 } 263 283 } 264 284
+4 -1
src/math.c
··· 3 3 #include <raylib.h> 4 4 #include <raymath.h> 5 5 6 + 6 7 #define x(T) \ 7 8 struct kf_vec2(T) kf_normalize_vec2##T(struct kf_vec2(T) v) \ 8 9 { \ ··· 26 27 _kf_mathdef(x) 27 28 #undef x 28 29 29 - static int _kf_isdir(enum kf_direction dir) 30 + 31 + static 32 + int _kf_isdir(enum kf_direction dir) 30 33 { 31 34 return dir >= kf_north && dir <= kf_west; 32 35 }
+1
src/sprites.c
··· 1 1 #include <keraforge.h> 2 2 #include <raylib.h> 3 3 4 + 4 5 struct kf_spritesheet kf_loadspritesheet(char *filename, int spritewidth, int spriteheight) 5 6 { 6 7 Texture2D tex = LoadTexture(filename);
+6 -3
src/ui.c
··· 1 1 #include <keraforge.h> 2 2 #include <raylib.h> 3 3 4 - static struct kf_uiconfig _kf_uiconfig = { 4 + 5 + static 6 + struct kf_uiconfig _kf_uiconfig = { 5 7 .select = KF_INPUTBIND_NONE, 6 8 .cancel = KF_INPUTBIND_NONE, 7 9 .up = KF_INPUTBIND_NONE, ··· 15 17 .xpadding = 8, 16 18 .ypadding = 16, 17 19 }; 20 + 18 21 19 22 struct kf_uiconfig *kf_ui_getconfig(void) 20 23 { ··· 64 67 65 68 if (kf_checkinputpress(_kf_uiconfig.select) || kf_checkinputpress(_kf_uiconfig.cancel)) 66 69 return 1; 67 - else if (kf_checkinputpress(_kf_uiconfig.down) && *choice < nchoices) 70 + else if (kf_checkinputpress(_kf_uiconfig.down) && *choice < nchoices - 1) 68 71 (*choice)++; 69 72 else if (kf_checkinputpress(_kf_uiconfig.up) && *choice > 0) 70 73 (*choice)--; ··· 75 78 int kf_ui_yesno(char *title, int *choice) 76 79 { 77 80 static char *yesno[] = { "yes", "no" }; 78 - return kf_ui_choice(title, yesno, 2, choice); 81 + return !kf_ui_choice(title, yesno, 2, choice); 79 82 } 80 83 81 84 int kf_ui_textinput(char *title, char *text);
+3 -1
src/world.c
··· 4 4 #include <string.h> 5 5 #include <math.h> 6 6 7 + 7 8 struct _kf_tiles kf_tiles = {0}; 9 + 8 10 9 11 struct kf_world *kf_world_new(u32 width, u32 height, kf_tileid_t fill) 10 12 { ··· 93 95 (int)y * KF_TILE_SIZE_PX, 94 96 KF_TILE_SIZE_PX, 95 97 KF_TILE_SIZE_PX, 96 - kf_tiles.color[*tile] 98 + kf_tiles.mapcol[*tile] 97 99 ); 98 100 tile++; /* shift tile pointer to the right */ 99 101 }