Mirai's Miscellaneous Misadventures
M32 / core / controls.c
1
2
3
4#include <mimimi/controls.h>
5#include <mimimi/behaviors.h>
6#include <mimimi/allocators.h>
7#include <mimimi/sprites.h>
8#include <mimimi/chapters.h>
9
10struct mimimi_history_data
11{
12 struct mimimi_allocator *allocator;
13 struct mimimi_behavior *behavior;
14 struct mimimi_history *history;
15 struct mimimi_chapter *chapter;
16};
17
18static void mimimi_history_behave(void *data0)
19{
20 struct mimimi_history_data *data = data0;
21 data->history->left <<= 1;
22 data->history->left |= data->chapter->left;
23 data->history->right <<= 1;
24 data->history->right |= data->chapter->right;
25}
26
27static void mimimi_history_finish(void *data)
28{
29 struct mimimi_history_data *history_data = data;
30 mimimi_deallocate(history_data->allocator,history_data->behavior);
31 mimimi_deallocate(history_data->allocator,history_data);
32}
33
34struct mimimi_behavior *mimimi_history(struct mimimi_history *history, struct mimimi_chapter *chapter, struct mimimi_allocator *allocator)
35{
36 struct mimimi_history_data *data = mimimi_allocate(allocator, sizeof *data);
37 data->allocator = allocator;
38 data->history = history;
39 data->chapter = chapter;
40
41 history->left = 0;
42 history->right = 0;
43
44 data->behavior = mimimi_allocate(allocator, sizeof *data->behavior);
45 data->behavior->behave = &mimimi_history_behave;
46 data->behavior->finish = &mimimi_history_finish;
47 data->behavior->data = data;
48
49 return data->behavior;
50}
51
52struct mimimi_controls_data
53{
54 struct mimimi_allocator *allocator;
55 struct mimimi_behavior *behavior;
56 struct mimimi_controls *controls;
57 struct mimimi_walk *walk;
58 struct mimimi_history *history;
59};
60
61static unsigned char mimimi_count_oscillations(unsigned int history)
62{
63 unsigned char count = 0;
64 unsigned char prev = history&1;
65 for (int i = 0 ; i < 16 ; i++)
66 {
67 if ((history&1) != prev) count++;
68 prev = history&1;
69 history >>= 1;
70 }
71 return count;
72}
73
74static void mimimi_control(void *data)
75{
76 struct mimimi_controls_data *controls_data = data;
77
78 struct mimimi_walk *walk = controls_data->walk;
79 struct mimimi_history *history = controls_data->history;
80
81 struct mimimi_behavior *jump = controls_data->controls->jump;
82
83 unsigned char left_oscillations = mimimi_count_oscillations(history->left);
84 unsigned char right_oscillations = mimimi_count_oscillations(history->right);
85
86 switch (walk->direction)
87 {
88 case 0:
89 if ((history->left&1) != 0)
90 {
91 walk->direction = 1;
92 if (left_oscillations > 1 && (history->left&2) == 0)
93 (*jump->behave)(jump->data);
94 }
95 if ((history->right&1) != 0)
96 {
97 walk->direction = 2;
98 if (right_oscillations > 1 && (history->right&2) == 0)
99 (*jump->behave)(jump->data);
100 }
101 break;
102 case 1:
103 if ((history->left&1) == 0)
104 walk->direction = 0;
105 break;
106 case 2:
107 if ((history->right&1) == 0)
108 walk->direction = 0;
109 break;
110 }
111}
112
113static void mimimi_controls_finish(void *data)
114{
115 struct mimimi_controls_data *controls_data = data;
116 mimimi_deallocate(controls_data->allocator, controls_data->behavior);
117 mimimi_deallocate(controls_data->allocator, controls_data);
118}
119
120struct mimimi_behavior *mimimi_controls(struct mimimi_controls *controls, struct mimimi_walk *walk, struct mimimi_history *history, struct mimimi_allocator *allocator)
121{
122 struct mimimi_controls_data *data = mimimi_allocate(allocator, sizeof *data);
123 data->allocator = allocator;
124 data->controls = controls;
125 data->walk = walk;
126 data->history = history;
127
128 controls->jump = mimimi_noop;
129
130 data->behavior = mimimi_allocate(allocator, sizeof *data->behavior);
131 data->behavior->behave = &mimimi_control;
132 data->behavior->finish = &mimimi_controls_finish;
133 data->behavior->data = data;
134
135 return data->behavior;
136}
137
138struct mimimi_jump_data
139{
140 struct mimimi_allocator *allocator;
141 struct mimimi_behavior *behavior;
142 struct mimimi_jump *jump;
143 struct mimimi_physics *physics;
144};
145
146static void mimimi_jump_behave(void *data)
147{
148 struct mimimi_jump_data *jump_data = data;
149 jump_data->physics->airborne = 1;
150 jump_data->physics->dy = -jump_data->jump->strength;
151}
152
153static void mimimi_jump_finish(void *data)
154{
155 struct mimimi_jump_data *jump_data = data;
156 mimimi_deallocate(jump_data->allocator, jump_data->behavior);
157 mimimi_deallocate(jump_data->allocator, jump_data);
158}
159
160struct mimimi_behavior *mimimi_jump(struct mimimi_jump *jump, struct mimimi_physics *physics, struct mimimi_allocator *allocator)
161{
162 struct mimimi_jump_data *data = mimimi_allocate(allocator, sizeof *data);
163 data->allocator = allocator;
164 data->jump = jump;
165 data->physics = physics;
166
167 jump->strength = 56;
168
169 data->behavior = mimimi_allocate(allocator, sizeof *data->behavior);
170 data->behavior->behave = &mimimi_jump_behave;
171 data->behavior->finish = &mimimi_jump_finish;
172 data->behavior->data = data;
173
174 return data->behavior;
175}
176
177struct mimimi_dash_data
178{
179 struct mimimi_allocator *allocator;
180 struct mimimi_behavior *behavior;
181 struct mimimi_dash *dash;
182 struct mimimi_physics *physics;
183 struct mimimi_walk *walk;
184};
185
186static void mimimi_dash_behave(void *data)
187{
188 struct mimimi_dash_data *dash_data = data;
189 if (dash_data->walk->direction == 1)
190 dash_data->physics->dx -= dash_data->dash->x_strength;
191 if (dash_data->walk->direction == 2)
192 dash_data->physics->dx += dash_data->dash->x_strength;
193 dash_data->physics->dy -= dash_data->dash->y_strength;
194}
195
196static void mimimi_dash_finish(void *data)
197{
198 struct mimimi_dash_data *dash_data = data;
199 mimimi_deallocate(dash_data->allocator, dash_data->behavior);
200 mimimi_deallocate(dash_data->allocator, dash_data);
201}
202
203struct mimimi_behavior *mimimi_dash(struct mimimi_dash *dash, struct mimimi_physics *physics, struct mimimi_walk *walk, struct mimimi_allocator *allocator)
204{
205 struct mimimi_dash_data *data = mimimi_allocate(allocator, sizeof *data);
206 data->allocator = allocator;
207 data->dash = dash;
208 data->physics = physics;
209 data->walk = walk;
210
211 dash->x_strength = 32;
212 dash->y_strength = 16;
213
214 data->behavior = mimimi_allocate(allocator, sizeof *data->behavior);
215 data->behavior->behave = &mimimi_dash_behave;
216 data->behavior->finish = &mimimi_dash_finish;
217 data->behavior->data = data;
218
219 return data->behavior;
220}
221
222struct mimimi_stationary
223{
224 struct mimimi_allocator *allocator;
225 struct mimimi_behavior *behavior;
226 int *direction;
227 int *position;
228 int *target;
229};
230
231static void mimimi_stationary_behave(void *data)
232{
233 struct mimimi_stationary *stationary = data;
234 if (*stationary->position > *stationary->target)
235 *stationary->direction = 1;
236 else
237 *stationary->direction = 2;
238}
239
240static void mimimi_stationary_finish(void *data)
241{
242 struct mimimi_stationary *stationary = data;
243 mimimi_deallocate(stationary->allocator, stationary->behavior);
244 mimimi_deallocate(stationary->allocator, stationary);
245}
246
247struct mimimi_behavior *mimimi_stationary(int *direction, int *position, int *target, struct mimimi_allocator *allocator)
248{
249 struct mimimi_stationary *data = mimimi_allocate(allocator, sizeof *data);
250 data->allocator = allocator;
251 data->direction = direction;
252 data->position = position;
253 data->target = target;
254
255 data->behavior = mimimi_allocate(allocator, sizeof *data->behavior);
256 data->behavior->behave = &mimimi_stationary_behave;
257 data->behavior->finish = &mimimi_stationary_finish;
258 data->behavior->data = data;
259
260 return data->behavior;
261}