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}