Mirai's Miscellaneous Misadventures
M51 / core / stages.c
1
2
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}