Mirai's Miscellaneous Misadventures

M49 / chapters / chapter-I / setup.c

1/* license: AGPLv3 or later */
2/* copyright 2024 zamfofex */
3
4#include <mimimi-chapters.h>
5
6#include "ground.c"
7#include "background.c"
8#include "foreground.c"
9
10static void mimimi_chapter_I_video_set(struct mimimi_test_video_set *tset, struct mimimi_video_set *set)
11{
12	static int video_count = 8;
13	static int image_count = 8;
14	static int width = 48;
15	static int height = 48;
16	
17	int i, j, k;
18	struct mimimi_video *videos, *standing, *knocked, *falling, *jumping;
19	struct mimimi_image *images, *image;
20	unsigned char *colors;
21	void **textures;
22	
23	videos = tset->videos;
24	images = tset->images;
25	colors = tset->colors;
26	textures = tset->textures;
27	
28	set->standing = videos;
29	set->standing_video_count = video_count;
30	videos += video_count;
31	
32	set->jumping = videos;
33	set->jumping_video_count = video_count;
34	videos += video_count;
35	
36	for (i = 0 ; i < video_count ; i++)
37	{
38		standing = set->standing + i;
39		standing->count = image_count;
40		standing->images = images;
41		images += image_count;
42		standing->textures = textures;
43		textures += image_count;
44		
45		for (j = 0 ; j < image_count ; j++)
46		{
47			image = standing->images + j;
48			image->width = width;
49			image->height = height;
50			image->colors = colors;
51			colors += width * height;
52			for (k = 0 ; k < width * height ; k++) image->colors[k] = 0;
53		}
54		
55		jumping = set->jumping + i;
56		jumping->count = image_count;
57		jumping->images = images;
58		images += image_count;
59		jumping->textures = textures;
60		textures += image_count;
61		
62		for (j = 0 ; j < image_count ; j++)
63		{
64			image = jumping->images + j;
65			image->width = width;
66			image->height = height;
67			image->colors = colors;
68			colors += width * height;
69			for (k = 0 ; k < width * height ; k++) image->colors[k] = 0;
70		}
71	}
72	
73	knocked = videos++;
74	knocked->count = 1;
75	knocked->images = images++;
76	knocked->images[0].width = width;
77	knocked->images[0].height = height;
78	knocked->images[0].colors = colors;
79	knocked->textures = textures++;
80	colors += width * height;
81	for (i = 0 ; i < width * height ; i++) knocked->images[0].colors[i] = 0;
82	
83	falling = videos++;
84	falling->count = 1;
85	falling->images = images++;
86	falling->images[0].width = width;
87	falling->images[0].height = height;
88	falling->images[0].colors = colors;
89	colors += width * height;
90	falling->textures = textures++;
91	for (i = 0 ; i < width * height ; i++) falling->images[0].colors[i] = 0;
92	
93	set->knocked = knocked;
94	set->falling = falling;
95}
96
97static void mimimi_chapter_I_appearance(struct mimimi_test_sprite *sprite, struct mimimi_engine *engine)
98{
99	mimimi_chapter_I_video_set(&sprite->left, &sprite->appearance.left);
100	mimimi_chapter_I_video_set(&sprite->right, &sprite->appearance.right);
101	
102	mimimi_appearance(&sprite->appearance, sprite->model, 24, 37);
103	mimimi_prepare_appearance(&sprite->appearance, engine);
104}
105
106static void mimimi_chapter_I_origin(struct mimimi_ground *ground, struct mimimi_position *position)
107{
108	for (position->y = 0 ; position->y < ground->height ; position->y++)
109	for (position->x = 0 ; position->x < ground->width ; position->x++)
110	{
111		if (ground->tiles[position->x + position->y * ground->width] == 2)
112			return;
113	}
114}
115
116static void mimimi_chapter_I_sprite(struct mimimi_test_sprite *sprite, struct mimimi_model *model, struct mimimi_chapter_I *chapter)
117{
118	sprite->model = model;
119	sprite->display.camera = &chapter->clamped_camera.output;
120	sprite->display.sprite = &sprite->sprite;
121	sprite->display.appearance = &sprite->appearance;
122	sprite->display.animation_time = 0;
123	sprite->display.direction = 1;
124	sprite->display.width = 24;
125	sprite->display.height = 48;
126	mimimi_sprite(&sprite->sprite, mimimi_chapter_I_ground, 0, 0, 80, 250);
127	mimimi_chapter_I_appearance(sprite, chapter->engine);
128}
129
130static void mimimi_chapter_I_player_tick(struct mimimi_chapter_I *chapter)
131{
132	mimimi_controls_tick(&chapter->player.sprite.walk, &chapter->history, &mimimi_jump, &chapter->player.sprite);
133	mimimi_sprite_tick(&chapter->player.sprite);
134}
135
136static void mimimi_chapter_I_stamp(struct mimimi_image *image, struct mimimi_image *source, int x, int y)
137{
138	int x0, y0;
139	for (y0 = 0 ; y0 < source->height ; y0++)
140	for (x0 = 0 ; x0 < source->width ; x0++)
141		image->colors[(x0 + x) + (y0 + y) * image->width] = source->colors[x0 + y0 * source->width];
142}
143
144static void mimimi_chapter_I_background(struct mimimi_chapter_I *chapter)
145{
146	static unsigned char colors[] = {6, 2, 2};
147	
148	int x, y;
149	unsigned char color;
150	int size;
151	
152	chapter->background_image.colors = chapter->background_colors;
153	chapter->background_image.width = mimimi_chapter_I_ground->width * 16;
154	chapter->background_image.height = mimimi_chapter_I_ground->height * 16;
155	
156	for (y = 0 ; y < chapter->background_image.height ; y++)
157	for (x = 0 ; x < chapter->background_image.width ; x++)
158	{
159		color = colors[mimimi_ground_tile(mimimi_chapter_I_ground, x / 16, y / 16)];
160		chapter->background_image.colors[x + y * chapter->background_image.width] = color;
161	}
162	
163	chapter->custom_background.colors = chapter->colors;
164	chapter->custom_background.width = mimimi_chapter_I_background_width;
165	chapter->custom_background.height = mimimi_chapter_I_background_height;
166	size = chapter->custom_background.width * chapter->custom_background.height;
167	
168	mimimi_unpack_bits(size, chapter->colors, mimimi_chapter_I_background_packed);
169	
170	mimimi_chapter_I_stamp(&chapter->background_image, &chapter->custom_background, (chapter->origin.x - 36) * 16 + 5, (chapter->origin.y - 10) * 16);
171	
172	chapter->background.texture = (*chapter->engine->texture)(chapter->engine->data, &chapter->background_image);
173	chapter->background.camera = &chapter->clamped_camera.output;
174	chapter->background.z = 0;
175}
176
177static void mimimi_chapter_I_foreground(struct mimimi_chapter_I *chapter)
178{
179	int size;
180	
181	chapter->foreground_image.colors = chapter->colors;
182	chapter->foreground_image.width = mimimi_chapter_I_foreground_width;
183	chapter->foreground_image.height = mimimi_chapter_I_foreground_height;
184	size = chapter->foreground_image.width * chapter->foreground_image.height;
185	
186	mimimi_unpack_bits(size, chapter->colors, mimimi_chapter_I_foreground_packed);
187	
188	chapter->foreground.texture = (*chapter->engine->texture)(chapter->engine->data, &chapter->foreground_image);
189	chapter->foreground.camera = &chapter->clamped_camera.output;
190	chapter->foreground.z = 0;
191}
192
193static void mimimi_chapter_I_camera(struct mimimi_chapter_I *chapter)
194{
195	static struct mimimi_clamped_camera_threshold thresholds[] =
196	{
197		{-270, 0, 0},
198		{-166, -1000, -53},
199		{-134, -51, -5},
200		{-35, -13, 5},
201		{8, 2, 2},
202		{1000, 1, 1},
203	};
204	
205	chapter->clamped_camera.position = &chapter->player.sprite.position;
206	chapter->clamped_camera.input = &chapter->camera;
207	chapter->clamped_camera.thresholds = thresholds;
208	chapter->clamped_camera.count = sizeof thresholds / sizeof *thresholds;
209}
210
211static void mimimi_chapter_I_offset(struct mimimi_chapter_I *chapter)
212{
213	static struct mimimi_offset_threshold thresholds[] =
214	{
215		{-134, {-29824, -768}},
216		{-35, {-12800, 2432}},
217		{8, {0, 0}},
218	};
219	
220	chapter->offset.sprite = &chapter->player.sprite;
221	chapter->offset.thresholds = thresholds;
222	chapter->offset.count = sizeof thresholds / sizeof *thresholds;
223}
224
225static void mimimi_chapter_I_background_tick(struct mimimi_chapter_I *chapter)
226{
227	chapter->background.x = chapter->player.sprite.offset.x;
228	chapter->background.y = chapter->player.sprite.offset.y;
229	mimimi_background_tick(&chapter->background, chapter->engine);
230}
231
232static void mimimi_chapter_I_foreground_tick(struct mimimi_chapter_I *chapter)
233{
234	chapter->foreground.x = -35 * 128;
235	chapter->foreground.y = -10 * 128;
236	mimimi_background_tick(&chapter->foreground, chapter->engine);
237}
238
239static void mimimi_chapter_I_linear_platform(struct mimimi_chapter_I *chapter, void *texture, int x, int y, int scale)
240{
241	static unsigned char tiles[] = {0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0};
242	int i;
243
244	i = chapter->linear_platform_count++;
245	
246	mimimi_positioned_physics(&chapter->linear_platforms[i].physics, &chapter->player.sprite.physics, &chapter->player.sprite.position);
247	chapter->linear_platforms[i].ground.width = 5;
248	chapter->linear_platforms[i].ground.height = 3;
249	chapter->linear_platforms[i].ground.tiles = tiles;
250	chapter->linear_platforms[i].texture = texture;
251	
252	chapter->linear_platforms[i].physics.transform.x = x * 128;
253	mimimi_linear_motion(chapter->linear_motions + i, &chapter->momentum, &chapter->linear_platforms[i].physics.transform.y, y * 128, scale);
254	(*chapter->linear_motions[i].motion.apply)(chapter->linear_motions[i].motion.data);
255}
256
257static void mimimi_chapter_I_platforms(struct mimimi_chapter_I *chapter)
258{
259	int i;
260	void *texture;
261	
262	for (i = 0 ; i < 1024 ; i++) chapter->platform_colors[i] = 1;
263	chapter->platform_image.colors = chapter->platform_colors;
264	chapter->platform_image.width = 48;
265	chapter->platform_image.height = 16;
266	
267	texture = (*chapter->engine->texture)(chapter->engine->data, &chapter->platform_image);
268	
269	chapter->momentum.x = 0;
270	chapter->momentum.dx = 0;
271	chapter->linear_platform_count = 0;
272	
273	mimimi_chapter_I_linear_platform(chapter, texture, -150, -14, 256);
274	mimimi_chapter_I_linear_platform(chapter, texture, -158, -24, 256);
275	mimimi_chapter_I_linear_platform(chapter, texture, -144, -16, -256);
276	mimimi_chapter_I_linear_platform(chapter, texture, -158, -26, -256);
277}
278
279static void mimimi_chapter_I_platforms_propagate(struct mimimi_chapter_I *chapter)
280{
281	int i;
282	for (i = 0 ; i < chapter->linear_platform_count ; i++)
283		if (chapter->linear_platforms[i].physics.other.airborne == 0)
284			(*chapter->linear_motions[i].motion.propagate)(chapter->linear_motions[i].motion.data);
285}
286
287static void mimimi_chapter_I_platforms_apply(struct mimimi_chapter_I *chapter)
288{
289	int i;
290	for (i = 0 ; i < chapter->linear_platform_count ; i++)
291		(*chapter->linear_motions[i].motion.apply)(chapter->linear_motions[i].motion.data);
292}
293
294static void mimimi_chapter_I_platforms_tick(struct mimimi_chapter_I *chapter)
295{
296	struct mimimi_momentum *momentum;
297	struct mimimi_platform *platforms;
298	int i;
299	
300	momentum = &chapter->momentum;
301	platforms = chapter->linear_platforms;
302	
303	for (i = 0 ; i < chapter->linear_platform_count ; i++)
304		if (platforms[i].physics.other.airborne == 0)
305			platforms[i].physics.transform.y += 4;
306	
307	mimimi_chapter_I_platforms_propagate(chapter);
308	
309	momentum->dx *= 31;
310	momentum->dx /= 32;
311	momentum->x += momentum->dx;
312	
313	if (momentum->x < 0)
314	{
315		momentum->x = 0;
316		momentum->dx = 0;
317	}
318	if (momentum->x > 1024)
319	{
320		momentum->x = 1024;
321		momentum->dx = 0;
322	}
323	
324	mimimi_chapter_I_platforms_apply(chapter);
325	
326	for (i = 0 ; i < chapter->linear_platform_count ; i++)
327		mimimi_positioned_physics_tick(&platforms[i].physics, &platforms[i].ground);
328}
329
330static void mimimi_chapter_I_platforms_display_tick(struct mimimi_chapter_I *chapter)
331{
332	int i;
333	for (i = 0 ; i < chapter->linear_platform_count ; i++)
334		mimimi_platform_display_tick(chapter->linear_platforms + i, &chapter->clamped_camera.output, -128, -128, chapter->engine);
335}
336
337void mimimi_chapter_I_tick(void *data, unsigned char left, unsigned char right)
338{
339	struct mimimi_chapter_I *chapter;
340	int x, y;
341	
342	chapter = data;
343	mimimi_offset_tick(&chapter->offset, chapter->origin.x * 128, chapter->origin.y * 128);
344	mimimi_history_tick(&chapter->history, left, right);
345	mimimi_chapter_I_player_tick(chapter);
346	mimimi_chapter_I_platforms_tick(chapter);
347	
348	x = chapter->player.sprite.physics.dx * 6;
349	y = chapter->player.sprite.physics.dy * 4;
350	
351	mimimi_chapter_I_background_tick(chapter);
352	mimimi_chapter_I_platforms_display_tick(chapter);
353	mimimi_display_tick(&chapter->player.display, chapter->engine);
354	mimimi_chapter_I_foreground_tick(chapter);
355	mimimi_camera_tick(&chapter->camera, &chapter->player.sprite.position, x, y - 256);
356	mimimi_clamped_camera_tick(&chapter->clamped_camera);
357	
358	if (chapter->progression == 0)
359	{
360		if (chapter->player.sprite.position.x < -190 * 128)
361			chapter->progression++;
362	}
363	if (chapter->progression == 1)
364	{
365		if (mimimi_logo_tick(chapter->engine, &chapter->logo, chapter->engine->size.width / 2, 16) != 0)
366			chapter->progression++;
367	}
368	if (chapter->progression == 2)
369	{
370		mimimi_logo_tick(chapter->engine, &chapter->logo, chapter->engine->size.width / 2, 16);
371		chapter->progression_counter++;
372		if (chapter->progression_counter > 128)
373			chapter->progression_counter = 0,
374			chapter->progression++;
375	}
376	if (chapter->progression == 3)
377	{
378		chapter->progression_counter++;
379		if (chapter->progression_counter > 128)
380			chapter->progression++;
381	}
382	if (chapter->progression == 4)
383	{
384		if (chapter->player.sprite.position.x < -256 * 128)
385			chapter->progression++;
386	}
387	if (chapter->progression == 5)
388	{
389		if (mimimi_toast_dialogue_bottom_tick(&chapter->dialogue) != 0)
390			chapter->progression++;
391	}
392}
393
394void mimimi_chapter_I(void *data, struct mimimi_engine *engine)
395{
396	struct mimimi_dialogue_paragraph paragraphs[] =
397	{
398		{0, "Mirai", "There seems to be nothing for me to do. Hmmm... Maybe I can find something to do later."},
399		{0, "Ryouna", "Hear that? If you come back later, then maybe you can find something to do!"},
400		{0, "Ryoubi", "Who are you talking with? Are you stupid or something?"},
401		{0, "Ryouna", "Aaah! Ryoubi, I really like when you yell insults at me!"},
402		{0, "Mirai", "Wha-? What are you two doing here?"},
403		{0, "Haruka", "Hehe, don't worry about it!"},
404	};
405	
406	struct mimimi_dialogue dialogue;
407	struct mimimi_chapter_I *chapter;
408	
409	paragraphs[0].model = mimimi_mirai_flash;
410	paragraphs[1].model = mimimi_ryouna_flash;
411	paragraphs[2].model = mimimi_ryoubi_flash;
412	paragraphs[3].model = mimimi_ryouna_flash;
413	paragraphs[4].model = mimimi_mirai_flash;
414	paragraphs[5].model = mimimi_haruka_flash;
415	
416	chapter = data;
417	chapter->engine = engine;
418	
419	chapter->progression = 0;
420	chapter->progression_counter = 0;
421	dialogue.count = sizeof paragraphs / sizeof *paragraphs;
422	dialogue.paragraphs = paragraphs;
423	mimimi_toast_dialogue(&chapter->dialogue, &dialogue, engine);
424	
425	mimimi_chapter_I_origin(mimimi_chapter_I_ground, &chapter->origin);
426	mimimi_chapter_I_sprite(&chapter->player, mimimi_mirai_flash, chapter);
427	
428	chapter->history.left = 0;
429	chapter->history.right = 0;
430	
431	chapter->camera = chapter->player.sprite.position;
432	chapter->camera.y -= 512;
433	
434	mimimi_chapter_I_camera(chapter);
435	mimimi_chapter_I_background(chapter);
436	mimimi_chapter_I_foreground(chapter);
437	
438	mimimi_chapter_I_offset(chapter);
439	
440	mimimi_clamped_camera_tick(&chapter->clamped_camera);
441	
442	mimimi_chapter_I_platforms(chapter);
443	
444	mimimi_logo(engine, &chapter->logo, mimimi_logo_lines, mimimi_logo_line_count);
445}