Mirai's Miscellaneous Misadventures

M44 / chapters / chapter-I / setup.c

1/* license: AGPLv3 or later */
2/* copyright 2023 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
116
117static void mimimi_chapter_I_sprite(struct mimimi_test_sprite *sprite, struct mimimi_model *model, struct mimimi_chapter_I *chapter)
118{
119	sprite->model = model;
120	sprite->display.camera = &chapter->clamped_camera.output;
121	sprite->display.sprite = &sprite->sprite;
122	sprite->display.appearance = &sprite->appearance;
123	sprite->display.animation_time = 0;
124	sprite->display.direction = 1;
125	sprite->display.width = 24;
126	sprite->display.height = 48;
127	mimimi_sprite(&sprite->sprite, mimimi_chapter_I_ground, chapter->origin.x * 128, chapter->origin.y * 128, 80, 250);
128	mimimi_chapter_I_appearance(sprite, chapter->engine);
129}
130
131static void mimimi_chapter_I_player_tick(struct mimimi_chapter_I *chapter)
132{
133	mimimi_controls_tick(&chapter->player.sprite.walk, &chapter->history, &mimimi_jump, &chapter->player.sprite);
134	mimimi_sprite_tick(&chapter->player.sprite);
135}
136
137static void mimimi_chapter_I_unpack_bits(int size, unsigned char *unpacked, unsigned char *packed)
138{
139	int i, j, k, n;
140	
141	i = 0;
142	j = 0;
143	
144	while (j < size)
145	{
146		n = packed[i++];
147		if (n == 128) continue;
148		if (n > 128) n -= 256;
149		
150		if (n > 0)
151		{
152			for (k = 0 ; k <= n ; k++)
153				unpacked[j++] = packed[i++];
154		}
155		else
156		{
157			for (k = 0 ; k <= -n ; k++)
158				unpacked[j++] = packed[i];
159			i++;
160		}
161	}
162}
163
164static void mimimi_chapter_I_stamp(struct mimimi_image *image, struct mimimi_image *source, int x, int y)
165{
166	int x0, y0;
167	for (y0 = 0 ; y0 < source->height ; y0++)
168	for (x0 = 0 ; x0 < source->width ; x0++)
169		image->colors[(x0 + x) + (y0 + y) * image->width] = source->colors[x0 + y0 * source->width];
170}
171
172static void mimimi_chapter_I_background(struct mimimi_chapter_I *chapter)
173{
174	static unsigned char colors[] = {6, 2, 2};
175	
176	int x, y;
177	unsigned char color;
178	int size;
179	
180	chapter->background_image.colors = chapter->background_colors;
181	chapter->background_image.width = mimimi_chapter_I_ground->width * 16;
182	chapter->background_image.height = mimimi_chapter_I_ground->height * 16;
183	
184	for (y = 0 ; y < chapter->background_image.height ; y++)
185	for (x = 0 ; x < chapter->background_image.width ; x++)
186	{
187		color = colors[mimimi_ground_tile(mimimi_chapter_I_ground, x / 16, y / 16)];
188		chapter->background_image.colors[x + y * chapter->background_image.width] = color;
189	}
190	
191	chapter->custom_background.colors = chapter->colors;
192	chapter->custom_background.width = mimimi_chapter_I_background_width;
193	chapter->custom_background.height = mimimi_chapter_I_background_height;
194	size = chapter->custom_background.width * chapter->custom_background.height;
195	
196	mimimi_chapter_I_unpack_bits(size, chapter->colors, mimimi_chapter_I_background_packed);
197	
198	mimimi_chapter_I_stamp(&chapter->background_image, &chapter->custom_background, (chapter->origin.x - 36) * 16, (chapter->origin.y - 10) * 16);
199	
200	chapter->background.texture = (*chapter->engine->texture)(chapter->engine->data, &chapter->background_image);
201	chapter->background.camera = &chapter->clamped_camera.output;
202	chapter->background.z = 0;
203}
204
205static void mimimi_chapter_I_foreground(struct mimimi_chapter_I *chapter)
206{
207	int size;
208	
209	chapter->foreground_image.colors = chapter->colors;
210	chapter->foreground_image.width = mimimi_chapter_I_foreground_width;
211	chapter->foreground_image.height = mimimi_chapter_I_foreground_height;
212	size = chapter->foreground_image.width * chapter->foreground_image.height;
213	
214	mimimi_chapter_I_unpack_bits(size, chapter->colors, mimimi_chapter_I_foreground_packed);
215	
216	chapter->foreground.texture = (*chapter->engine->texture)(chapter->engine->data, &chapter->foreground_image);
217	chapter->foreground.camera = &chapter->clamped_camera.output;
218	chapter->foreground.z = 0;
219}
220
221static void mimimi_chapter_I_camera(struct mimimi_chapter_I *chapter)
222{
223	static struct mimimi_clamped_camera_threshold thresholds[] =
224	{
225		{-135, 0,0},
226		{-35, -13, 5},
227		{8, 2, 2},
228	};
229	
230	chapter->clamped_camera.origin = &chapter->origin;
231	chapter->clamped_camera.position = &chapter->player.sprite.position;
232	chapter->clamped_camera.input = &chapter->camera;
233	chapter->clamped_camera.thresholds = thresholds;
234	chapter->clamped_camera.count = sizeof thresholds / sizeof *thresholds;
235}
236
237static void mimimi_chapter_I_offset(struct mimimi_chapter_I *chapter)
238{
239	static struct mimimi_offset_threshold thresholds[] =
240	{
241		{-35, {-12800, 2432}},
242		{8, {0, 0}},
243	};
244	
245	chapter->offset.origin = &chapter->origin;
246	chapter->offset.sprite = &chapter->player.sprite;
247	chapter->offset.thresholds = thresholds;
248	chapter->offset.count = sizeof thresholds / sizeof *thresholds;
249}
250
251static void mimimi_chapter_I_background_tick(struct mimimi_chapter_I *chapter)
252{
253	chapter->background.x = chapter->player.sprite.offset.x;
254	chapter->background.y = chapter->player.sprite.offset.y;
255	mimimi_background_tick(&chapter->background, chapter->engine);
256}
257
258static void mimimi_chapter_I_foreground_tick(struct mimimi_chapter_I *chapter)
259{
260	chapter->foreground.x = chapter->background.x + (chapter->origin.x - 35) * 128;
261	chapter->foreground.y = chapter->background.y + (chapter->origin.y - 10) * 128;
262	mimimi_background_tick(&chapter->foreground, chapter->engine);
263}
264
265void mimimi_chapter_I_tick(void *data, unsigned char left, unsigned char right)
266{
267	struct mimimi_chapter_I *chapter;
268	chapter = data;
269	mimimi_history_tick(&chapter->history, left, right);
270	mimimi_chapter_I_player_tick(chapter);
271	mimimi_chapter_I_background_tick(chapter);
272	mimimi_offset_tick(&chapter->offset);
273	mimimi_display_tick(&chapter->player.display, chapter->engine);
274	mimimi_chapter_I_foreground_tick(chapter);
275	mimimi_camera_tick(&chapter->camera, &chapter->player.sprite.position, 0, -512);
276	mimimi_clamped_camera_tick(&chapter->clamped_camera);
277	if (chapter->progression == 0)
278	{
279		if (chapter->player.sprite.position.x - chapter->origin.x * 128 < -16384)
280			chapter->progression++;
281	}
282	if (chapter->progression == 1)
283	{
284		if (mimimi_toast_dialogue_bottom_tick(&chapter->dialogue) != 0)
285			chapter->progression++;
286	}
287}
288
289void mimimi_chapter_I(void *data, struct mimimi_engine *engine)
290{
291	struct mimimi_dialogue_paragraph paragraphs[] =
292	{
293		{0, "Mango", "Hello, world!"},
294	};
295	
296	struct mimimi_dialogue dialogue;
297	struct mimimi_chapter_I *chapter;
298	
299	paragraphs[0].model = mimimi_mango;
300	
301	chapter = data;
302	chapter->engine = engine;
303	
304	chapter->progression = 0;
305	dialogue.count = sizeof paragraphs / sizeof *paragraphs;
306	dialogue.paragraphs = paragraphs;
307	mimimi_toast_dialogue(&chapter->dialogue, &dialogue, engine);
308	
309	mimimi_chapter_I_origin(mimimi_chapter_I_ground, &chapter->origin);
310	mimimi_chapter_I_sprite(&chapter->player, mimimi_mango, chapter);
311	
312	chapter->history.left = 0;
313	chapter->history.right = 0;
314	
315	chapter->camera = chapter->player.sprite.position;
316	chapter->camera.y -= 512;
317	
318	mimimi_chapter_I_camera(chapter);
319	mimimi_chapter_I_background(chapter);
320	mimimi_chapter_I_foreground(chapter);
321	
322	mimimi_chapter_I_offset(chapter);
323	
324	mimimi_clamped_camera_tick(&chapter->clamped_camera);
325}