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