Mirai's Miscellaneous Misadventures
M50 / core / effects.c
1
2
3
4#include <stdlib.h>
5
6#include <mimimi.h>
7
8void mimimi_conveyor_tick(struct mimimi_conveyor *conveyor)
9{
10 struct mimimi_sprite *sprite;
11 struct mimimi_ground *ground;
12 unsigned char was_airborne;
13 int x1, x2, y;
14
15 sprite = conveyor->sprite;
16 ground = conveyor->ground;
17 was_airborne = conveyor->was_airborne;
18
19 conveyor->was_airborne = sprite->physics.airborne;
20
21 if (sprite->physics.airborne != 0)
22 {
23 if (was_airborne == 0)
24 sprite->physics.dx += conveyor->speed;
25 return;
26 }
27
28 x1 = (sprite->position.x - sprite->physics.width / 2) / 128;
29 x2 = (sprite->position.x + sprite->physics.width / 2) / 128;
30 y = (sprite->position.y + 64) / 128;
31
32 if (mimimi_ground_tile(ground, x1, y) != 0 || mimimi_ground_tile(ground, x2, y) != 0)
33 sprite->position.x += conveyor->speed;
34}
35
36void mimimi_positioned_physics_tick(struct mimimi_positioned_physics *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 {
64 other_position.x += dx;
65 other_position.y += dy;
66 }
67
68 if (physics->physics->airborne != 0) physics->other.airborne = 1;
69 mimimi_collision_physics_tick(&physics->other, &other_position, ground);
70 if (physics->other.airborne == 0) physics->physics->airborne = 0;
71
72 if (airborne == 0) return;
73
74 other_position.x += physics->transform.x;
75 other_position.y += physics->transform.y;
76
77 *physics->position = other_position;
78
79 physics->physics->dx = physics->other.dx;
80 physics->physics->dy = physics->other.dy;
81
82 if (physics->other.airborne != 0 && was_airborne == 0)
83 {
84
85
86 }
87}
88
89void mimimi_positioned_physics(struct mimimi_positioned_physics *physics, struct mimimi_physics *other, struct mimimi_position *position)
90{
91 mimimi_physics(&physics->other, 0, 0);
92 physics->physics = other;
93 physics->position = position;
94 physics->transform.x = 0;
95 physics->transform.y = 0;
96 physics->previous = *position;
97 physics->was_airborne = other->airborne;
98}
99
100void mimimi_trampoline_tick(struct mimimi_trampoline *trampoline)
101{
102 struct mimimi_sprite *sprite;
103 struct mimimi_ground *ground;
104 int dy;
105 int x1, x2, y;
106
107 sprite = trampoline->sprite;
108 ground = trampoline->ground;
109
110 dy = trampoline->dy;
111 trampoline->dy = 0;
112
113 if (sprite->physics.airborne != 0)
114 {
115 trampoline->dy = sprite->physics.dy;
116 return;
117 }
118
119 if (dy == 0) return;
120
121 x1 = (sprite->position.x - sprite->physics.width / 2) / 128;
122 x2 = (sprite->position.x + sprite->physics.width / 2) / 128;
123 y = (sprite->position.y + 64) / 128;
124
125 if (mimimi_ground_tile(ground, x1, y) != 0) return;
126 if (mimimi_ground_tile(ground, x2, y) != 0) return;
127
128 sprite->physics.airborne = 1;
129 sprite->physics.dy -= dy * trampoline->restitution / 256;
130}
131
132void mimimi_platform_display_tick(struct mimimi_platform *platform, struct mimimi_position *camera, int x, int y, struct mimimi_engine *engine)
133{
134 mimimi_camera_stamp(engine, camera, platform->physics.transform.x - x, platform->physics.transform.y - y, 0, platform->texture);
135}
136
137struct mimimi_platform_set *mimimi_add_platform_set(struct mimimi_stage *stage)
138{
139 int i;
140 struct mimimi_platform_set *platforms;
141
142 if (stage->platform_set_count == 0)
143 stage->platform_sets = NULL;
144
145 i = stage->platform_set_count++;
146 stage->platform_sets = realloc(stage->platform_sets, sizeof *stage->platform_sets * stage->platform_set_count);
147
148 platforms = stage->platform_sets + i;
149
150 platforms->angular_platform_count = 0;
151 platforms->linear_platform_count = 0;
152 platforms->momentum.x = 0;
153 platforms->momentum.dx = 0;
154 platforms->balance = 0;
155 platforms->strength = 0;
156 platforms->linear_weight = 0;
157 platforms->angular_weight = 1024;
158 platforms->min = -0x10000000;
159 platforms->max = 0x10000000;
160
161 return platforms;
162}
163
164void mimimi_spawn_linear_platform(struct mimimi_stage *stage, struct mimimi_platform_set *platforms, struct mimimi_ground *ground, void *texture, int x, int y, int scale)
165{
166 int i;
167
168 if (platforms->linear_platform_count == 0)
169 {
170 platforms->linear_platforms = NULL;
171 platforms->linear_motions = NULL;
172 }
173
174 i = platforms->linear_platform_count++;
175 platforms->linear_platforms = realloc(platforms->linear_platforms, sizeof *platforms->linear_platforms * platforms->linear_platform_count);
176 platforms->linear_motions = realloc(platforms->linear_motions, sizeof *platforms->linear_motions * platforms->linear_platform_count);
177
178 mimimi_positioned_physics(&platforms->linear_platforms[i].physics, &stage->sprites[0].physics, &stage->sprites[0].position);
179 platforms->linear_platforms[i].ground = ground;
180 platforms->linear_platforms[i].texture = texture;
181
182 platforms->linear_platforms[i].physics.transform.x = x;
183 mimimi_linear_motion(platforms->linear_motions + i, &platforms->linear_platforms[i].physics.transform.y, y, scale);
184 mimimi_linear_motion_apply(platforms->linear_motions + i, &platforms->momentum);
185
186 for (i = 0 ; i < platforms->linear_platform_count ; i++)
187 platforms->linear_motions[i].value = &platforms->linear_platforms[i].physics.transform.y;
188}
189
190void mimimi_spawn_angular_platform(struct mimimi_stage *stage, struct mimimi_platform_set *platforms, struct mimimi_ground *ground, void *texture, int x, int y, int a, int scale, int height)
191{
192 int i;
193
194 if (platforms->angular_platform_count == 0)
195 {
196 platforms->angular_platforms = NULL;
197 platforms->angular_motions = NULL;
198 }
199
200 i = platforms->angular_platform_count++;
201 platforms->angular_platforms = realloc(platforms->angular_platforms, sizeof *platforms->angular_platforms * platforms->angular_platform_count);
202 platforms->angular_motions = realloc(platforms->angular_motions, sizeof *platforms->angular_motions * platforms->angular_platform_count);
203
204 mimimi_positioned_physics(&platforms->angular_platforms[i].physics, &stage->sprites[0].physics, &stage->sprites[0].position);
205 platforms->angular_platforms[i].ground = ground;
206 platforms->angular_platforms[i].texture = texture;
207
208 mimimi_angular_motion(platforms->angular_motions + i, &platforms->angular_platforms[i].physics.transform, x, y, a, scale, height);
209 mimimi_angular_motion_apply(platforms->angular_motions + i, &platforms->momentum);
210
211 for (i = 0 ; i < platforms->angular_platform_count ; i++)
212 platforms->angular_motions[i].value = &platforms->angular_platforms[i].physics.transform;
213}
214
215static void mimimi_platforms_propagate(struct mimimi_platform_set *platforms)
216{
217 int i;
218 for (i = 0 ; i < platforms->linear_platform_count ; i++)
219 if (platforms->linear_platforms[i].physics.other.airborne == 0)
220 mimimi_linear_motion_propagate(platforms->linear_motions + i, &platforms->momentum);
221 for (i = 0 ; i < platforms->angular_platform_count ; i++)
222 if (platforms->angular_platforms[i].physics.other.airborne == 0)
223 mimimi_angular_motion_propagate(platforms->angular_motions + i, &platforms->momentum);
224}
225
226static void mimimi_platforms_apply(struct mimimi_platform_set *platforms)
227{
228 int i;
229 for (i = 0 ; i < platforms->linear_platform_count ; i++)
230 mimimi_linear_motion_apply(platforms->linear_motions + i, &platforms->momentum);
231 for (i = 0 ; i < platforms->angular_platform_count ; i++)
232 mimimi_angular_motion_apply(platforms->angular_motions + i, &platforms->momentum);
233}
234
235void mimimi_platform_set_tick(struct mimimi_platform_set *platforms)
236{
237 int i;
238 int diff;
239
240 for (i = 0 ; i < platforms->linear_platform_count ; i++)
241 if (platforms->linear_platforms[i].physics.other.airborne == 0)
242 platforms->linear_platforms[i].physics.transform.y += platforms->linear_weight;
243
244 for (i = 0 ; i < platforms->angular_platform_count ; i++)
245 if (platforms->angular_platforms[i].physics.other.airborne == 0)
246 platforms->angular_platforms[i].physics.transform.y += platforms->angular_weight * platforms->angular_motions[i].height / 2048;
247
248 mimimi_platforms_propagate(platforms);
249
250 if (platforms->momentum.x < platforms->min)
251 {
252 platforms->momentum.x = platforms->min;
253 platforms->momentum.dx = 0;
254 }
255 if (platforms->momentum.x > platforms->max)
256 {
257 platforms->momentum.x = platforms->max;
258 platforms->momentum.dx = 0;
259 }
260
261 platforms->momentum.dx *= 31;
262 platforms->momentum.dx /= 32;
263 platforms->momentum.x += platforms->momentum.dx / 256;
264
265 mimimi_platforms_apply(platforms);
266
267 for (i = 0 ; i < platforms->linear_platform_count ; i++)
268 mimimi_positioned_physics_tick(&platforms->linear_platforms[i].physics, platforms->linear_platforms[i].ground);
269 for (i = 0 ; i < platforms->angular_platform_count ; i++)
270 mimimi_positioned_physics_tick(&platforms->angular_platforms[i].physics, platforms->angular_platforms[i].ground);
271
272 diff = platforms->balance - platforms->momentum.x;
273 platforms->momentum.dx += platforms->strength * diff / 256;
274}
275
276void mimimi_platform_set_display_tick(struct mimimi_platform_set *platforms, struct mimimi_engine *engine, struct mimimi_position *camera)
277{
278 int i;
279 for (i = 0 ; i < platforms->linear_platform_count ; i++)
280 mimimi_platform_display_tick(platforms->linear_platforms + i, camera, 0, 0, engine);
281 for (i = 0 ; i < platforms->angular_platform_count ; i++)
282 mimimi_platform_display_tick(platforms->angular_platforms + i, camera, 0, 0, engine);
283}