Mirai's Miscellaneous Misadventures

M24 / core / displays.c

1// copyright 2022 zamfofex
2// license: AGPLv3 or later
3
4#include <mimimi/allocators.h>
5#include <mimimi/behaviors.h>
6#include <mimimi/sprites.h>
7#include <mimimi/geometry.h>
8#include <mimimi/engines.h>
9#include <mimimi/chapters.h>
10#include <mimimi/assets.h>
11#include <mimimi/animations.h>
12#include <mimimi/appearances.h>
13
14struct mimimi_display
15{
16	struct mimimi_allocator *allocator;
17	struct mimimi_behavior *behavior;
18	struct mimimi_engine *engine;
19	struct mimimi_position *camera;
20	struct mimimi_sprite *sprite;
21	struct mimimi_appearance *appearance;
22	unsigned char animation_time;
23	unsigned char direction;
24};
25
26static void mimimi_camera_stamp(struct mimimi_engine *engine, struct mimimi_position *camera, int x, int y, int z, struct mimimi_image *image)
27{
28	z += 8;
29	if (z <= 0) return;
30	
31	x -= camera->x;
32	x += engine->size->width * z / 2;
33	x -= image->width * z / 2;
34	
35	y -= camera->y;
36	y += engine->size->height * z / 2;
37	y -= image->height * z;
38	
39	(*engine->stamp)(engine->data, x / z, y / z, image);
40}
41
42static void mimimi_display_behave(void *data)
43{
44	struct mimimi_display *display = data;
45	struct mimimi_sprite *sprite = display->sprite;
46	struct mimimi_appearance *appearance = display->appearance;
47	
48	struct mimimi_position *position = sprite->position;
49	struct mimimi_physics *physics = sprite->physics;
50	struct mimimi_life *life = sprite->life;
51	struct mimimi_walk *walk = sprite->walk;
52	
53	int dx;
54	int dy = physics->dy;
55	
56	if (walk->direction != 0) display->direction = walk->direction;
57	
58	struct mimimi_animation_set *animations;
59	
60	if (display->direction == 1)
61	{
62		dx = -physics->dx;
63		animations = &appearance->left;
64	}
65	if (display->direction == 2)
66	{
67		dx = physics->dx;
68		animations = &appearance->right;
69	}
70	
71	if (dx > 31) dx = 31;
72	if (dx < 0) dx = 0;
73	if (dy < 0) dy = 0;
74	
75	struct mimimi_animation *animation;
76	
77	int y = 0;
78	
79	if (life->knocked_time == 0)
80	{
81		animation = animations->standing + dx * animations->standing_animation_count / 32;
82		display->animation_time += dx / 4;
83	}
84	else
85	{
86		if (physics->airborne == 0)
87			animation = animations->knocked,
88			y = 128;
89		else
90			animation = animations->falling;
91		
92		display->animation_time += dy / 8;
93	}
94	
95	struct mimimi_image *image = animation->images + display->animation_time * animation->count / 256;
96	
97	mimimi_camera_stamp(display->engine, display->camera, position->x, position->y + y, 0, image);
98}
99
100static void mimimi_display_finish(void *data)
101{
102	struct mimimi_display *display = data;
103	(*display->allocator->deallocate)(display->behavior);
104	(*display->allocator->deallocate)(display);
105}
106
107struct mimimi_behavior *mimimi_display(struct mimimi_engine *engine, struct mimimi_position *camera, struct mimimi_sprite *sprite, struct mimimi_appearance *appearance, struct mimimi_allocator *allocator)
108{
109	struct mimimi_display *display = (*allocator->allocate)(sizeof *display);
110	display->allocator = allocator;
111	display->engine = engine;
112	display->camera = camera;
113	display->sprite = sprite;
114	display->appearance = appearance;
115	
116	display->animation_time = 0;
117	display->direction = 1;
118	
119	display->behavior = (*allocator->allocate)(sizeof *display->behavior);
120	display->behavior->behave = &mimimi_display_behave;
121	display->behavior->finish = &mimimi_display_finish;
122	display->behavior->data = display;
123	
124	return display->behavior;
125}
126
127struct mimimi_background
128{
129	struct mimimi_allocator *allocator;
130	struct mimimi_behavior *behavior;
131	struct mimimi_image *image;
132	struct mimimi_position *camera;
133	struct mimimi_engine *engine;
134	int offset;
135};
136
137static void mimimi_background_behave(void *data)
138{
139	struct mimimi_background *background_data = data;
140	mimimi_camera_stamp(background_data->engine, background_data->camera, background_data->image->width * 4, background_data->image->height * 8 - 7, background_data->offset, background_data->image);
141}
142
143static void mimimi_background_finish(void *data)
144{
145	struct mimimi_background *background_data = data;
146	(*background_data->allocator->deallocate)(background_data->behavior);
147	(*background_data->allocator->deallocate)(background_data);
148}
149
150struct mimimi_behavior *mimimi_background(struct mimimi_engine *engine, struct mimimi_position *camera, struct mimimi_image *image, int offset, struct mimimi_allocator *allocator)
151{
152	struct mimimi_background *data = (*allocator->allocate)(sizeof *data);
153	data->allocator = allocator;
154	data->image = image;
155	data->camera = camera;
156	data->engine = engine;
157	data->offset = offset;
158	
159	data->behavior = (*allocator->allocate)(sizeof *data->behavior);
160	data->behavior->behave = &mimimi_background_behave;
161	data->behavior->finish = &mimimi_background_finish;
162	data->behavior->data = data;
163	
164	return data->behavior;
165}
166
167struct mimimi_overlay
168{
169	struct mimimi_allocator *allocator;
170	struct mimimi_behavior *behavior;
171	struct mimimi_engine *engine;
172	struct mimimi_image *image;
173	int x;
174	int y;
175};
176
177static void mimimi_overlay_behave(void *data)
178{
179	struct mimimi_overlay *overlay_data = data;
180	struct mimimi_engine *engine = overlay_data->engine;
181	(*engine->stamp)(engine->data, overlay_data->x, overlay_data->y, overlay_data->image);
182}
183
184static void mimimi_overlay_finish(void *data)
185{
186	struct mimimi_background *overlay_data = data;
187	(*overlay_data->allocator->deallocate)(overlay_data->behavior);
188	(*overlay_data->allocator->deallocate)(overlay_data);
189}
190
191struct mimimi_behavior *mimimi_overlay(struct mimimi_engine *engine, struct mimimi_image *image, int x, int y, struct mimimi_allocator *allocator)
192{
193	struct mimimi_overlay *data = (*allocator->allocate)(sizeof *data);
194	data->allocator = allocator;
195	data->engine = engine;
196	data->image = image;
197	data->x = x;
198	data->y = y;
199	
200	data->behavior = (*allocator->allocate)(sizeof *data->behavior);
201	data->behavior->behave = &mimimi_overlay_behave;
202	data->behavior->finish = &mimimi_overlay_finish;
203	data->behavior->data = data;
204	
205	return data->behavior;
206}