]> git.lizzy.rs Git - nothing.git/blob - src/game/level/physical_world.c
(#639) Make rigid bodies interact with platforms
[nothing.git] / src / game / level / physical_world.c
1 #include "system/stacktrace.h"
2 #include <stdlib.h>
3
4 #include "game/level/platforms.h"
5 #include "physical_world.h"
6 #include "system/lt.h"
7 #include "system/nth_alloc.h"
8
9 #define PHYSICAL_WORLD_CAPACITY 256
10 #define PHYSICAL_WORLD_GRAVITY 1500.0f
11
12 struct Physical_world
13 {
14     Lt *lt;
15     size_t capacity;
16     size_t size;
17     Solid_ref *solids;
18 };
19
20 Physical_world *create_physical_world(void)
21 {
22     Lt *lt = create_lt();
23     if (lt == NULL) {
24         return NULL;
25     }
26
27     Physical_world * const physical_world =
28         PUSH_LT(lt, nth_alloc(sizeof(Physical_world)), free);
29     if (physical_world == NULL) {
30         RETURN_LT(lt, NULL);
31     }
32
33     physical_world->solids =
34         PUSH_LT(
35             lt,
36             nth_alloc(sizeof(Solid_ref) * PHYSICAL_WORLD_CAPACITY),
37             free);
38     if (physical_world->solids == NULL) {
39         RETURN_LT(lt, NULL);
40     }
41
42     physical_world->capacity = PHYSICAL_WORLD_CAPACITY;
43     physical_world->size = 0;
44     physical_world->lt = lt;
45
46     return physical_world;
47 }
48
49 void destroy_physical_world(Physical_world *physical_world)
50 {
51     trace_assert(physical_world);
52     RETURN_LT0(physical_world->lt);
53 }
54
55 void physical_world_apply_gravity(Physical_world *physical_world)
56 {
57     for (size_t i = 0; i < physical_world->size; ++i) {
58         solid_apply_force(
59             physical_world->solids[i],
60             vec(0.0f, PHYSICAL_WORLD_GRAVITY));
61     }
62 }
63
64 void physical_world_collide_solids(Physical_world *physical_world,
65                                    Platforms *platforms)
66 {
67     trace_assert(physical_world);
68
69     for (size_t i = 0; i < physical_world->size; ++i) {
70         solid_collide_with_solid(
71             physical_world->solids[i],
72             platforms_as_solid(platforms));
73
74         for (size_t j = 0; j < physical_world->size; ++j) {
75             if (i != j) {
76                 solid_collide_with_solid(
77                     physical_world->solids[i],
78                     physical_world->solids[j]);
79             }
80         }
81
82         solid_collide_with_solid(
83             physical_world->solids[i],
84             platforms_as_solid(platforms));
85     }
86 }
87
88 int physical_world_add_solid(Physical_world *physical_world,
89                              Solid_ref solid)
90 {
91     trace_assert(physical_world);
92
93     if (physical_world->size >= physical_world->capacity) {
94         const size_t new_capacity = physical_world->capacity * 2;
95         Solid_ref * const new_solids = nth_realloc(
96             physical_world->solids,
97             sizeof(Solid_ref) * new_capacity);
98
99         if (new_solids == NULL) {
100             return -1;
101         }
102
103         physical_world->capacity = new_capacity;
104         physical_world->solids = REPLACE_LT(
105             physical_world->lt,
106             physical_world->solids,
107             new_solids);
108     }
109
110     physical_world->solids[physical_world->size++] = solid;
111
112     return 0;
113 }
114
115 void physical_world_clean(Physical_world *physical_world)
116 {
117     trace_assert(physical_world);
118     physical_world->size = 0;
119 }