Mirai's Miscellaneous Misadventures

M52 / core / displays.c

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