Mirai's Miscellaneous Misadventures

M18 / core / sprites.c

1// copyright 2022 zamfofex
2// license: AGPLv3 or later
3
4#include <mimimi/sprites.h>
5#include <mimimi/compound-behaviors.h>
6#include <mimimi/allocators.h>
7#include <mimimi/geometry.h>
8#include <mimimi/behaviors.h>
9#include <mimimi/ground.h>
10
11struct mimimi_physics_data
12{
13	struct mimimi_allocator *allocator;
14	struct mimimi_behavior *behavior;
15	struct mimimi_ground *ground;
16	struct mimimi_position *position;
17	struct mimimi_physics physics;
18};
19
20#include "physics.c"
21
22static void mimimi_physics_behave(void *data)
23{
24	struct mimimi_physics_data *physics_data = data;
25	struct mimimi_physics *physics = &physics_data->physics;
26	
27	if (physics->airborne == 0)
28		mimimi_ground_physics(data);
29	else
30		mimimi_airborne_physics(data);
31}
32
33static void mimimi_physics_finish(void *data)
34{
35	struct mimimi_physics_data *physics_data = data;
36	(*physics_data->allocator->deallocate)(physics_data->behavior);
37	(*physics_data->allocator->deallocate)(physics_data);
38}
39
40struct mimimi_behavior *mimimi_physics(struct mimimi_position *position, struct mimimi_ground *ground, struct mimimi_allocator *allocator)
41{
42	struct mimimi_physics_data *data = (*allocator->allocate)(sizeof *data);
43	data->allocator = allocator;
44	data->position = position;
45	data->ground = ground;
46	
47	data->physics.dx = 0;
48	data->physics.dy = 0;
49	data->physics.airborne = 1;
50	data->physics.width = 0;
51	data->physics.height = 0;
52	data->physics.gravity = 4;
53	
54	data->behavior = (*allocator->allocate)(sizeof *data->behavior);
55	data->behavior->behave = &mimimi_physics_behave;
56	data->behavior->finish = &mimimi_physics_finish;
57	data->behavior->data = data;
58	
59	return data->behavior;
60}
61
62struct mimimi_physics *mimimi_physics_attributes(struct mimimi_behavior *behavior)
63{
64	struct mimimi_physics_data *data = behavior->data;
65	return &data->physics;
66}
67
68struct mimimi_life_data
69{
70	struct mimimi_allocator *allocator;
71	struct mimimi_behavior *behavior;
72	struct mimimi_life life;
73};
74
75static void mimimi_live(void *data)
76{
77	struct mimimi_life_data *life_data = data;
78	struct mimimi_life *life = &life_data->life;
79	
80	if (life->knocked_time != 0)
81	{
82		life->knocked_time--;
83		life->immunity_time = life->recovery_time;
84	}
85	
86	if (life->immunity_time != 0)
87	{
88		life->pristinity = life->max_pristinity;
89		life->immunity_time--;
90	}
91	
92	if (life->pristinity < life->max_pristinity)
93		life->pristinity++;
94}
95
96static void mimimi_life_finish(void *data)
97{
98	struct mimimi_life_data *life_data = data;
99	(*life_data->allocator->deallocate)(life_data->behavior);
100	(*life_data->allocator->deallocate)(life_data);
101}
102
103struct mimimi_behavior *mimimi_life(struct mimimi_allocator *allocator)
104{
105	struct mimimi_life_data *data = (*allocator->allocate)(sizeof *data);
106	data->allocator = allocator;
107	
108	data->life.knocked_time = 0;
109	data->life.immunity_time = 0;
110	data->life.pristinity = 256;
111	data->life.max_pristinity = 256;
112	data->life.recovery_time = 64;
113	
114	data->behavior = (*allocator->allocate)(sizeof *data->behavior);
115	data->behavior->behave = &mimimi_live;
116	data->behavior->finish = &mimimi_life_finish;
117	data->behavior->data = data;
118	
119	return data->behavior;
120}
121
122struct mimimi_life *mimimi_life_attributes(struct mimimi_behavior *behavior)
123{
124	struct mimimi_life_data *data = behavior->data;
125	return &data->life;
126}
127
128struct mimimi_fall_data
129{
130	struct mimimi_allocator *allocator;
131	struct mimimi_behavior *behavior;
132	struct mimimi_physics *physics;
133	struct mimimi_life *life;
134	struct mimimi_fall fall;
135};
136
137static void mimimi_fall_behave(void *data)
138{
139	struct mimimi_fall_data *fall_data = data;
140	
141	if (fall_data->physics->dy > fall_data->fall.max_speed)
142	if (fall_data->life->knocked_time < fall_data->fall.knocked_time)
143		fall_data->life->knocked_time = fall_data->fall.knocked_time;
144}
145
146static void mimimi_fall_finish(void *data)
147{
148	struct mimimi_fall_data *fall_data = data;
149	(*fall_data->allocator->deallocate)(fall_data->behavior);
150	(*fall_data->allocator->deallocate)(fall_data);
151}
152
153struct mimimi_behavior *mimimi_fall(struct mimimi_physics *physics, struct mimimi_life *life, struct mimimi_allocator *allocator)
154{
155	struct mimimi_fall_data *data = (*allocator->allocate)(sizeof *data);
156	data->allocator = allocator;
157	data->physics = physics;
158	data->life = life;
159	
160	data->fall.max_speed = 128;
161	data->fall.knocked_time = 64;
162	
163	data->behavior = (*allocator->allocate)(sizeof *data->behavior);
164	data->behavior->behave = &mimimi_fall_behave;
165	data->behavior->finish = &mimimi_fall_finish;
166	data->behavior->data = data;
167	
168	return data->behavior;
169}
170
171struct mimimi_fall *mimimi_fall_attributes(struct mimimi_behavior *behavior)
172{
173	struct mimimi_fall_data *data = behavior->data;
174	return &data->fall;
175}
176
177struct mimimi_walk_data
178{
179	struct mimimi_allocator *allocator;
180	struct mimimi_behavior *behavior;
181	struct mimimi_physics *physics;
182	struct mimimi_walk walk;
183};
184
185static void mimimi_walk_behave(void *data)
186{
187	struct mimimi_walk_data *walk_data = data;
188	struct mimimi_physics *physics = walk_data->physics;
189	
190	if (walk_data->walk.direction != 0)
191	{
192		int ax;
193		if (walk_data->physics->airborne)
194			ax = walk_data->walk.airborne_speed;
195		else
196			ax = walk_data->walk.ground_speed;
197		
198		if (walk_data->walk.direction == 1)
199			physics->dx -= ax;
200		if (walk_data->walk.direction == 2)
201			physics->dx += ax;
202	}
203}
204
205static void mimimi_walk_finish(void *data)
206{
207	struct mimimi_walk_data *walk_data = data;
208	(*walk_data->allocator->deallocate)(walk_data->behavior);
209	(*walk_data->allocator->deallocate)(walk_data);
210}
211
212struct mimimi_behavior *mimimi_walk(struct mimimi_physics *physics, struct mimimi_allocator *allocator)
213{
214	struct mimimi_walk_data *data = (*allocator->allocate)(sizeof *data);
215	data->allocator = allocator;
216	data->physics = physics;
217	
218	data->walk.ground_speed = 4;
219	data->walk.airborne_speed = 3;
220	data->walk.direction = 0;
221	
222	data->behavior = (*allocator->allocate)(sizeof *data->behavior);
223	data->behavior->behave = &mimimi_walk_behave;
224	data->behavior->finish = &mimimi_walk_finish;
225	data->behavior->data = data;
226	
227	return data->behavior;
228}
229
230struct mimimi_walk *mimimi_walk_attributes(struct mimimi_behavior *behavior)
231{
232	struct mimimi_walk_data *data = behavior->data;
233	return &data->walk;
234}
235
236struct mimimi_sprite_data
237{
238	struct mimimi_behavior *walk_behavior;
239	struct mimimi_sprite *sprite;
240};
241
242static void mimimi_sprite_behave(void *data0)
243{
244	struct mimimi_sprite_data *data = data0;
245	struct mimimi_sprite *sprite = data->sprite;
246	struct mimimi_behavior *walk_behavior = data->walk_behavior;
247	struct mimimi_behavior *awake_behavior = sprite->awake_behavior;
248	
249	if (sprite->life->knocked_time == 0)
250	{
251		(*walk_behavior->behave)(walk_behavior->data);
252		(*awake_behavior->behave)(awake_behavior->data);
253	}
254} 
255
256struct mimimi_sprite *mimimi_sprite(struct mimimi_ground *ground, int x, int y, int width, int height, struct mimimi_allocator *allocator)
257{
258	struct mimimi_behavior *compound = mimimi_compound_behavior(allocator);
259	
260	struct mimimi_position *position = (*allocator->allocate)(sizeof *position);
261	struct mimimi_behavior *position_behavior = mimimi_finalizer(position, allocator->deallocate, allocator);
262	
263	struct mimimi_behavior *physics_behavior = mimimi_physics(position, ground, allocator);
264	struct mimimi_physics *physics = mimimi_physics_attributes(physics_behavior);
265	
266	struct mimimi_behavior *life_behavior = mimimi_life(allocator);
267	struct mimimi_life *life = mimimi_life_attributes(life_behavior);
268	
269	struct mimimi_behavior *fall_behavior = mimimi_fall(physics, life, allocator);
270	struct mimimi_fall *fall = mimimi_fall_attributes(fall_behavior);
271	
272	struct mimimi_behavior *walk_behavior = mimimi_walk(physics, allocator);
273	struct mimimi_walk *walk = mimimi_walk_attributes(walk_behavior);
274	mimimi_compound(compound, mimimi_finalizer(walk_behavior->data, walk_behavior->finish, allocator));
275	
276	position->x = x;
277	position->y = y;
278	physics->width = width;
279	physics->height = height;
280	
281	struct mimimi_sprite *sprite = (*allocator->allocate)(sizeof *sprite);
282	mimimi_compound(compound, mimimi_finalizer(sprite, allocator->deallocate, allocator));
283	
284	struct mimimi_sprite_data *sprite_data = (*allocator->allocate)(sizeof *sprite_data);
285	mimimi_compound(compound, mimimi_finalizer(sprite_data, allocator->deallocate, allocator));
286	
287	sprite_data->walk_behavior = walk_behavior;
288	sprite_data->sprite = sprite;
289	
290	struct mimimi_behavior *sprite_behavior = mimimi_function(sprite_data, &mimimi_sprite_behave, allocator);
291	
292	mimimi_compound(compound, sprite_behavior);
293	mimimi_compound(compound, physics_behavior);
294	mimimi_compound(compound, life_behavior);
295	mimimi_compound(compound, fall_behavior);
296	
297	sprite->position = position;
298	sprite->physics = physics;
299	sprite->life = life;
300	sprite->fall = fall;
301	sprite->walk = walk;
302	sprite->behavior = compound;
303	sprite->awake_behavior = mimimi_noop;
304	
305	return sprite;
306}