Mirai's Miscellaneous Misadventures
M41 / 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
22 data->history->left <<= 1;
23 data->history->left |= data->chapter->left;
24 data->history->left &= 0xFFFF;
25
26 data->history->right <<= 1;
27 data->history->right |= data->chapter->right;
28 data->history->right &= 0xFFFF;
29}
30
31static void mimimi_history_finish(void *data)
32{
33 struct mimimi_history_data *history_data = data;
34 mimimi_deallocate(history_data->allocator, history_data->behavior);
35 mimimi_deallocate(history_data->allocator, history_data);
36}
37
38struct mimimi_behavior *mimimi_history(struct mimimi_history *history, struct mimimi_chapter *chapter, struct mimimi_allocator *allocator)
39{
40 struct mimimi_history_data *data = mimimi_allocate(allocator, sizeof *data);
41 data->allocator = allocator;
42 data->history = history;
43 data->chapter = chapter;
44
45 history->left = 0;
46 history->right = 0;
47
48 data->behavior = mimimi_allocate(allocator, sizeof *data->behavior);
49 data->behavior->behave = &mimimi_history_behave;
50 data->behavior->finish = &mimimi_history_finish;
51 data->behavior->data = data;
52
53 return data->behavior;
54}
55
56struct mimimi_controls_data
57{
58 struct mimimi_allocator *allocator;
59 struct mimimi_behavior *behavior;
60 struct mimimi_controls *controls;
61 struct mimimi_walk *walk;
62 struct mimimi_history *history;
63};
64
65static unsigned char mimimi_count_oscillations(unsigned int history)
66{
67 unsigned char count = 0;
68 unsigned char prev = history&1;
69 for (int i = 0 ; i < 16 ; i++)
70 {
71 if ((history&1) != prev) count++;
72 prev = history&1;
73 history >>= 1;
74 }
75 return count;
76}
77
78static void mimimi_control(void *data)
79{
80 struct mimimi_controls_data *controls_data = data;
81
82 struct mimimi_walk *walk = controls_data->walk;
83 struct mimimi_history *history = controls_data->history;
84
85 struct mimimi_behavior *jump = controls_data->controls->jump;
86
87 unsigned char left_oscillations = mimimi_count_oscillations(history->left);
88 unsigned char right_oscillations = mimimi_count_oscillations(history->right);
89
90 switch (walk->direction)
91 {
92 case 0:
93 if ((history->left&1) != 0)
94 {
95 walk->direction = 1;
96 if (left_oscillations > 1 && (history->left&2) == 0)
97 (*jump->behave)(jump->data);
98 }
99 if ((history->right&1) != 0)
100 {
101 walk->direction = 2;
102 if (right_oscillations > 1 && (history->right&2) == 0)
103 (*jump->behave)(jump->data);
104 }
105 break;
106 case 1:
107 if ((history->left&1) == 0)
108 walk->direction = 0;
109 break;
110 case 2:
111 if ((history->right&1) == 0)
112 walk->direction = 0;
113 break;
114 }
115}
116
117static void mimimi_controls_finish(void *data)
118{
119 struct mimimi_controls_data *controls_data = data;
120 mimimi_deallocate(controls_data->allocator, controls_data->behavior);
121 mimimi_deallocate(controls_data->allocator, controls_data);
122}
123
124struct mimimi_behavior *mimimi_controls(struct mimimi_controls *controls, struct mimimi_walk *walk, struct mimimi_history *history, struct mimimi_allocator *allocator)
125{
126 struct mimimi_controls_data *data = mimimi_allocate(allocator, sizeof *data);
127 data->allocator = allocator;
128 data->controls = controls;
129 data->walk = walk;
130 data->history = history;
131
132 controls->jump = mimimi_noop;
133
134 data->behavior = mimimi_allocate(allocator, sizeof *data->behavior);
135 data->behavior->behave = &mimimi_control;
136 data->behavior->finish = &mimimi_controls_finish;
137 data->behavior->data = data;
138
139 return data->behavior;
140}
141
142struct mimimi_stationary
143{
144 struct mimimi_allocator *allocator;
145 struct mimimi_behavior *behavior;
146 int *direction;
147 int *position;
148 int *target;
149};
150
151static void mimimi_stationary_behave(void *data)
152{
153 struct mimimi_stationary *stationary = data;
154 if (*stationary->position < *stationary->target)
155 *stationary->direction = 1;
156 else
157 *stationary->direction = 2;
158}
159
160static void mimimi_stationary_finish(void *data)
161{
162 struct mimimi_stationary *stationary = data;
163 mimimi_deallocate(stationary->allocator, stationary->behavior);
164 mimimi_deallocate(stationary->allocator, stationary);
165}
166
167struct mimimi_behavior *mimimi_stationary(int *direction, int *position, int *target, struct mimimi_allocator *allocator)
168{
169 struct mimimi_stationary *data = mimimi_allocate(allocator, sizeof *data);
170 data->allocator = allocator;
171 data->direction = direction;
172 data->position = position;
173 data->target = target;
174
175 data->behavior = mimimi_allocate(allocator, sizeof *data->behavior);
176 data->behavior->behave = &mimimi_stationary_behave;
177 data->behavior->finish = &mimimi_stationary_finish;
178 data->behavior->data = data;
179
180 return data->behavior;
181}