summaryrefslogtreecommitdiff
path: root/src/physics.c
blob: 6567dc49ea8198775414e1e445ed9ccca3565217 (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
#include "physics.h"
#include "game.h"

extern Game game;

static inline bool PhysicsEnabled(const Entity* e) {
    return EntityAllocated(e) && (e->flags & ENTITY_PHYSICS_ACTIVE);
}

static inline bool IsColliding(const Rectangle* a, const Rectangle* b) {
    bool collisionX = (a->x <= b->x && a->x + a->width > b->x)
        || (b->x <= a->x && b->x + b->width > a->x);

    bool collisionY = (a->y <= b->y && a->y + a->height > b->y)
        || (b->y <= a->y && b->y + b->height > a->y);

    return collisionX && collisionY;
}

static inline Rectangle GetPhysicsColliderGlobal(const Entity* e) {
    Rectangle physicsColliderGlobal = e->physicsCollider;
    physicsColliderGlobal.x += e->position.x;
    physicsColliderGlobal.y += e->position.y;

    return physicsColliderGlobal;
}

void MoveAndSlide(Entity* e, float deltaTime) {
    Vector2 velocity = e->velocity;
    Rectangle physicsCollider = GetPhysicsColliderGlobal(e);

    physicsCollider.x += e->velocity.x * deltaTime;
    for (int i = 0; i < MAX_ENTITY_COUNT; i++) {
        Entity* c = &game.entities[i];

        if(!PhysicsEnabled(c) || SameEntity(c, e)) continue;
        Rectangle otherCollider = GetPhysicsColliderGlobal(c);

        if(IsColliding(&physicsCollider, &otherCollider)) {
            if (velocity.x > 0) {
                physicsCollider.x = otherCollider.x - physicsCollider.width;
            } else {
                physicsCollider.x = otherCollider.x + otherCollider.width;
            }
        }
    }

    physicsCollider.y += e->velocity.y * deltaTime;
    for (int i = 0; i < MAX_ENTITY_COUNT; i++) {
        Entity* c = &game.entities[i];

        if(!PhysicsEnabled(c) || SameEntity(c, e)) continue;
        Rectangle otherCollider = GetPhysicsColliderGlobal(c);

        if(IsColliding(&physicsCollider, &otherCollider)) {
            if (velocity.y > 0) {
                physicsCollider.y = otherCollider.y - physicsCollider.height;
            } else {
                physicsCollider.y = otherCollider.y + otherCollider.height;
            }
        }
    }

    e->position.x = physicsCollider.x;
    e->position.y = physicsCollider.y;
}

#ifdef BEATEMUP_DEBUG
void DebugHighlights(const Entity* e) {
    if (!PhysicsEnabled(e))
        return;

    Rectangle dstRect = GetPhysicsColliderGlobal(e);
    DrawRectangle(dstRect.x, dstRect.y, dstRect.width, dstRect.height, e->physicsColliderColor);
}
#endif