Mirai's Miscellaneous Misadventures

M52 / 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)
12			return y;
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	{
21		if (ground->tiles[position->x + position->y * ground->width] == 2)
22			return;
23	}
24}
25
26void mimimi_stage(struct mimimi_stage *stage, struct mimimi_ground **grounds, int count)
27{
28	int i;
29	struct mimimi_position offset;
30	int left_floor_y, right_floor_y;
31	struct mimimi_area *area;
32	
33	stage->sprite_count = 0;
34	stage->area_count = count;
35	stage->areas = malloc(sizeof *stage->areas * count);
36	if (stage->areas == NULL) exit(1);
37	stage->clamped_camera.input = &stage->camera;
38	stage->platform_set_count = 0;
39	
40	for (i = 0 ; i < count ; i++)
41	{
42		area = stage->areas + i;
43		area->ground = grounds[i];
44		area->background_count = 0;
45		area->foreground_count = 0;
46	}
47	
48	mimimi_origin(grounds[0], &offset);
49	offset.x *= -1;
50	offset.y *= -1;
51	stage->areas[0].ground = grounds[0];
52	stage->areas[0].offset = offset;
53	
54	left_floor_y = mimimi_ground_floor(grounds[0], 0);
55	
56	for (i = 1 ; i < count ; i++)
57	{
58		area = stage->areas + i;
59		area->ground = grounds[i];
60		right_floor_y = mimimi_ground_floor(grounds[i], grounds[i]->width - 1);
61		offset.x -= grounds[i]->width;
62		offset.y -= right_floor_y - left_floor_y;
63		left_floor_y = mimimi_ground_floor(grounds[i], 0);
64		area->offset = offset;
65	}
66}
67
68void mimimi_stage_tick(struct mimimi_stage *stage, struct mimimi_image *image)
69{
70	struct mimimi_sprite *sprite, *player;
71	int i, j, k;
72	int x, y;
73	
74	player = stage->sprites;
75	
76	j = 0;
77	while (player->position.x < stage->areas[j].offset.x * 128) j++;
78	
79	for (i = 0 ; i < stage->sprite_count ; i++)
80	{
81		sprite = stage->sprites + i;
82		
83		k = 0;
84		while (sprite->position.x < stage->areas[k].offset.x * 128) k++;
85		sprite->ground = stage->areas[k].ground;
86		sprite->offset = stage->areas[k].offset;
87		sprite->offset.x *= 128;
88		sprite->offset.y *= 128;
89		
90		stage->clamped_camera.offset = stage->areas[k].offset;
91		stage->clamped_camera.size.width = stage->areas[k].ground->width;
92		stage->clamped_camera.size.height = stage->areas[k].ground->height;
93		
94		mimimi_sprite_tick(sprite);
95	}
96	
97	for (i = 0 ; i < stage->platform_set_count ; i++)
98		mimimi_platform_set_tick(stage->platform_sets + i);
99	
100	x = player->physics.dx / 42;
101	y = player->physics.dy / 64 - 256;
102	mimimi_camera_tick(&stage->camera, &player->position, x, y);
103	mimimi_clamped_camera_tick(&stage->clamped_camera, image->width, image->height);
104	
105	for (i = 0 ; i < stage->areas[j].background_count ; i++)
106		mimimi_background_tick(stage->areas[j].backgrounds + i, image, &stage->clamped_camera.output, &player->offset);
107	for (i = 0 ; i < stage->platform_set_count ; i++)
108		mimimi_platform_set_display_tick(stage->platform_sets + i, image, &stage->clamped_camera.output);
109	for (i = 0 ; i < stage->sprite_count ; i++)
110		mimimi_display_tick(stage->displays[i], image, stage->sprites + i);
111	for (i = 0 ; i < stage->areas[j].foreground_count ; i++)
112		mimimi_background_tick(stage->areas[j].foregrounds + i, image, &stage->clamped_camera.output, &player->offset);
113	
114	mimimi_boxing(&stage->clamped_camera.size, image);
115}
116
117struct mimimi_sprite *mimimi_spawn(struct mimimi_stage *stage, struct mimimi_display *display, int x, int y, int width, int height)
118{
119	int i;
120	
121	if (stage->sprite_count == 0)
122	{
123		stage->sprites = NULL;
124		stage->displays = NULL;
125	}
126	
127	i = stage->sprite_count++;
128	
129	stage->sprites = realloc(stage->sprites, sizeof *stage->sprites * stage->sprite_count);
130	stage->displays = realloc(stage->displays, sizeof *stage->displays * stage->sprite_count);
131	if (stage->sprites == NULL) exit(1);
132	if (stage->displays == NULL) exit(1);
133	
134	mimimi_sprite(stage->sprites + i, NULL, x, y, width, height);
135	
136	display->camera = &stage->clamped_camera.output;
137	display->animation_time = 0;
138	display->direction = 1;
139	
140	stage->displays[i] = display;
141	
142	if (i == 0)
143	{
144		stage->camera = stage->sprites[i].position;
145		stage->camera.y -= 256;
146	}
147	
148	return stage->sprites + i;
149}
150
151void mimimi_background(struct mimimi_image *image, struct mimimi_ground *ground, unsigned char *colors)
152{
153	int x, y;
154	unsigned char color;
155	
156	image->width = ground->width * 16;
157	image->height = ground->height * 16;
158	image->colors = malloc(image->width * image->height);
159	if (image->colors == NULL) exit(1);
160	
161	for (y = 0 ; y < image->height ; y++)
162	for (x = 0 ; x < image->width ; x++)
163	{
164		color = colors[mimimi_ground_tile(ground, x / 16, y / 16)];
165		image->colors[x + y * image->width] = color;
166	}
167}