Mirai's Miscellaneous Misadventures

M54 / core / stages.c

1/* license: AGPLv3 or later */
2/* copyright 2024 zamfofex */
3
4#include <stdlib.h>
5#include "../mimimi.h"
6
7static int mimimi_ground_floor(struct mimimi_ground *ground, int x)
8{
9	int y;
10	for (y = ground->height ; y > 0 ; y--) {
11		if (mimimi_ground_tile(ground, x, y - 1) == 0) return y;
12	}
13	return 0;
14}
15
16static void mimimi_origin(struct mimimi_ground *ground, struct mimimi_position *position)
17{
18	for (position->y = 0 ; position->y < ground->height ; position->y++) {
19		for (position->x = 0 ; position->x < ground->width ; position->x++) {
20			if (ground->tiles[position->x + position->y * ground->width] == 2) return;
21		}
22	}
23}
24
25void mimimi_stage(struct mimimi_stage *stage, struct mimimi_ground **grounds, int count)
26{
27	int i, k;
28	struct mimimi_position offset;
29	int left_floor_y, right_floor_y;
30	struct mimimi_area *area;
31	
32	stage->sprite_count = 0;
33	stage->area_count = count;
34	stage->areas = malloc(sizeof *stage->areas * count);
35	if (stage->areas == NULL) exit(1);
36	stage->clamped_camera.input = &stage->camera;
37	stage->platform_set_count = 0;
38	
39	for (i = 0 ; i < count ; i++) {
40		area = stage->areas + i;
41		area->ground = grounds[i];
42		area->background_count = 0;
43		area->foreground_count = 0;
44	}
45	
46	mimimi_origin(grounds[0], &offset);
47	offset.x *= -1;
48	offset.y *= -1;
49	stage->areas[0].ground = grounds[0];
50	stage->areas[0].offset = offset;
51	
52	left_floor_y = mimimi_ground_floor(grounds[0], 0);
53	
54	for (i = 1 ; i < count ; i++) {
55		area = stage->areas + i;
56		area->ground = grounds[i];
57		right_floor_y = mimimi_ground_floor(grounds[i], grounds[i]->width - 1);
58		offset.x -= grounds[i]->width;
59		offset.y -= right_floor_y - left_floor_y;
60		left_floor_y = mimimi_ground_floor(grounds[i], 0);
61		area->offset = offset;
62	}
63	
64	k = sizeof stage->sounds / sizeof *stage->sounds;
65	
66	for (i = 0 ; i < k ; i++) {
67		stage->sounds[i].sound.count = 0;
68		stage->sounds[i].current = 0;
69	}
70}
71
72void mimimi_stage_tick(struct mimimi_stage *stage, struct mimimi_input *input)
73{
74	struct mimimi_sprite *sprite, *player;
75	int i, j, k;
76	int x, y;
77	int count;
78	struct mimimi_image *image;
79	struct mimimi_played_sound *sound;
80	
81	image = &input->image;
82	player = stage->sprites;
83	
84	j = 0;
85	while (player->position.x < stage->areas[j].offset.x * 128) j++;
86	
87	for (i = 0 ; i < stage->sprite_count ; i++) {
88		
89		sprite = stage->sprites + i;
90		
91		k = 0;
92		while (sprite->position.x < stage->areas[k].offset.x * 128) k++;
93		sprite->ground = stage->areas[k].ground;
94		sprite->offset = stage->areas[k].offset;
95		sprite->offset.x *= 128;
96		sprite->offset.y *= 128;
97		
98		stage->clamped_camera.offset = stage->areas[k].offset;
99		stage->clamped_camera.size.width = stage->areas[k].ground->width;
100		stage->clamped_camera.size.height = stage->areas[k].ground->height;
101		
102		mimimi_sprite_tick(sprite);
103	}
104	
105	for (i = 0 ; i < stage->platform_set_count ; i++) mimimi_platform_set_tick(stage->platform_sets + i);
106	
107	x = player->physics.dx / 42;
108	y = player->physics.dy / 64 - 256;
109	mimimi_camera_tick(&stage->camera, &player->position, x, y);
110	mimimi_clamped_camera_tick(&stage->clamped_camera, image->width, image->height);
111	
112	for (i = 0 ; i < stage->areas[j].background_count ; i++) {
113		mimimi_background_tick(stage->areas[j].backgrounds + i, image, &stage->clamped_camera.output, &player->offset);
114	}
115	for (i = 0 ; i < stage->platform_set_count ; i++) {
116		mimimi_platform_set_display_tick(stage->platform_sets + i, image, &stage->clamped_camera.output);
117	}
118	for (i = 0 ; i < stage->sprite_count ; i++) {
119		mimimi_display_tick(image, stage->sprites + i, &stage->clamped_camera.output);
120	}
121	for (i = 0 ; i < stage->areas[j].foreground_count ; i++) {
122		mimimi_background_tick(stage->areas[j].foregrounds + i, image, &stage->clamped_camera.output, &player->offset);
123	}
124	
125	mimimi_boxing(&stage->clamped_camera.size, image);
126	
127	count = sizeof stage->sounds / sizeof *stage->sounds;
128	k = sizeof input->notes / sizeof *input->notes;
129	
130	for (i = 0 ; i < k ; i++) input->notes[i].volume = 0;
131	
132	for (i = 0 ; i < count ; i++) {
133		sound = stage->sounds + i;
134		if (sound->current >= sound->sound.count) continue;
135		for (k = 0 ; k < 16 ; k++) input->notes[i * 16 + k] = sound->sound.notes[sound->current][k];
136		sound->current++;
137	}
138}
139
140struct mimimi_sprite *mimimi_spawn(struct mimimi_stage *stage, struct mimimi_model *model, int x, int y, int width, int height)
141{
142	int i;
143	
144	if (stage->sprite_count == 0) stage->sprites = NULL;
145	
146	i = stage->sprite_count++;
147	
148	stage->sprites = realloc(stage->sprites, sizeof *stage->sprites * stage->sprite_count);
149	if (stage->sprites == NULL) exit(1);
150	
151	mimimi_sprite(stage->sprites + i, model, NULL, x, y, width, height);
152	
153	if (i == 0) {
154		stage->camera = stage->sprites[i].position;
155		stage->camera.y -= 256;
156	}
157	
158	return stage->sprites + i;
159}
160
161void mimimi_background(struct mimimi_image *image, struct mimimi_ground *ground, unsigned char *colors)
162{
163	int x, y;
164	unsigned char color;
165	
166	image->width = ground->width * 16;
167	image->height = ground->height * 16;
168	image->colors = malloc(image->width * image->height);
169	if (image->colors == NULL) exit(1);
170	
171	for (y = 0 ; y < image->height ; y++) {
172		for (x = 0 ; x < image->width ; x++) {
173			color = colors[mimimi_ground_tile(ground, x / 16, y / 16)];
174			image->colors[x + y * image->width] = color;
175		}
176	}
177}
178
179void mimimi_play_sound(struct mimimi_stage *stage, struct mimimi_sound *sound)
180{
181	int i;
182	int count;
183	
184	count = sizeof stage->sounds / sizeof *stage->sounds;
185	
186	for (i = 0 ; i < count ; i++) {
187		if (stage->sounds[i].current >= stage->sounds[i].sound.count) break;
188	}
189	
190	if (i == count) return;
191	
192	stage->sounds[i].sound = *sound;
193	stage->sounds[i].current = 0;
194}
195
196void mimimi_stage_jump(void *data)
197{
198	static struct mimimi_sound sound = {{0}, 0};
199	
200	struct mimimi_stage_jump *jump;
201	
202	jump = data;
203	if (jump->sprite->physics.airborne == 0) mimimi_play_sound(jump->stage, &sound);
204	mimimi_jump(jump->sprite);
205}