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

Add sprinting and transparent tiles

Changed files
+62 -17
include
keraforge
src
+2
include/keraforge/actor.h
··· 35 35 bool controlled; 36 36 /* The direction that the actor is pointing. */ 37 37 enum kf_direction pointing; 38 + /* If the actor is running. This will not increase their speed, you are expected to yourself. */ 39 + bool running; 38 40 /* Called every frame to update the actor. Don't forget about deltatime (kf_dts, kf_dtms)! */ 39 41 void (*tick)(struct kf_world *world, struct kf_actor *self); 40 42 /* Called every frame to render the actor. */
+3
include/keraforge/world.h
··· 65 65 struct kf_vec2(u32) sprite[KF_TILEID_MAX]; 66 66 /* Whether or not this tile has collision. */ 67 67 bool collide[KF_TILEID_MAX]; 68 + /* Whether or not this tile has a transparent or transluscent texture. */ 69 + bool transparent[KF_TILEID_MAX]; 68 70 }; 69 71 /* Struct-of-arrays for tiles. */ 70 72 extern struct _kf_tiles kf_tiles; ··· 77 79 struct kf_spritesheet *sheet; 78 80 struct kf_vec2(u32) sprite; 79 81 bool collide; 82 + bool transparent; 80 83 }; 81 84 82 85 kf_tileid_t kf_addtile(struct kf_tile_opts opts);
+17 -7
src/actor.c
··· 119 119 else if (self->vel.y) 120 120 self->vel.y /= self->friction; 121 121 122 - if (self->speedmod > -(1+speed_deadzone) && self->speedmod < 1+speed_deadzone) 123 - self->speedmod = 1; 124 - else if (self->speedmod) 125 - self->speedmod -= self->friction * self->friction * dt; 122 + // if (self->speedmod > -(1+speed_deadzone) && self->speedmod < 1+speed_deadzone) 123 + // self->speedmod = 1; 124 + // else if (self->speedmod) 125 + // self->speedmod -= self->friction * self->friction * dt; 126 126 } 127 127 128 128 void kf_actor_draw(struct kf_actor *actor) 129 129 { 130 + int frames = 4; 130 131 int x = 0, y = 0; 131 132 132 133 switch (actor->pointing) ··· 137 138 case kf_north: y = 3; break; 138 139 } 139 140 140 - if (actor->vel.x != 0 || actor->vel.y != 0) 141 + bool moving = actor->vel.x != 0 || actor->vel.y != 0; 142 + 143 + if (actor->running && moving) 144 + { 145 + y += 5; /* run sprites */ 146 + frames = 6; 147 + } 148 + else if (moving) 149 + { 141 150 x += 7; /* walk sprites */ 151 + } 142 152 143 - x += (int)(kf_s * 5) % 4; 153 + /* todo: jump */ 144 154 145 - /* todo: run and jump */ 155 + x += (int)(kf_s * (frames+1)) % frames; 146 156 147 157 kf_drawsprite(&actor->sprites, actor->pos.x, actor->pos.y, x, y); 148 158 }
+3 -3
src/input.c
··· 16 16 kf_inputbind_t i = kf_inputbinds.count; 17 17 if (i >= KF_INPUTBIND_MAX) 18 18 { 19 - fprintf(stderr, "error: max keybind count is 255.\n"); 20 - return -1; 19 + KF_THROW("max keybind count is 255"); 20 + return -1; /* unreachable */ 21 21 } 22 22 kf_inputbinds.count++; 23 23 24 - printf("add keybind: %d: %s (k=%d a=%d m=%d g=%d x=%d)\n", i, id, key, alt, mouse, gamepad, axis); 24 + kf_logdbg("add keybind: %d: %s (k=%d a=%d m=%d g=%d x=%d)", i, id, key, alt, mouse, gamepad, axis); 25 25 kf_inputbinds.id[i] = id; 26 26 kf_inputbinds.key[i] = key; 27 27 kf_inputbinds.alt[i] = alt;
+33 -5
src/main.c
··· 26 26 inputbind_move_down, 27 27 inputbind_move_left, 28 28 inputbind_move_right, 29 + inputbind_run, 29 30 inputbind_ui_up, 30 31 inputbind_ui_down, 31 32 inputbind_ui_left, ··· 45 46 static 46 47 void loadbinds() 47 48 { 48 - inputbind_move_up = kf_addinput("move_up", KEY_W, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_Y); 49 - inputbind_move_down = kf_addinput("move_down", KEY_S, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_Y); 50 - inputbind_move_left = kf_addinput("move_left", KEY_A, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_X); 51 - inputbind_move_right = kf_addinput("move_right", KEY_D, KEY_NULL, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_UNKNOWN, GAMEPAD_AXIS_LEFT_X); 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); 52 54 53 55 inputbind_ui_up = kf_addinput("ui_up", KEY_W, KEY_UP, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_UP, GAMEPAD_AXIS_UNKNOWN); 54 56 inputbind_ui_down = kf_addinput("ui_down", KEY_S, KEY_DOWN, MOUSE_BUTTON_UNKNOWN, GAMEPAD_BUTTON_LEFT_FACE_DOWN, GAMEPAD_AXIS_UNKNOWN); ··· 127 129 void _player_tick(struct kf_world *world, struct kf_actor *self) 128 130 { 129 131 if (menu == menu_none) 132 + { 130 133 _player_tick_move(self); 131 134 135 + if (kf_checkinputpress(inputbind_run)) 136 + { 137 + self->running = true; 138 + self->speedmod = 1.5; 139 + } 140 + else if (kf_checkinputrelease(inputbind_run)) 141 + { 142 + self->running = false; 143 + self->speedmod = 1; 144 + } 145 + } 146 + 132 147 kf_actor_move(world, self, kf_dts); 133 148 } 134 149 ··· 223 238 .sprite = {8, 0}, 224 239 .collide = true, 225 240 ); 241 + KF_ADDTILE( 242 + .key = "ice", 243 + .mapcol = BLUE, 244 + .sheet = &terrain, 245 + .sprite = {8, 4}, 246 + .transparent = true, 247 + ); 248 + KF_ADDTILE( 249 + .key = "dirt", 250 + .mapcol = BROWN, 251 + .sheet = &terrain, 252 + .sprite = {12, 0}, 253 + ); 226 254 kf_logdbg("loaded %d tiles", kf_tiles.count); 227 255 228 256 struct kf_uiconfig *uiconfig = kf_ui_getconfig(); ··· 239 267 if (!world) 240 268 KF_THROW("failed to load world: %p", world); 241 269 242 - struct kf_actor *player = kf_actor_new(kf_actor_loadspritesheet("data/res/img/char/whom.png"), 10, 10, true); 270 + struct kf_actor *player = kf_actor_new(kf_actor_loadspritesheet("data/res/img/char/template.png"), 10, 10, true); 243 271 player->sizeoffset.y = 6; 244 272 player->pos.x = world->width / 4.0f * KF_TILE_SIZE_PX; 245 273 player->pos.y = world->height / 4.0f * KF_TILE_SIZE_PX;
+4 -2
src/world.c
··· 26 26 kf_tiles.sheet[id] = opts.sheet; 27 27 kf_tiles.sprite[id] = opts.sprite; 28 28 kf_tiles.collide[id] = opts.collide; 29 + kf_tiles.transparent[id] = opts.transparent; 29 30 30 31 return id; 31 32 } ··· 34 35 { 35 36 const size_t len = sizeof(struct kf_world) + sizeof(struct kf_tile)*width*height; 36 37 struct kf_world *world = malloc(len); 37 - printf("creating world: %lu bytes: %p\n", len, world); 38 + kf_loginfo("creating world: %lu bytes: %p\n", len, world); 38 39 world->revision = 0; 39 40 world->width = width; 40 41 world->height = height; ··· 183 184 for (x = sx ; x < ex ; x++) 184 185 { 185 186 KF_SANITY_CHECK(tile->subid <= kf_tiles.count, "erroneous subtile on map at %u,%u: %u (count=%u)", x, y, tile->subid, kf_tiles.count); 187 + /* 0x1111: full tile, no subtile rendering needed */ 186 188 KF_SANITY_CHECK(tile->id <= kf_tiles.count, "erroneous tile on map at %u,%u: %u (count=%u)", x, y, tile->id, kf_tiles.count); 187 - if (tile->data != 0x1111 && tile->subid && tile->id) /* 0x1111: full tile, no subtile rendering needed */ 189 + if ((tile->data != 0x1111 || kf_tiles.transparent[tile->id]) && tile->subid && tile->id) 188 190 { 189 191 kf_drawsprite_wh( 190 192 kf_tiles.sheet[tile->subid],