Mirai's Miscellaneous Misadventures

M27 / test / chapter.c

1// copyright 2022 zamfofex
2// license: AGPLv3 or later
3
4#include <mimimi/chapters.h>
5#include <mimimi/senran-kagura/characters.h>
6#include <mimimi/appearances.h>
7#include <mimimi/allocators.h>
8#include <mimimi/ground.h>
9#include <mimimi/compound-behaviors.h>
10#include <mimimi/geometry.h>
11#include <mimimi/assets.h>
12#include <mimimi/engines.h>
13#include <mimimi/controls.h>
14#include <mimimi/sprites.h>
15#include <mimimi/cameras.h>
16#include <mimimi/behaviors.h>
17#include <mimimi/font.h>
18#include <mimimi/fonts.h>
19#include <mimimi/animations.h>
20#include <mimimi/collisions.h>
21#include <mimimi/test.h>
22
23#include "ground.c"
24
25static void mimimi_test_animation_set(struct mimimi_animation_set *set, struct mimimi_behavior *compound, struct mimimi_allocator *allocator)
26{
27	int animation_count = 8;
28	int image_count = 6;
29	int width = 48;
30	int height = 48;
31	
32	int total_animation_count = 2 + animation_count;
33	int total_image_count = 2 + image_count * animation_count + image_count;
34	
35	struct mimimi_animation *animations = mimimi_compound_allocate(compound, total_animation_count * sizeof *animations, allocator);
36	struct mimimi_image *images = mimimi_compound_allocate(compound, total_image_count * sizeof *images, allocator);
37	
38	set->standing = animations;
39	set->standing_animation_count = animation_count;
40	animations += animation_count;
41	
42	for (int i = 0 ; i < animation_count ; i++)
43	{
44		struct mimimi_animation *animation = set->standing + i;
45		animation->count = image_count;
46		animation->images = images;
47		images += image_count;
48		
49		for (int i = 0 ; i < image_count ; i++)
50		{
51			struct mimimi_image *image = animation->images + i;
52			image->width = width;
53			image->height = height;
54			image->colors = mimimi_compound_allocate(compound, width * height, allocator);
55			for (int i = 0 ; i < width * height ; i++) image->colors[i] = 0;
56		}
57	}
58	
59	struct mimimi_animation *knocked = animations++;
60	knocked->count = 1;
61	knocked->images = images++;
62	knocked->images[0].width = width;
63	knocked->images[0].height = height;
64	knocked->images[0].colors = mimimi_compound_allocate(compound, width * height, allocator);
65	for (int i = 0 ; i < width * height ; i++) knocked->images[0].colors[i] = 0;
66	
67	struct mimimi_animation *falling = animations++;
68	falling->count = 1;
69	falling->images = images++;
70	falling->images[0].width = width;
71	falling->images[0].height = height;
72	falling->images[0].colors = mimimi_compound_allocate(compound, width * height, allocator);
73	for (int i = 0 ; i < width * height ; i++) falling->images[0].colors[i] = 0;
74	
75	set->knocked = knocked;
76	set->falling = falling;
77	
78	for (int i = 0 ; i < width * height ; i++)
79	{
80		knocked->images[0].colors[i] = 0;
81		falling->images[0].colors[i] = 0;
82	}
83	
84	set->jumping = images;
85	set->jumping_image_count = image_count;
86	images += image_count;
87	
88	for (int i = 0 ; i < image_count ; i++)
89	{
90		struct mimimi_image *image = set->jumping + i;
91		image->width = width;
92		image->height = height;
93		image->colors = mimimi_compound_allocate(compound, width * height, allocator);
94		for (int i = 0 ; i < width * height ; i++) image->colors[i] = 0;
95	}
96}
97
98static struct mimimi_appearance *mimimi_test_appearance(struct mimimi_behavior *compound, struct mimimi_allocator *allocator)
99{
100	struct mimimi_appearance *appearance = mimimi_compound_allocate(compound, sizeof *appearance, allocator);
101	
102	mimimi_test_animation_set(&appearance->left, compound, allocator);
103	mimimi_test_animation_set(&appearance->right, compound, allocator);
104	
105	return appearance;
106}
107
108struct mimimi_test_sprite
109{
110	int x, y;
111	struct mimimi_model *model;
112};
113
114static void mimimi_test_player(struct mimimi_behavior *compound, struct mimimi_chapter *chapter, struct mimimi_sprite *player, struct mimimi_allocator *allocator)
115{
116	struct mimimi_history *history = mimimi_compound_allocate(compound, sizeof *history, allocator);
117	mimimi_compound(compound, mimimi_history(history, chapter, allocator));
118	
119	struct mimimi_jump *jump = mimimi_compound_allocate(compound, sizeof *jump, allocator);
120	struct mimimi_behavior *jump_behavior = mimimi_jump(jump, player->physics, allocator);
121	mimimi_compound(compound, mimimi_finalizer(jump_behavior->data, jump_behavior->finish, allocator));
122	
123	// struct mimimi_dash *dash = mimimi_compound_allocate(compound, sizeof *dash, allocator);
124	// struct mimimi_behavior *dash_behavior = mimimi_dash(dash, player->physics, player->walk, allocator);
125	// mimimi_compound(compound, mimimi_finalizer(dash_behavior->data, dash_behavior->finish, allocator));
126	// struct mimimi_behavior *throttled_dash = mimimi_throttle(compound, dash_behavior, 32, allocator);
127	
128	struct mimimi_behavior *jump_choice = mimimi_choice(&player->physics->airborne, mimimi_noop, jump_behavior, allocator);
129	
130	struct mimimi_controls *mirai_controls = mimimi_compound_allocate(compound, sizeof *mirai_controls, allocator);
131	player->awake_behavior = mimimi_controls(mirai_controls, player->walk, history, allocator);
132	mimimi_compound(compound, mimimi_finalizer(player->awake_behavior->data, player->awake_behavior->finish, allocator));
133	mirai_controls->jump = jump_choice;
134}
135
136struct mimimi_chapter *mimimi_test(struct mimimi_engine *engine)
137{
138	struct mimimi_allocator *allocator = engine->allocator;
139	
140	struct mimimi_behavior *compound = mimimi_compound_behavior(allocator);
141	
142	struct mimimi_chapter *chapter = mimimi_compound_allocate(compound, sizeof *chapter, allocator);
143	chapter->behavior = compound;
144	
145	struct mimimi_position *camera = mimimi_compound_allocate(compound, sizeof *camera, allocator);
146	
147	struct mimimi_test_sprite infos[] =
148	{
149		{110, 28, mimimi_mirai_flash},
150		// {x, y, mimimi_ryoubi_flash},
151		// {x, y, mimimi_ryouna_flash},
152	};
153	
154	int count = sizeof infos / sizeof *infos;
155	
156	struct mimimi_position **positions = mimimi_compound_allocate(compound, count * sizeof *positions, allocator);
157	mimimi_compound(compound, mimimi_collision(count, positions, 128, 256, 512, 64, allocator));
158	
159	int *directions = mimimi_compound_allocate(compound, count * sizeof *directions, allocator);
160	
161	struct mimimi_sprite **sprites = (allocator->allocate)(count * sizeof *sprites);
162	
163	for (int i = 0 ; i < count ; i++)
164	{
165		struct mimimi_test_sprite *info = infos + i;
166		
167		struct mimimi_sprite *sprite = mimimi_sprite(&mimimi_test_ground, info->x * 128, info->y * 128, 80, 250, allocator);
168		mimimi_compound(compound, sprite->behavior);
169		sprites[i] = sprite;
170		
171		if (i == 0)
172		{
173			mimimi_test_player(compound, chapter, sprite, allocator);
174			mimimi_compound(compound, mimimi_camera(camera, sprite->position, 0, -512, allocator));
175		}
176		else
177		{
178			mimimi_compound(compound, mimimi_stationary(directions + i, &sprite->position->x, &sprites[i]->position->x, allocator));
179		}
180		
181		positions[i] = sprite->position;
182	}
183	
184	struct mimimi_image *background = mimimi_compound_allocate(compound, sizeof *background, allocator);
185	background->colors = mimimi_compound_allocate(compound, mimimi_test_ground.width * 16 * mimimi_test_ground.height * 16, allocator);
186	
187	background->width = mimimi_test_ground.width * 16;
188	background->height = mimimi_test_ground.height * 16;
189	
190	static unsigned char ground_colors[] = {0x0D, 0x05, 0x24, 0x28, 0x92, 0xBC, 0x77};
191	
192	for (int y = 0 ; y < mimimi_test_ground.height * 16 ; y++)
193	for (int x = 0 ; x < mimimi_test_ground.width * 16 ; x++)
194	{
195		unsigned char color = ground_colors[mimimi_test_ground.tiles[x / 16 + y / 16 * mimimi_test_ground.width]];
196		background->colors[x + y * mimimi_test_ground.width * 16] = color;
197	}
198	
199	mimimi_compound(compound, mimimi_background(engine, camera, background, 0, allocator));
200	
201	for (int i = 0 ; i < count ; i++)
202	{
203		struct mimimi_test_sprite *info = infos + i;
204		struct mimimi_sprite *sprite = sprites[i];
205		
206		struct mimimi_appearance *appearance = mimimi_test_appearance(compound, allocator);
207		mimimi_appearance(appearance, info->model, 24, 48, allocator);
208		mimimi_compound(compound, mimimi_display(engine, camera, sprite, appearance, directions + i, allocator));
209	}
210	
211	(allocator->deallocate)(sprites);
212	
213	struct mimimi_image *overlay = mimimi_compound_allocate(compound, sizeof *overlay, allocator);
214	overlay->width = 256;
215	overlay->height = 64;
216	overlay->colors = mimimi_compound_allocate(compound, overlay->width * overlay->height, allocator);
217	
218	for (int i = 0 ; i < overlay->width * overlay->height ; i++)
219		overlay->colors[i] = 0;
220	
221	struct mimimi_image *glyphs = (*allocator->allocate)(mimimi_font_image_count * sizeof *glyphs);
222	unsigned char *colors = (*allocator->allocate)(mimimi_font_color_count);
223	
224	for (int i = 0 ; i < mimimi_font_image_count ; i++)
225		glyphs[i].colors = colors + i * mimimi_font_image_color_count;
226	
227	mimimi_glyphs(glyphs, mimimi_font, 0x76);
228	
229	mimimi_text(overlay, glyphs, 16, 16, "Mirai's Miscellaneous Misadventures M27");
230	mimimi_text(overlay, glyphs, 16, 32, "a Senran Kagura fangame, June 28 of 2022");
231	
232	(*allocator->deallocate)(colors);
233	(*allocator->deallocate)(glyphs);
234	
235	mimimi_compound(compound, mimimi_overlay(engine, overlay, 0, 0, allocator));
236	
237	return chapter;
238}