Mirai's Miscellaneous Misadventures

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