Mirai's Miscellaneous Misadventures

M53 / core / displays.c

1/* license: AGPLv3 or later */
2/* copyright 2024 zamfofex */
3
4/* note: a lot of this file assumes C99 division rules */
5/* note: is this worthwhile fixing? */
6
7#include <stdlib.h>
8#include "../mimimi.h"
9
10void mimimi_camera_stamp(struct mimimi_image *target,
11    struct mimimi_position *camera, int x, int y, int z,
12    struct mimimi_image *source)
13{
14    z += 8;
15    if (z <= 0) return;
16
17    x -= camera->x;
18    x = mimimi_div_up(x, z);
19    x += target->width / 2;
20
21    y -= camera->y;
22    y = mimimi_div_up(y, z);
23    y += target->height / 2;
24
25    mimimi_stamp(target, x, y, source);
26}
27
28static void mimimi_sprite_jumping(struct mimimi_image *image,
29    struct mimimi_sprite *sprite)
30{
31    static struct mimimi_pose pose0 = { 0 };
32    static struct mimimi_pose poses[2] = { 0 };
33
34    int slant;
35    int n;
36    int dx, dy;
37    int y_angle;
38
39    n = sprite->direction == 1 ? 1 : -1;
40
41    dx = sprite->physics.dx * -n;
42    dy = sprite->physics.dy;
43
44    if (dx < 0)
45        dx = 0;
46    if (dx > 8191)
47        dx = 8191;
48
49    dy += 8192;
50    if (dy < 0)
51        dy = 0;
52    if (dy > 16383)
53        dy = 16383;
54
55    slant = 64 * dx / 8192 * n;
56    y_angle = 64 + (20 + 20 * dx / 8192) * n;
57
58    poses[0] = pose0;
59    poses[1] = pose0;
60
61    poses[0].layers[0].y_angle = y_angle;
62    poses[0].layers[0].slant = -slant * 2;
63    poses[0].layers[1].slant = slant * 2;
64    poses[0].layers[4].slant = -slant / 2;
65    poses[0].layers[5].slant = -slant / 2;
66
67    poses[1].layers[0].y_angle = y_angle;
68    poses[1].layers[2].slant = -slant * 2;
69    poses[1].layers[3].slant = -slant * 2;
70    poses[1].layers[4].slant = slant * 2;
71    poses[1].layers[5].slant = slant * 2;
72
73    poses[0].x = image->width / 2;
74    poses[0].y = image->height - 15;
75    poses[1].x = image->width / 2;
76    poses[1].y = image->height - 15;
77
78    mimimi_interpolate(poses, poses + 1, dy, 16384);
79    mimimi_pose(image, sprite->model, poses);
80}
81
82static void mimimi_sprite_falling(struct mimimi_image *image,
83    struct mimimi_sprite *sprite)
84{
85    static struct mimimi_pose pose = { 0 };
86
87    int n;
88
89    n = sprite->direction == 1 ? 1 : -1;
90
91    pose.layers[0].z_angle = n;
92    pose.layers[0].y_angle = 64 + 32 * n;
93    pose.layers[4].slant = 96 * n;
94    pose.layers[5].slant = 96 * n;
95    pose.layers[2].z_angle = n;
96    pose.layers[2].slant = -96;
97    pose.layers[3].z_angle = n;
98    pose.layers[3].slant = 96;
99
100    image->width = 48;
101    image->height = 24;
102
103    pose.x = image->width / 2 - 4 * n;
104    pose.y = image->height - 8;
105    mimimi_pose(image, sprite->model, &pose);
106}
107
108static void mimimi_sprite_knocked(struct mimimi_image *image,
109    struct mimimi_sprite *sprite)
110{
111    static struct mimimi_pose pose = { 0 };
112
113    int n;
114
115    n = sprite->direction == 1 ? 1 : -1;
116
117    pose.layers[0].slant = 0;
118    pose.layers[0].z_angle = n;
119    pose.layers[0].y_angle = 64 + 32 * n;
120
121    image->width = 48;
122    image->height = 24;
123
124    pose.x = image->width / 2 - 4 * n;
125    pose.y = image->height - 8;
126    mimimi_pose(image, sprite->model, &pose);
127}
128
129static void mimimi_sprite_walking(struct mimimi_image *image,
130    struct mimimi_sprite *sprite)
131{
132    static struct mimimi_pose pose0 = { 0 };
133    static struct mimimi_pose poses[2] = { 0 };
134
135    int slant, y_angle;
136    int intent;
137    int n;
138    int dx;
139    struct mimimi_pose *a, *b;
140    int i;
141    int y;
142
143    n = sprite->direction == 1 ? 1 : -1;
144
145    dx = sprite->physics.dx * -n;
146    if (dx < 0)
147        dx = 0;
148    if (dx > 8191)
149        dx = 8191;
150
151    intent = dx / 16;
152    slant = intent * n;
153    y_angle = 64 + (20 + 20 * dx / 8192) * n;
154
155    poses[0] = pose0;
156    poses[1] = pose0;
157
158    poses[0].layers[0].y_angle = y_angle;
159    poses[1].layers[0].y_angle = y_angle;
160
161    poses[0].layers[0].slant = -slant / 8;
162    poses[1].layers[0].slant = -slant / 8;
163
164    poses[0].layers[1].slant = slant / 8;
165    poses[1].layers[1].slant = slant / 8;
166
167    poses[1].layers[4].slant = slant / 2;
168    poses[0].layers[4].slant = -slant / 3;
169    poses[1].layers[8].slant = -slant / 8;
170    poses[0].layers[8].slant = -slant / 16;
171
172    poses[0].layers[5].slant = slant / 2;
173    poses[1].layers[5].slant = -slant / 4;
174    poses[0].layers[9].slant = -slant / 8;
175    poses[1].layers[9].slant = -slant / 16;
176
177    poses[0].layers[2].slant = slant / 6;
178    poses[1].layers[2].slant = -slant / 2;
179    poses[0].layers[6].slant = slant / 6;
180    poses[1].layers[6].slant = slant / 2;
181    poses[1].layers[6].y = intent / 128;
182
183    poses[1].layers[3].slant = slant / 6;
184    poses[0].layers[3].slant = -slant / 2;
185    poses[1].layers[7].slant = slant / 6;
186    poses[0].layers[7].slant = slant / 2;
187    poses[0].layers[7].y = intent / 128;
188
189    sprite->animation_time += dx / 1024;
190
191    /* do not assume 'char' is eight bits */
192    sprite->animation_time &= 0xFF;
193
194    if (sprite->animation_time < 128) {
195        a = poses;
196        b = poses + 1;
197        i = sprite->animation_time;
198    } else {
199        a = poses + 1;
200        b = poses;
201        i = sprite->animation_time - 128;
202    }
203
204    y = sprite->landing_time * dx / 0x8000;
205
206    a->layers[8].y = 128 + mimimi_sine[sprite->animation_time * 8];
207    a->layers[8].y *= intent;
208    a->layers[8].y /= 0x8000;
209    a->layers[8].y += y;
210    b->layers[8].y = a->layers[8].y;
211
212    a->layers[9].y = 128 - mimimi_sine[sprite->animation_time * 8];
213    a->layers[9].y *= intent;
214    a->layers[9].y /= 0x8000;
215    a->layers[9].y += y;
216    b->layers[9].y = a->layers[9].y;
217
218    poses[0].layers[0].y = 128 + mimimi_cosine[i * 16];
219    poses[0].layers[0].y *= intent * (16 - sprite->landing_time);
220    poses[0].layers[0].y /= 0x8000 * 16;
221    poses[0].layers[0].y -= y;
222    poses[1].layers[0].y = poses[0].layers[0].y;
223
224    a->x = image->width / 2;
225    a->y = image->height - 15;
226    b->x = a->x;
227    b->y = a->y;
228
229    mimimi_interpolate(a, b, i, 128);
230    mimimi_pose(image, sprite->model, a);
231}
232
233void mimimi_display_tick(struct mimimi_image *target,
234    struct mimimi_sprite *sprite, struct mimimi_position *camera)
235{
236    static unsigned char colors[24 * 48];
237
238    struct mimimi_physics *physics;
239    struct mimimi_life *life;
240    struct mimimi_walk *walk;
241    struct mimimi_image image;
242    int x, y;
243    int trail;
244
245    physics = &sprite->physics;
246    life = &sprite->life;
247    walk = &sprite->walk;
248
249    image.width = 24;
250    image.height = 48;
251    image.colors = colors;
252
253    for (y = 0; y < image.height; y++)
254        for (x = 0; x < image.width; x++)
255            colors[x + y * image.width] = 0;
256
257    if (life->knocked_time == 0 && walk->direction != 0)
258        sprite->direction = walk->direction;
259
260    if (physics->airborne != 0)
261        sprite->landing_time = 16;
262    else if (sprite->landing_time > 0)
263        sprite->landing_time--;
264
265    if (life->knocked_time == 0) {
266        if (physics->airborne == 0)
267            mimimi_sprite_walking(&image, sprite);
268        else
269            mimimi_sprite_jumping(&image, sprite);
270    } else {
271        if (physics->airborne == 0)
272            mimimi_sprite_knocked(&image, sprite);
273        else
274            mimimi_sprite_falling(&image, sprite);
275    }
276
277    trail = sprite->trail;
278    sprite->trailing_y = mimimi_div(sprite->trailing_y * trail, 256);
279    sprite->trailing_y += mimimi_div(sprite->position.y * (256 - trail), 256);
280    sprite->trail = trail * 3 / 4;
281
282    mimimi_camera_stamp(target, camera, sprite->position.x - image.width * 4,
283        sprite->trailing_y - image.height * 8 + 32, 0, &image);
284}
285
286void mimimi_background_tick(struct mimimi_background *background,
287    struct mimimi_image *image, struct mimimi_position *camera,
288    struct mimimi_position *offset)
289{
290    mimimi_camera_stamp(image, camera, background->x + offset->x,
291        background->y + offset->y, background->z, &background->image);
292}