Mirai's Miscellaneous Misadventures
M41 / core / effects.c
1
2
3
4#include <mimimi/ground.h>
5#include <mimimi/behaviors.h>
6#include <mimimi/sprites.h>
7#include <mimimi/allocators.h>
8#include <mimimi/geometry.h>
9#include <mimimi/compound-behaviors.h>
10
11struct mimimi_conveyor
12{
13 struct mimimi_sprite *sprite;
14 struct mimimi_ground *ground;
15 unsigned char which;
16 int speed;
17 unsigned char was_airborne;
18};
19
20static void mimimi_conveyor_behave(void *data)
21{
22 struct mimimi_conveyor *conveyor_data = data;
23 struct mimimi_sprite *sprite = conveyor_data->sprite;
24 struct mimimi_ground *ground = conveyor_data->ground;
25 unsigned char was_airborne = conveyor_data->was_airborne;
26 conveyor_data->was_airborne = sprite->physics->airborne;
27
28 if (sprite->physics->airborne != 0)
29 {
30 if (was_airborne == 0)
31 sprite->physics->dx += conveyor_data->speed;
32 return;
33 }
34
35 int x1 = (sprite->position->x - sprite->physics->width / 2) / 128;
36 int x2 = (sprite->position->x + sprite->physics->width / 2) / 128;
37 int y = (sprite->position->y + 64) / 128;
38
39 if (mimimi_ground_tile(ground, x1, y) == conveyor_data->which || mimimi_ground_tile(ground, x2, y) == conveyor_data->which)
40 sprite->position->x += conveyor_data->speed;
41}
42
43struct mimimi_behavior *mimimi_conveyor(struct mimimi_sprite *sprite, struct mimimi_ground *ground, unsigned char which, int speed, struct mimimi_allocator *allocator)
44{
45 struct mimimi_behavior *compound = mimimi_compound_behavior(allocator);
46
47 struct mimimi_conveyor *conveyor = mimimi_compound_allocate(compound, sizeof *conveyor, allocator);
48 conveyor->sprite = sprite;
49 conveyor->ground = ground;
50 conveyor->which = which;
51 conveyor->speed = speed;
52 conveyor->was_airborne = sprite->physics->airborne;
53
54 mimimi_compound(compound, mimimi_function(conveyor, &mimimi_conveyor_behave, allocator));
55
56 return compound;
57}
58
59struct mimimi_transformed_physics
60{
61 struct mimimi_physics *physics;
62 struct mimimi_position *position;
63 struct mimimi_ground *ground;
64 struct mimimi_physics *other;
65 struct mimimi_behavior *behavior;
66 struct mimimi_position *transform;
67 struct mimimi_position previous;
68 struct mimimi_position other_position;
69 unsigned char was_airborne;
70};
71
72static void mimimi_transformed_physics_behave(void *data)
73{
74 struct mimimi_transformed_physics *physics = data;
75
76 int dx = physics->transform->x - physics->previous.x;
77 int dy = physics->transform->y - physics->previous.y;
78 physics->previous = *physics->transform;
79
80 unsigned char was_airborne = physics->was_airborne;
81 physics->was_airborne = physics->other->airborne;
82
83 physics->other->dx = physics->physics->dx;
84 physics->other->dy = physics->physics->dy;
85 physics->other->width = physics->physics->width;
86 physics->other->height = physics->physics->height;
87 physics->other->gravity = 0;
88
89 physics->other_position = *physics->position;
90 physics->other_position.x -= physics->transform->x;
91 physics->other_position.y -= physics->transform->y;
92
93 if (physics->other->airborne == 0)
94 {
95 physics->other_position.x += dx;
96 physics->other_position.y += dy;
97 }
98
99 if (physics->physics->airborne != 0) physics->other->airborne = 1;
100
101 (*physics->behavior->behave)(physics->behavior->data);
102
103 if (physics->other->airborne == 0) physics->physics->airborne = 0;
104
105 *physics->position = physics->other_position;
106 physics->position->x += physics->transform->x;
107 physics->position->y += physics->transform->y;
108
109 physics->physics->dx = physics->other->dx;
110 physics->physics->dy = physics->other->dy;
111
112 if (physics->other->airborne != 0 && was_airborne == 0)
113 {
114 physics->physics->dx += dx;
115 physics->physics->dy += dy;
116 }
117}
118
119struct mimimi_behavior *mimimi_positioned_physics(struct mimimi_physics *other, struct mimimi_position *position, struct mimimi_ground *ground, struct mimimi_position *transform, struct mimimi_allocator *allocator)
120{
121 struct mimimi_behavior *compound = mimimi_compound_behavior(allocator);
122
123 struct mimimi_transformed_physics *physics = mimimi_compound_allocate(compound, sizeof *physics, allocator);
124 physics->physics = other;
125 physics->position = position;
126 physics->ground = ground;
127 physics->other = mimimi_compound_allocate(compound, sizeof *physics->other, allocator);
128 physics->behavior = mimimi_collision_physics(physics->other, &physics->other_position, ground, allocator);
129 physics->transform = transform;
130 physics->previous = *transform;
131 physics->was_airborne = other->airborne;
132
133 mimimi_compound(compound, mimimi_function(physics, &mimimi_transformed_physics_behave, allocator));
134 mimimi_compound(compound, mimimi_finalizer(physics->behavior->data, physics->behavior->finish, allocator));
135
136 return compound;
137}
138
139struct mimimi_trampoline
140{
141 struct mimimi_sprite *sprite;
142 struct mimimi_ground *ground;
143 unsigned char which;
144 int restitution;
145 int dy;
146};
147
148static void mimimi_trampoline_behave(void *data)
149{
150 struct mimimi_trampoline *trampoline_data = data;
151 struct mimimi_sprite *sprite = trampoline_data->sprite;
152 struct mimimi_ground *ground = trampoline_data->ground;
153 int dy = trampoline_data->dy;
154 trampoline_data->dy = 0;
155
156 if (sprite->physics->airborne != 0)
157 {
158 trampoline_data->dy = sprite->physics->dy;
159 return;
160 }
161
162 if (dy == 0) return;
163
164 int x1 = (sprite->position->x - sprite->physics->width / 2) / 128;
165 int x2 = (sprite->position->x + sprite->physics->width / 2) / 128;
166 int y = (sprite->position->y + 64) / 128;
167
168 if (mimimi_ground_tile(ground, x1, y) != trampoline_data->which) return;
169 if (mimimi_ground_tile(ground, x2, y) != trampoline_data->which) return;
170
171 sprite->physics->airborne = 1;
172 sprite->physics->dy -= dy * trampoline_data->restitution / 256;
173}
174
175struct mimimi_behavior *mimimi_trampoline(struct mimimi_sprite *sprite, struct mimimi_ground *ground, unsigned char which, int restitution, struct mimimi_allocator *allocator)
176{
177 struct mimimi_behavior *compound = mimimi_compound_behavior(allocator);
178
179 struct mimimi_trampoline *trampoline = mimimi_compound_allocate(compound, sizeof *trampoline, allocator);
180 trampoline->sprite = sprite;
181 trampoline->ground = ground;
182 trampoline->which = which;
183 trampoline->restitution = restitution;
184 trampoline->dy = sprite->physics->dy;
185
186 mimimi_compound(compound, mimimi_function(trampoline, &mimimi_trampoline_behave, allocator));
187
188 return compound;
189}