A game engine for top-down 2D RPG games.
rpg game-engine raylib c99
1#include <keraforge.h> 2#include <stdlib.h> 3#include <raymath.h> 4 5struct kf_actor *kf_actor_new(void) 6{ 7 struct kf_actor *actor = calloc(1, sizeof(struct kf_actor)); 8 return actor; 9} 10 11int kf_actor_canmovetowards(struct kf_world *world, struct kf_actor *actor, struct kf_vec2(f32) dir) 12{ 13 Rectangle r = {actor->pos.x - actor->size.x / 2, actor->pos.y - actor->size.y / 2, actor->size.x, actor->size.y}; 14 r.x += dir.x; 15 r.y += dir.y; 16 17 /* get a range of tiles to check */ 18 const u32 sx = fmax(0, floorf(r.x / KF_TILE_SIZE_PX) - 1); 19 const u32 sy = fmax(0, floorf(r.y / KF_TILE_SIZE_PX) - 1); 20 const u32 ex = fmin(world->width, ceilf(r.width / KF_TILE_SIZE_PX) + sx + 2); 21 const u32 ey = fmin(world->height, ceilf(r.height / KF_TILE_SIZE_PX) + sy + 2); 22 const size_t down = world->width - ex + sx - 1; /* number of indexes to add to reach the next tile down */ 23 24 /* check if any tiles will collide with the actor's rect */ 25 const f32 trx = sx * KF_TILE_SIZE_PX; 26 Rectangle tr = { 27 trx, 28 sy * KF_TILE_SIZE_PX, 29 KF_TILE_SIZE_PX + 1, 30 KF_TILE_SIZE_PX + 1, 31 }; /* tile rect */ 32 u32 x; 33 kf_tileid_t *tile = kf_world_gettile(world, sx, sy); 34 35 for (u32 y = sy ; y <= ey ; y++) 36 { 37 for (x = sx ; x <= ex ; x++) 38 { 39 if (kf_tiles.collide[*tile] && CheckCollisionRecs(r, tr)) 40 return 0; 41 tile++; /* shift tile pointer to the right */ 42 tr.x += KF_TILE_SIZE_PX; 43 } 44 tile += down; /* shift tile pointer down */ 45 tr.x = trx; 46 tr.y += KF_TILE_SIZE_PX; 47 } 48 49 return 1; 50} 51 52void kf_actor_addforce(struct kf_actor *self, struct kf_vec2(f32) force) 53{ 54 self->vel.x += force.x; 55 self->vel.y += force.y; 56} 57 58void kf_actor_move(struct kf_world *world, struct kf_actor *self, f32 dt) 59{ 60 struct kf_vec2(f32) delta = kf_mulval_vec2(f32)(self->vel, (self->speed * self->speedmod) * dt); 61 62 if (self->collide) 63 { 64 if (delta.x && !kf_actor_canmovetowards(world, self, kf_vec2_x(f32)(delta))) 65 delta.x = 0; 66 if (delta.y && !kf_actor_canmovetowards(world, self, kf_vec2_y(f32)(delta))) 67 delta.y = 0; 68 } 69 70 self->pos = kf_add_vec2(f32)(self->pos, delta); 71 72 static const f32 speed_deadzone = 0.1f; 73 74 if (self->vel.x > -speed_deadzone && self->vel.x < speed_deadzone) 75 self->vel.x = 0; 76 else if (self->vel.x) 77 self->vel.x /= self->friction; 78 79 if (self->vel.y > -speed_deadzone && self->vel.y < speed_deadzone) 80 self->vel.y = 0; 81 else if (self->vel.y) 82 self->vel.y /= self->friction; 83 84 if (self->speedmod > -(1+speed_deadzone) && self->speedmod < 1+speed_deadzone) 85 self->speedmod = 1; 86 else if (self->speedmod) 87 self->speedmod -= self->friction * self->friction * dt; 88}