Mirai's Miscellaneous Misadventures

M50 / core / displays.c

1/* license: AGPLv3 or later */
2/* copyright 2024 zamfofex */
3
4#include <stdlib.h>
5
6#include <mimimi.h>
7
8void mimimi_camera_stamp(struct mimimi_engine *engine, struct mimimi_position *camera, int x, int y, int z, void *texture)
9{
10	z += 8;
11	if (z <= 0) return;
12	
13	x -= camera->x;
14	x = mimimi_div_up(x, z);
15	x += engine->size.width / 2;
16	
17	y -= camera->y;
18	y = mimimi_div_up(y, z);
19	y += engine->size.height / 2;
20	
21	(*engine->stamp)(engine->data, x, y, texture);
22}
23
24void mimimi_display_tick(struct mimimi_display *display, struct mimimi_engine *engine, struct mimimi_sprite *sprite)
25{
26	struct mimimi_appearance *appearance;
27	struct mimimi_position *position;
28	struct mimimi_physics *physics;
29	struct mimimi_life *life;
30	struct mimimi_walk *walk;
31	int dx, dy;
32	struct mimimi_video_set *videos;
33	struct mimimi_video *video;
34	void *texture;
35	int x, y;
36	
37	appearance = &display->appearance;
38	
39	position = &sprite->position;
40	physics = &sprite->physics;
41	life = &sprite->life;
42	walk = &sprite->walk;
43	
44	x = display->width * -8;
45	y = display->height * -8;
46	
47	if (life->knocked_time == 0 && walk->direction != 0)
48		display->direction = walk->direction;
49	
50	dx = physics->dx;
51	dy = physics->dy;
52	videos = &appearance->right;
53	
54	if (display->direction == 1)
55	{
56		videos = &appearance->left;
57		dx *= -1;
58	}
59	
60	if (dx > 8191) dx = 8191;
61	if (dx < 0) dx = 0;
62	
63	if (life->knocked_time == 0)
64	{
65		if (physics->airborne != 0)
66		{
67			if (dy < -8191) dy = -8191;
68			if (dy > 8191) dy = 8191;
69			dy += 8191;
70			
71			video = videos->jumping + dx * videos->jumping_video_count / 8192;
72			texture = video->textures[dy * video->count / 16384];
73			
74			mimimi_camera_stamp(engine, display->camera, position->x + x, position->y + y, 0, texture);
75			return;
76		}
77		
78		if (physics->airborne != 0)
79		{
80			texture = videos->jumping->textures[dx * videos->jumping->count / 8192];
81			mimimi_camera_stamp(engine, display->camera, position->x + x, position->y + y, 0, texture);
82			return;
83		}
84		
85		video = videos->standing + dx * videos->standing_video_count / 8192;
86		display->animation_time += dx / 1024;
87	}
88	else
89	{
90		if (physics->airborne == 0)
91			video = videos->knocked,
92			y += 212;
93		else
94			video = videos->falling,
95			y += 128;
96		
97		if (dy < 0) dy = 0;
98		display->animation_time += dy / 2048;
99	}
100	
101	/* do not assume 'char' is eight bits */
102	display->animation_time &= 0xFF;
103	
104	texture = video->textures[display->animation_time * video->count / 256];
105	mimimi_camera_stamp(engine, display->camera, position->x + x, position->y + y, 0, texture);
106}
107
108void mimimi_background_tick(struct mimimi_background *background, struct mimimi_engine *engine, struct mimimi_position *camera, struct mimimi_position *offset)
109{
110	mimimi_camera_stamp(engine, camera, background->x + offset->x, background->y + offset->y, background->z, background->texture);
111}
112
113static void mimimi_populate_video_set(struct mimimi_video_set *set)
114{
115	static int video_count = 8;
116	static int image_count = 8;
117	static int width = 48;
118	static int height = 48;
119	
120	int i, j, k;
121	struct mimimi_video *videos, *standing, *knocked, *falling, *jumping;
122	struct mimimi_image *images, *image;
123	unsigned char *colors;
124	void **textures;
125	
126	videos = malloc(sizeof *videos * (video_count * 2 + 2));
127	images = malloc(sizeof *images * (image_count * video_count * 2 + 2));
128	textures = malloc(sizeof *textures * (image_count * video_count * 2 + 2));
129	colors = malloc((image_count * video_count * 2 + 2) * 48 * 48);
130	
131	if (videos == NULL) exit(1);
132	if (images == NULL) exit(1);
133	if (textures == NULL) exit(1);
134	if (colors == NULL) exit(1);
135	
136	set->standing = videos;
137	set->standing_video_count = video_count;
138	videos += video_count;
139	
140	set->jumping = videos;
141	set->jumping_video_count = video_count;
142	videos += video_count;
143	
144	for (i = 0 ; i < video_count ; i++)
145	{
146		standing = set->standing + i;
147		standing->count = image_count;
148		standing->images = images;
149		images += image_count;
150		standing->textures = textures;
151		textures += image_count;
152		
153		for (j = 0 ; j < image_count ; j++)
154		{
155			image = standing->images + j;
156			image->width = width;
157			image->height = height;
158			image->colors = colors;
159			colors += width * height;
160			for (k = 0 ; k < width * height ; k++) image->colors[k] = 0;
161		}
162		
163		jumping = set->jumping + i;
164		jumping->count = image_count;
165		jumping->images = images;
166		images += image_count;
167		jumping->textures = textures;
168		textures += image_count;
169		
170		for (j = 0 ; j < image_count ; j++)
171		{
172			image = jumping->images + j;
173			image->width = width;
174			image->height = height;
175			image->colors = colors;
176			colors += width * height;
177			for (k = 0 ; k < width * height ; k++) image->colors[k] = 0;
178		}
179	}
180	
181	knocked = videos++;
182	knocked->count = 1;
183	knocked->images = images++;
184	knocked->images[0].width = width;
185	knocked->images[0].height = height;
186	knocked->images[0].colors = colors;
187	knocked->textures = textures++;
188	colors += width * height;
189	for (i = 0 ; i < width * height ; i++) knocked->images[0].colors[i] = 0;
190	
191	falling = videos++;
192	falling->count = 1;
193	falling->images = images++;
194	falling->images[0].width = width;
195	falling->images[0].height = height;
196	falling->images[0].colors = colors;
197	colors += width * height;
198	falling->textures = textures++;
199	for (i = 0 ; i < width * height ; i++) falling->images[0].colors[i] = 0;
200	
201	set->knocked = knocked;
202	set->falling = falling;
203}
204
205static void mimimi_populate_appearance(struct mimimi_display *display, struct mimimi_model *model, struct mimimi_engine *engine)
206{
207	mimimi_populate_video_set(&display->appearance.left);
208	mimimi_populate_video_set(&display->appearance.right);
209	
210	mimimi_appearance(&display->appearance, model, 24, 37);
211	mimimi_prepare_appearance(&display->appearance, engine);
212}
213
214void mimimi_display(struct mimimi_display *display, struct mimimi_model *model, struct mimimi_engine *engine)
215{
216	display->animation_time = 0;
217	display->direction = 1;
218	display->width = 24;
219	display->height = 48;
220	mimimi_populate_appearance(display, model, engine);
221}