Mirai's Miscellaneous Misadventures
M53 / core / effects.c
1
2
3
4#include <stdlib.h>
5#include "../mimimi.h"
6
7void mimimi_conveyor_tick(struct mimimi_conveyor *conveyor)
8{
9 struct mimimi_sprite *sprite;
10 struct mimimi_ground *ground;
11 unsigned char was_airborne;
12 int x1, x2, y;
13
14 sprite = conveyor->sprite;
15 ground = conveyor->ground;
16 was_airborne = conveyor->was_airborne;
17
18 conveyor->was_airborne = sprite->physics.airborne;
19
20 if (sprite->physics.airborne != 0) {
21 if (was_airborne == 0)
22 sprite->physics.dx += conveyor->speed;
23 return;
24 }
25
26 x1 = (sprite->position.x - sprite->physics.width / 2) / 128;
27 x2 = (sprite->position.x + sprite->physics.width / 2) / 128;
28 y = (sprite->position.y + 64) / 128;
29
30 if (mimimi_ground_tile(ground, x1, y) != 0
31 || mimimi_ground_tile(ground, x2, y) != 0)
32 sprite->position.x += conveyor->speed;
33}
34
35void mimimi_positioned_physics_tick(struct mimimi_positioned_physics
36 *physics, struct mimimi_ground *ground)
37{
38 int dx, dy;
39 unsigned char was_airborne;
40 struct mimimi_position other_position;
41 unsigned char airborne;
42
43 dx = physics->transform.x - physics->previous.x;
44 dy = physics->transform.y - physics->previous.y;
45
46 physics->previous = physics->transform;
47
48 was_airborne = physics->was_airborne;
49 physics->was_airborne = physics->other.airborne;
50
51 airborne = physics->physics->airborne;
52
53 physics->other.dx = physics->physics->dx;
54 physics->other.dy = physics->physics->dy;
55 physics->other.width = physics->physics->width;
56 physics->other.height = physics->physics->height;
57
58 other_position = *physics->position;
59 other_position.x -= physics->transform.x;
60 other_position.y -= physics->transform.y;
61
62 if (physics->other.airborne == 0) {
63 other_position.x += dx;
64 other_position.y += dy;
65 }
66
67 if (physics->physics->airborne != 0)
68 physics->other.airborne = 1;
69 mimimi_collision_physics_tick(&physics->other, &other_position, ground);
70 if (physics->other.airborne == 0)
71 physics->physics->airborne = 0;
72
73 if (airborne == 0)
74 return;
75
76 other_position.x += physics->transform.x;
77 other_position.y += physics->transform.y;
78
79 *physics->position = other_position;
80
81 physics->physics->dx = physics->other.dx;
82 physics->physics->dy = physics->other.dy;
83
84 if (physics->other.airborne != 0 && was_airborne == 0) {
85
86
87 }
88}
89
90void mimimi_positioned_physics(struct mimimi_positioned_physics *physics,
91 struct mimimi_physics *other, struct mimimi_position *position)
92{
93 mimimi_physics(&physics->other, 0, 0);
94 physics->other.sprite = other->sprite;
95 physics->physics = other;
96 physics->position = position;
97 physics->transform.x = 0;
98 physics->transform.y = 0;
99 physics->previous = *position;
100 physics->was_airborne = other->airborne;
101}
102
103void mimimi_trampoline_tick(struct mimimi_trampoline *trampoline)
104{
105 struct mimimi_sprite *sprite;
106 struct mimimi_ground *ground;
107 int dy;
108 int x1, x2, y;
109
110 sprite = trampoline->sprite;
111 ground = trampoline->ground;
112
113 dy = trampoline->dy;
114 trampoline->dy = 0;
115
116 if (sprite->physics.airborne != 0) {
117 trampoline->dy = sprite->physics.dy;
118 return;
119 }
120
121 if (dy == 0)
122 return;
123
124 x1 = (sprite->position.x - sprite->physics.width / 2) / 128;
125 x2 = (sprite->position.x + sprite->physics.width / 2) / 128;
126 y = (sprite->position.y + 64) / 128;
127
128 if (mimimi_ground_tile(ground, x1, y) != 0)
129 return;
130 if (mimimi_ground_tile(ground, x2, y) != 0)
131 return;
132
133 sprite->physics.airborne = 1;
134 sprite->physics.dy -= dy * trampoline->restitution / 256;
135}
136
137void mimimi_platform_display_tick(struct mimimi_platform *platform,
138 struct mimimi_position *camera, struct mimimi_image *image)
139{
140 mimimi_camera_stamp(image, camera, platform->physics.transform.x,
141 platform->physics.transform.y, 0, platform->image);
142}
143
144struct mimimi_platform_set *mimimi_add_platform_set(struct mimimi_stage
145 *stage)
146{
147 int i;
148 struct mimimi_platform_set *platforms;
149
150 if (stage->platform_set_count == 0)
151 stage->platform_sets = NULL;
152
153 i = stage->platform_set_count++;
154 stage->platform_sets =
155 realloc(stage->platform_sets,
156 sizeof *stage->platform_sets * stage->platform_set_count);
157 if (stage->platform_sets == NULL)
158 exit(1);
159
160 platforms = stage->platform_sets + i;
161
162 platforms->angular_platform_count = 0;
163 platforms->linear_platform_count = 0;
164 platforms->momentum.x = 0;
165 platforms->momentum.dx = 0;
166 platforms->balance = 0;
167 platforms->strength = 0;
168 platforms->linear_weight = 1024;
169 platforms->angular_weight = 1024;
170 platforms->min = -0x10000000;
171 platforms->max = 0x10000000;
172
173 return platforms;
174}
175
176void mimimi_spawn_linear_platform(struct mimimi_stage *stage,
177 struct mimimi_platform_set *platforms, struct mimimi_ground *ground,
178 struct mimimi_image *image, int x, int y, int scale)
179{
180 int i;
181
182 if (platforms->linear_platform_count == 0) {
183 platforms->linear_platforms = NULL;
184 platforms->linear_motions = NULL;
185 }
186
187 i = platforms->linear_platform_count++;
188 platforms->linear_platforms =
189 realloc(platforms->linear_platforms,
190 sizeof *platforms->linear_platforms *
191 platforms->linear_platform_count);
192 platforms->linear_motions =
193 realloc(platforms->linear_motions,
194 sizeof *platforms->linear_motions *
195 platforms->linear_platform_count);
196
197 if (platforms->linear_platforms == NULL)
198 exit(1);
199 if (platforms->linear_motions == NULL)
200 exit(1);
201
202 mimimi_positioned_physics(&platforms->linear_platforms[i].physics,
203 &stage->sprites[0].physics, &stage->sprites[0].position);
204 platforms->linear_platforms[i].ground = ground;
205 platforms->linear_platforms[i].image = image;
206
207 platforms->linear_platforms[i].physics.transform.x = x;
208 mimimi_linear_motion(platforms->linear_motions + i,
209 &platforms->linear_platforms[i].physics.transform.y, y, scale);
210 mimimi_linear_motion_apply(platforms->linear_motions + i,
211 &platforms->momentum);
212
213 for (i = 0; i < platforms->linear_platform_count; i++)
214 platforms->linear_motions[i].value =
215 &platforms->linear_platforms[i].physics.transform.y;
216}
217
218void mimimi_spawn_angular_platform(struct mimimi_stage *stage,
219 struct mimimi_platform_set *platforms, struct mimimi_ground *ground,
220 struct mimimi_image *image, int x, int y, int a, int scale, int height)
221{
222 int i;
223 struct mimimi_platform *platform;
224
225 if (platforms->angular_platform_count == 0) {
226 platforms->angular_platforms = NULL;
227 platforms->angular_motions = NULL;
228 }
229
230 i = platforms->angular_platform_count++;
231 platforms->angular_platforms =
232 realloc(platforms->angular_platforms,
233 sizeof *platforms->angular_platforms *
234 platforms->angular_platform_count);
235 platforms->angular_motions =
236 realloc(platforms->angular_motions,
237 sizeof *platforms->angular_motions *
238 platforms->angular_platform_count);
239
240 if (platforms->angular_platforms == NULL)
241 exit(1);
242 if (platforms->angular_motions == NULL)
243 exit(1);
244
245 platform = platforms->angular_platforms + i;
246
247 mimimi_positioned_physics(&platform->physics, &stage->sprites[0].physics,
248 &stage->sprites[0].position);
249 platform->ground = ground;
250 platform->image = image;
251
252 mimimi_angular_motion(platforms->angular_motions + i,
253 &platform->physics.transform, x, y, a, scale, height);
254 mimimi_angular_motion_apply(platforms->angular_motions + i,
255 &platforms->momentum);
256
257 for (i = 0; i < platforms->angular_platform_count; i++)
258 platforms->angular_motions[i].value =
259 &platforms->angular_platforms[i].physics.transform;
260}
261
262static void mimimi_platforms_propagate(struct mimimi_platform_set *platforms)
263{
264 int i;
265 for (i = 0; i < platforms->linear_platform_count; i++)
266 if (platforms->linear_platforms[i].physics.other.airborne == 0)
267 mimimi_linear_motion_propagate(platforms->linear_motions + i,
268 &platforms->momentum);
269 for (i = 0; i < platforms->angular_platform_count; i++)
270 if (platforms->angular_platforms[i].physics.other.airborne == 0)
271 mimimi_angular_motion_propagate(platforms->angular_motions + i,
272 &platforms->momentum);
273}
274
275static void mimimi_platforms_apply(struct mimimi_platform_set *platforms)
276{
277 int i;
278 for (i = 0; i < platforms->linear_platform_count; i++)
279 mimimi_linear_motion_apply(platforms->linear_motions + i,
280 &platforms->momentum);
281 for (i = 0; i < platforms->angular_platform_count; i++)
282 mimimi_angular_motion_apply(platforms->angular_motions + i,
283 &platforms->momentum);
284}
285
286void mimimi_platform_set_tick(struct mimimi_platform_set *platforms)
287{
288 int i;
289 int diff;
290
291 for (i = 0; i < platforms->linear_platform_count; i++)
292 if (platforms->linear_platforms[i].physics.other.airborne == 0)
293 platforms->linear_platforms[i].physics.transform.y +=
294 platforms->linear_weight;
295
296 for (i = 0; i < platforms->angular_platform_count; i++)
297 if (platforms->angular_platforms[i].physics.other.airborne == 0)
298 platforms->angular_platforms[i].physics.transform.y +=
299 platforms->angular_weight *
300 platforms->angular_motions[i].height / 2048;
301
302 mimimi_platforms_propagate(platforms);
303
304 platforms->momentum.dx *= 31;
305 platforms->momentum.dx /= 32;
306 platforms->momentum.x += platforms->momentum.dx / 256;
307
308 if (platforms->momentum.x < platforms->min) {
309 platforms->momentum.x = platforms->min;
310 platforms->momentum.dx = 0;
311 }
312 if (platforms->momentum.x > platforms->max) {
313 platforms->momentum.x = platforms->max;
314 platforms->momentum.dx = 0;
315 }
316
317 mimimi_platforms_apply(platforms);
318
319 for (i = 0; i < platforms->linear_platform_count; i++)
320 mimimi_positioned_physics_tick(&platforms->linear_platforms[i].
321 physics, platforms->linear_platforms[i].ground);
322 for (i = 0; i < platforms->angular_platform_count; i++)
323 mimimi_positioned_physics_tick(&platforms->angular_platforms[i].
324 physics, platforms->angular_platforms[i].ground);
325
326 diff = platforms->balance - platforms->momentum.x;
327 platforms->momentum.dx += platforms->strength * diff / 256;
328}
329
330void mimimi_platform_set_display_tick(struct mimimi_platform_set
331 *platforms, struct mimimi_image *image, struct mimimi_position *camera)
332{
333 int i;
334 for (i = 0; i < platforms->linear_platform_count; i++)
335 mimimi_platform_display_tick(platforms->linear_platforms + i,
336 camera, image);
337 for (i = 0; i < platforms->angular_platform_count; i++)
338 mimimi_platform_display_tick(platforms->angular_platforms + i,
339 camera, image);
340}