Mirai's Miscellaneous Misadventures

M32 / 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}