Mirai's Miscellaneous Misadventures
M54 / core / sprites.c
1
2
3
4#include <stdlib.h>
5#include "../mimimi.h"
6
7static int mimimi_wall_tile(struct mimimi_ground *ground, int x, int y)
8{
9 if (mimimi_ground_tile(ground, x, y + 1) == 0 && mimimi_ground_tile(ground, x, y - 1) == 0) return 0;
10 return mimimi_ground_tile(ground, x, y);
11}
12
13static void mimimi_wall_physics(struct mimimi_physics *physics, struct mimimi_position *position, struct mimimi_ground *ground)
14{
15 int x0, y0;
16 int x1, y1;
17 int left, right;
18 int top;
19
20 x0 = position->x;
21 y0 = position->y;
22 x1 = physics->width / 2;
23 y1 = physics->height;
24
25 top = mimimi_div_down(y0 - y1, 128);
26 left = mimimi_div_down(x0 - x1, 128);
27 right = mimimi_div_down(x0 + x1, 128);
28
29 if (mimimi_wall_tile(ground, left, top) != 0) {
30 if (physics->dx < 0) physics->dx = 0;
31 position->x = (left + 1) * 128 + x1;
32 }
33
34 if (mimimi_wall_tile(ground, right, top) != 0) {
35 if (physics->dx > 0) physics->dx = 0;
36 position->x = right * 128 - x1 - 1;
37 }
38}
39
40static void mimimi_slope_physics(struct mimimi_physics *physics, struct mimimi_position *position, struct mimimi_ground *ground)
41{
42 int x0, y0;
43 int x1, y1;
44 int top, bottom;
45 int left, right;
46
47 x0 = position->x;
48 y0 = position->y;
49 x1 = physics->width / 2;
50 y1 = physics->height;
51
52 top = mimimi_div_down(y0 - y1, 128);
53 bottom = mimimi_div_down(y0 - 1, 128);
54 left = mimimi_div_down(x0 - x1, 128);
55 right = mimimi_div_down(x0 + x1, 128);
56
57 if (mimimi_ground_tile(ground, left, bottom) != 0) {
58 if (mimimi_ground_tile(ground, left, top) == 0) {
59 position->y = bottom * 128;
60 if (physics->sprite != NULL) physics->sprite->trail = 0xFF;
61 }
62 }
63
64 if (mimimi_ground_tile(ground, right, bottom) != 0) {
65 if (mimimi_ground_tile(ground, right, top) == 0) {
66 position->y = bottom * 128;
67 if (physics->sprite != NULL) physics->sprite->trail = 0xFF;
68 }
69 }
70}
71
72static void mimimi_ceiling_physics(struct mimimi_physics *physics, struct mimimi_position *position, struct mimimi_ground *ground)
73{
74 int x0, y0;
75 int x1, y1;
76 int top, top2;
77 int left, right;
78
79 x0 = position->x;
80 y0 = position->y;
81 x1 = physics->width / 2;
82 y1 = physics->height;
83
84 top = mimimi_div_down(y0 - y1, 128);
85 top2 = top - 1;
86 left = mimimi_div_down(x0 - x1, 128);
87 right = mimimi_div_down(x0 + x1, 128);
88
89 if (mimimi_ground_tile(ground, left, top) != 0 && mimimi_ground_tile(ground, right, top) != 0) {
90 if (mimimi_ground_tile(ground, left, top2) != 0 || mimimi_ground_tile(ground, right, top2) != 0) {
91 if (physics->dy < 0) physics->dy = 0;
92 position->y = (top + 1) * 128 + y1;
93 }
94 }
95}
96
97static void mimimi_landing_physics(struct mimimi_physics *physics, struct mimimi_position *position, struct mimimi_ground *ground)
98{
99 int x0, y0;
100 int x1, y1;
101 int left, right;
102 int bottom, bottom1;
103
104 if (physics->dy < 0) return;
105
106 y0 = position->y - mimimi_div(physics->dy, 256) - 1;
107 x0 = position->x;
108 x1 = physics->width / 2;
109 y1 = position->y;
110
111 bottom = mimimi_div_down(y0, 128);
112 bottom1 = mimimi_div_down(y1, 128);
113 left = mimimi_div_down(x0 - x1, 128);
114 right = mimimi_div_down(x0 + x1, 128);
115
116 while (bottom <= bottom1) {
117 if (mimimi_ground_tile(ground, left, bottom) != 0 || mimimi_ground_tile(ground, right, bottom) != 0) {
118 physics->airborne = 0;
119 physics->dy = 0;
120 position->y = bottom * 128;
121 return;
122 }
123 bottom++;
124 }
125}
126
127static void mimimi_fall_physics(struct mimimi_physics *physics, struct mimimi_position *position, struct mimimi_ground *ground)
128{
129 int x0, y0;
130 int x1;
131 int bottom, bottom2;
132 int center;
133 int left, right;
134
135 x0 = position->x;
136 y0 = position->y;
137 x1 = physics->width / 2;
138
139 bottom = mimimi_div_down(y0, 128);
140 bottom2 = bottom + 1;
141 center = mimimi_div_down(x0, 128);
142 left = mimimi_div_down(x0 - x1, 128);
143 right = mimimi_div_down(x0 + x1, 128);
144
145 if (mimimi_ground_tile(ground, left, bottom) == 0 && mimimi_ground_tile(ground, right, bottom) == 0) {
146 if (mimimi_ground_tile(ground, center, bottom2) == 0) {
147 physics->airborne = 1;
148 }
149 else {
150 if (physics->sprite != NULL) physics->sprite->trail = 0xFF;
151 position->y = bottom2 * 128;
152 }
153 }
154}
155
156static void mimimi_physics_dynamics(struct mimimi_physics *physics, struct mimimi_position *position)
157{
158 position->x += mimimi_div(physics->dx, 256);
159 position->y += mimimi_div(physics->dy, 256);
160}
161
162static void mimimi_ground_collision_physics(struct mimimi_physics *physics, struct mimimi_position *position, struct mimimi_ground *ground)
163{
164 mimimi_slope_physics(physics, position, ground);
165 mimimi_wall_physics(physics, position, ground);
166 mimimi_fall_physics(physics, position, ground);
167 if (physics->airborne == 0) position->y = mimimi_div_down(position->y, 128) * 128;
168}
169
170static void mimimi_airborne_collision_physics(struct mimimi_physics *physics, struct mimimi_position *position, struct mimimi_ground *ground)
171{
172 mimimi_ceiling_physics(physics, position, ground);
173 mimimi_wall_physics(physics, position, ground);
174 mimimi_landing_physics(physics, position, ground);
175}
176
177static void mimimi_ground_physics(struct mimimi_physics *physics)
178{
179 physics->dx -= mimimi_div(physics->dx, 5);
180 physics->dy = 0;
181}
182
183static void mimimi_airborne_physics(struct mimimi_physics *physics)
184{
185 physics->dy += physics->gravity;
186 physics->dx -= mimimi_div(physics->dx, 7);
187 physics->dy -= mimimi_div(physics->dy, 32);
188}
189
190void mimimi_collision_physics_tick(struct mimimi_physics *physics, struct mimimi_position *position, struct mimimi_ground *ground)
191{
192 if (physics->airborne == 0) mimimi_ground_collision_physics(physics, position, ground);
193 else mimimi_airborne_collision_physics(physics, position, ground);
194}
195
196void mimimi_physics_tick(struct mimimi_physics *physics, struct mimimi_position *position, struct mimimi_ground *ground)
197{
198 if (physics->airborne == 0) mimimi_ground_physics(physics);
199 else mimimi_airborne_physics(physics);
200 mimimi_physics_dynamics(physics, position);
201 mimimi_collision_physics_tick(physics, position, ground);
202}
203
204void mimimi_physics(struct mimimi_physics *physics, int width, int height)
205{
206 physics->dx = 0;
207 physics->dy = 0;
208 physics->airborne = 1;
209 physics->width = width;
210 physics->height = height;
211 physics->gravity = 2048;
212 physics->sprite = NULL;
213}
214
215static void mimimi_walk_tick(struct mimimi_walk *walk, struct mimimi_physics *physics)
216{
217 int ax;
218
219 if (walk->direction == 0) return;
220
221 if (physics->airborne == 0) ax = walk->ground_speed;
222 else ax = walk->airborne_speed;
223
224 if (walk->direction == 1) physics->dx -= ax;
225 if (walk->direction == 2) physics->dx += ax;
226}
227
228void mimimi_sprite(struct mimimi_sprite *sprite, struct mimimi_model *model, struct mimimi_ground *ground, int x, int y, int width, int height)
229{
230 sprite->position.x = x;
231 sprite->position.y = y;
232
233 sprite->trailing_y = y;
234 sprite->trail = 0;
235
236 sprite->ground = ground;
237 mimimi_physics(&sprite->physics, width, height);
238 sprite->physics.sprite = sprite;
239
240 sprite->walk.ground_speed = 4096;
241 sprite->walk.airborne_speed = 2048;
242 sprite->walk.direction = 0;
243
244 sprite->offset.x = 0;
245 sprite->offset.y = 0;
246
247 sprite->animation_time = 0;
248 sprite->landing_time = 0;
249 sprite->direction = 1;
250 sprite->model = model;
251}
252
253void mimimi_sprite_tick(struct mimimi_sprite *sprite)
254{
255 mimimi_walk_tick(&sprite->walk, &sprite->physics);
256 sprite->position.x -= sprite->offset.x;
257 sprite->position.y -= sprite->offset.y;
258 mimimi_physics_tick(&sprite->physics, &sprite->position, sprite->ground);
259 sprite->position.x += sprite->offset.x;
260 sprite->position.y += sprite->offset.y;
261}
262
263void mimimi_jump(void *data)
264{
265 struct mimimi_sprite *sprite;
266 sprite = data;
267 if (sprite->physics.airborne != 0) return;
268 sprite->physics.airborne = 1;
269 sprite->physics.dy = -0x6800;
270}