Mirai's Miscellaneous Misadventures

M20 / core / controls.c

1// copyright 2022 zamfofex
2// license: AGPLv3 or later
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	(*history_data->allocator->deallocate)(history_data->behavior);
31	(*history_data->allocator->deallocate)(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 = (*allocator->allocate)(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 = (*allocator->allocate)(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			walk->direction = 1;
91		if ((history->right&1) != 0)
92			walk->direction = 2;
93		break;
94	case 1:
95		if ((history->left&1) == 0)
96			walk->direction = 0;
97		else if (left_oscillations > 1)
98			(*jump->behave)(jump->data);
99		
100		if ((history->right&1) != 0)
101		{
102			if (right_oscillations == 0)
103			{
104				// rapid attack
105			}
106		}
107		if ((history->right&1) != 0 && (history->right&2) == 0)
108		{
109			// attack
110		}
111		break;
112	case 2:
113		if ((history->right&1) == 0)
114			walk->direction = 0;
115		else if (right_oscillations > 1)
116			(*jump->behave)(jump->data);
117		
118		if ((history->left&1) != 0)
119		{
120			if (left_oscillations == 0)
121			{
122				// rapid attack
123			}
124		}
125		if ((history->left&1) != 0 && (history->left&2) == 0)
126		{
127			// attack
128		}
129		break;
130	}
131}
132
133static void mimimi_controls_finish(void *data)
134{
135	struct mimimi_controls_data *controls_data = data;
136	(*controls_data->allocator->deallocate)(controls_data->behavior);
137	(*controls_data->allocator->deallocate)(controls_data);
138}
139
140struct mimimi_behavior *mimimi_controls(struct mimimi_controls *controls, struct mimimi_walk *walk, struct mimimi_history *history, struct mimimi_allocator *allocator)
141{
142	struct mimimi_controls_data *data = (*allocator->allocate)(sizeof *data);
143	data->allocator = allocator;
144	data->controls = controls;
145	data->walk = walk;
146	data->history = history;
147	
148	controls->jump = mimimi_noop;
149	
150	data->behavior = (*allocator->allocate)(sizeof *data->behavior);
151	data->behavior->behave = &mimimi_control;
152	data->behavior->finish = &mimimi_controls_finish;
153	data->behavior->data = data;
154	
155	return data->behavior;
156}
157
158struct mimimi_jump_data
159{
160	struct mimimi_allocator *allocator;
161	struct mimimi_behavior *behavior;
162	struct mimimi_jump *jump;
163	struct mimimi_physics *physics;
164};
165
166static void mimimi_jump_behave(void *data)
167{
168	struct mimimi_jump_data *jump_data = data;
169	if (jump_data->physics->airborne == 0)
170	{
171		jump_data->physics->airborne = 1;
172		jump_data->physics->dy = -jump_data->jump->strength;
173	}
174}
175
176static void mimimi_jump_finish(void *data)
177{
178	struct mimimi_jump_data *jump_data = data;
179	(*jump_data->allocator->deallocate)(jump_data->behavior);
180	(*jump_data->allocator->deallocate)(jump_data);
181}
182
183struct mimimi_behavior *mimimi_jump(struct mimimi_jump *jump, struct mimimi_physics *physics, struct mimimi_allocator *allocator)
184{
185	struct mimimi_jump_data *data = (*allocator->allocate)(sizeof *data);
186	data->allocator = allocator;
187	data->jump = jump;
188	data->physics = physics;
189	
190	jump->strength = 56;
191	
192	data->behavior = (*allocator->allocate)(sizeof *data->behavior);
193	data->behavior->behave = &mimimi_jump_behave;
194	data->behavior->finish = &mimimi_jump_finish;
195	data->behavior->data = data;
196	
197	return data->behavior;
198}