Mirai's Miscellaneous Misadventures

M50 / core / stages.c

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