]> git.lizzy.rs Git - nothing.git/blob - src/game/level/player/rigid_rect.c
Remove ./ prefix from includes
[nothing.git] / src / game / level / player / rigid_rect.c
1 #include <assert.h>
2 #include <SDL2/SDL.h>
3
4 #include "color.h"
5 #include "rigid_rect.h"
6 #include "system/error.h"
7 #include "system/lt.h"
8
9 #define RIGID_RECT_GRAVITY 1500.0f
10
11 struct rigid_rect_t {
12     lt_t *lt;
13     vec_t position;
14     vec_t velocity;
15     vec_t movement;
16     vec_t size;
17     color_t color;
18     int touches_ground;
19 };
20
21 static const vec_t opposing_rect_side_forces[RECT_SIDE_N] = {
22     { .x = 1.0f,  .y =  0.0f  },  /* RECT_SIDE_LEFT = 0, */
23     { .x = -1.0f, .y =  0.0f  },  /* RECT_SIDE_RIGHT, */
24     { .x = 0.0f,  .y =  1.0f, },  /* RECT_SIDE_TOP, */
25     { .x = 0.0f,  .y = -1.0f, }   /* RECT_SIDE_BOTTOM, */
26 };
27
28 static vec_t opposing_force_by_sides(int sides[RECT_SIDE_N])
29 {
30     vec_t opposing_force = {
31         .x = 0.0f,
32         .y = 0.0f
33     };
34
35     for (rect_side_t side = 0; side < RECT_SIDE_N; ++side) {
36         if (sides[side]) {
37             vec_add(
38                 &opposing_force,
39                 opposing_rect_side_forces[side]);
40         }
41     }
42
43     return opposing_force;
44 }
45
46 rigid_rect_t *create_rigid_rect(rect_t rect, color_t color)
47 {
48     lt_t *lt = create_lt();
49
50     if (lt == NULL) {
51         return NULL;
52     }
53
54     rigid_rect_t *rigid_rect = PUSH_LT(lt, malloc(sizeof(rigid_rect_t)), free);
55     if (rigid_rect == NULL) {
56         throw_error(ERROR_TYPE_LIBC);
57         RETURN_LT(lt, NULL);
58     }
59
60     rigid_rect->lt = lt;
61     rigid_rect->position = vec(rect.x, rect.y);
62     rigid_rect->velocity = vec(0.0f, 0.0f);
63     rigid_rect->movement = vec(0.0f, 0.0f);
64     rigid_rect->size = vec(rect.w, rect.h);
65     rigid_rect->color = color;
66     rigid_rect->touches_ground = 0;
67
68     return rigid_rect;
69 }
70
71 void destroy_rigid_rect(rigid_rect_t *rigid_rect)
72 {
73     RETURN_LT0(rigid_rect->lt);
74 }
75
76 int rigid_rect_render(const rigid_rect_t *rigid_rect,
77                       SDL_Renderer *renderer,
78                       const camera_t *camera)
79 {
80     return camera_fill_rect(
81         camera,
82         renderer,
83         rigid_rect_hitbox(rigid_rect),
84         rigid_rect->color);
85
86 }
87
88 int rigid_rect_update(rigid_rect_t * rigid_rect,
89                       const platforms_t *platforms,
90                       float delta_time)
91 {
92     assert(rigid_rect);
93     assert(platforms);
94
95     rigid_rect->touches_ground = 0;
96
97     rigid_rect->velocity.y += RIGID_RECT_GRAVITY * delta_time;
98     rigid_rect->position = vec_sum(
99         rigid_rect->position,
100         vec_scala_mult(
101             vec_sum(
102                 rigid_rect->velocity,
103                 rigid_rect->movement),
104             delta_time));
105
106     int sides[RECT_SIDE_N] = { 0, 0, 0, 0 };
107
108     platforms_rect_object_collide(platforms, rigid_rect_hitbox(rigid_rect), sides);
109
110     if (sides[RECT_SIDE_BOTTOM]) {
111         rigid_rect->touches_ground = 1;
112     }
113
114     vec_t opposing_force = opposing_force_by_sides(sides);
115
116     for (int i = 0; i < 1000 && vec_length(opposing_force) > 1e-6; ++i) {
117         rigid_rect->position = vec_sum(
118             rigid_rect->position,
119             vec_scala_mult(
120                 opposing_force,
121                 1e-2f));
122
123         if (fabs(opposing_force.x) > 1e-6 && (opposing_force.x < 0.0f) != ((rigid_rect->velocity.x + rigid_rect->movement.x) < 0.0f)) {
124             rigid_rect->velocity.x = 0.0f;
125             rigid_rect->movement.x = 0.0f;
126         }
127
128         if (fabs(opposing_force.y) > 1e-6 && (opposing_force.y < 0.0f) != ((rigid_rect->velocity.y + rigid_rect->movement.y) < 0.0f)) {
129             rigid_rect->velocity.y = 0.0f;
130             rigid_rect->movement.y = 0.0f;
131         }
132
133         platforms_rect_object_collide(
134             platforms,
135             rigid_rect_hitbox(rigid_rect),
136             sides);
137         opposing_force = opposing_force_by_sides(sides);
138     }
139
140     return 0;
141 }
142
143 rect_t rigid_rect_hitbox(const rigid_rect_t *rigid_rect)
144 {
145     return rect_from_vecs(
146         rigid_rect->position,
147         rigid_rect->size);
148 }
149
150 void rigid_rect_move(rigid_rect_t *rigid_rect,
151                            vec_t movement)
152 {
153     rigid_rect->movement = movement;
154 }
155
156 void rigid_rect_jump(rigid_rect_t *rigid_rect,
157                      float force)
158 {
159     rigid_rect->velocity.y = -force;
160 }
161
162 int rigid_rect_touches_ground(const rigid_rect_t *rigid_rect)
163 {
164     return rigid_rect->touches_ground;
165 }