summaryrefslogtreecommitdiff
path: root/src/physics.c
blob: 33065a9f1aa2a14947ef5fe9a5bc60df4d4639b4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <stdbool.h>
#include "game.h"
#include "entity.h"
#include "physics.h"

extern struct game game;

static inline bool can_collide(const struct entity* entity) {
  return (entity->flags & ENTITY_ACTIVE) && (entity->flags & ENTITY_COLLISION_ACTIVE);
}

static inline bool aabb(const struct entity* a, const struct entity* b) {
  Rectangle acol = get_entity_collider_world(a);
  Rectangle bcol = get_entity_collider_world(b);

  bool collision_x = (acol.x <= bcol.x && acol.x + acol.width > bcol.x) ||
    (bcol.x <= acol.x && bcol.x + bcol.width > acol.x);
  bool collision_y = (acol.y <= bcol.y && acol.y + acol.height > bcol.y) ||
    (bcol.y <= acol.y && bcol.y + bcol.height > acol.y);
  
  return collision_x && collision_y;
}

void move_and_collide
(
 struct entity* entity,
 float delta_time
 ) {
  entity->position.x += entity->velocity.x * delta_time;

  if (can_collide(entity)) {
    for (int i = 0; i < MAX_ENTITY_COUNT; i++) {
      struct entity* other = &game.entities[i];
      if (same_entity(entity, other) || !can_collide(other) || !aabb(entity, other))
        continue;

      Rectangle acol = get_entity_collider_world(entity);
      Rectangle bcol = get_entity_collider_world(other);

      if (entity->velocity.x > 0) {
        entity->position.x = bcol.x - acol.width - entity->collider.x;

        entity_handle_collision(entity, other, Direction_Right);
        entity_handle_collision(other, entity, Direction_Left);
      } else {
        entity->position.x = bcol.x + bcol.width - entity->collider.x;

        entity_handle_collision(entity, other, Direction_Left);
        entity_handle_collision(other, entity, Direction_Right);
      }
    }
  }

  entity->position.y += entity->velocity.y * delta_time;

  if (can_collide(entity)) {
    for (int i = 0; i < MAX_ENTITY_COUNT; i++) {
      struct entity* other = &game.entities[i];
      if (same_entity(other, entity) || !can_collide(other) || !aabb(entity, other))
        continue;

      Rectangle acol = get_entity_collider_world(entity);
      Rectangle bcol = get_entity_collider_world(other);

      if (entity->velocity.y > 0) {
        entity->position.y = bcol.y - acol.height - entity->collider.y;

        entity_handle_collision(entity, other, Direction_Down);
        entity_handle_collision(other, entity, Direction_Up);
      } else {
        entity->position.y = bcol.y + bcol.height - entity->collider.y;

        entity_handle_collision(entity, other, Direction_Up);
        entity_handle_collision(other, entity, Direction_Down);
      }
    }
  }
}