Mirai's Miscellaneous Misadventures

M20 / core / physics.c

1// copyright 2022 zamfofex
2// license: AGPLv3 or later
3
4static void mimimi_wall_physics(struct mimimi_physics_data *data)
5{
6	struct mimimi_ground *ground = data->ground;
7	struct mimimi_position *position = data->position;
8	struct mimimi_physics *physics = data->physics;
9	
10	int x0 = position->x;
11	int y0 = position->y;
12	int x1 = physics->width / 2;
13	int y1 = physics->height;
14	
15	int top = (y0 - y1) / 128;
16	int top2 = top - 1;
17	int bottom = (y0 - 127) / 128;
18	int bottom2 = bottom - 1;
19	int left = (x0 - x1) / 128;
20	int right = (x0 + x1) / 128;
21	
22	if (
23		ground->tiles[left + bottom * ground->width] != 0 &&
24		ground->tiles[left + bottom2 * ground->width] != 0 ||
25		ground->tiles[left + top * ground->width] != 0 &&
26		ground->tiles[left + top2 * ground->width]
27	)
28	{
29		if (physics->dx < 0) physics->dx = 0;
30		position->x = (left + 1) * 128 + x1;
31	}
32	
33	if (
34		ground->tiles[right + bottom * ground->width] != 0 &&
35		ground->tiles[right + bottom2 * ground->width] != 0 ||
36		ground->tiles[right + top * ground->width] != 0 &&
37		ground->tiles[right + top2 * ground->width]
38	)
39	{
40		if (physics->dx > 0) physics->dx = 0;
41		position->x = right * 128 - x1 - 1;
42	}
43}
44
45static void mimimi_slope_physics(struct mimimi_physics_data *data)
46{
47	struct mimimi_ground *ground = data->ground;
48	struct mimimi_position *position = data->position;
49	struct mimimi_physics *physics = data->physics;
50	
51	int x0 = position->x;
52	int y0 = position->y;
53	int x1 = physics->width / 2;
54	int y1 = physics->height;
55	
56	int top = (y0 - y1) / 128;
57	int bottom = (y0 - 127) / 128;
58	int left = (x0 - x1) / 128;
59	int right = (x0 + x1) / 128;
60	
61	if (ground->tiles[left + bottom * ground->width] != 0 && ground->tiles[left + top * ground->width] == 0)
62		position->y = bottom * 128;
63	if (ground->tiles[right + bottom * ground->width] != 0 && ground->tiles[right + top * ground->width] == 0)
64		position->y = bottom * 128;
65}
66
67static void mimimi_ceiling_physics(struct mimimi_physics_data *data)
68{
69	struct mimimi_ground *ground = data->ground;
70	struct mimimi_position *position = data->position;
71	struct mimimi_physics *physics = data->physics;
72	
73	int x0 = position->x;
74	int y0 = position->y;
75	int x1 = physics->width / 2;
76	int y1 = physics->height;
77	
78	int top = (y0 - y1) / 128;
79	int top2 = top - 1;
80	int left = (x0 - x1) / 128;
81	int right = (x0 + x1) / 128;
82	
83	if (physics->dy > 0) return;
84	
85	if (ground->tiles[left + top * ground->width] != 0)
86	if (ground->tiles[right + top * ground->width] != 0)
87	if (ground->tiles[left + top2 * ground->width] != 0 || ground->tiles[right + top2 * ground->width] != 0)
88	{
89		physics->dy = 0;
90		position->y = (top + 1) * 128 + y1;
91	}
92}
93
94static void mimimi_landing_physics(struct mimimi_physics_data *data)
95{
96	struct mimimi_ground *ground = data->ground;
97	struct mimimi_position *position = data->position;
98	struct mimimi_physics *physics = data->physics;
99	
100	int x0 = position->x;
101	int y0 = position->y;
102	int x1 = physics->width / 2;
103	
104	int bottom = y0 / 128;
105	int left = (x0 - x1) / 128;
106	int right = (x0 + x1) / 128;
107	
108	if (physics->dy < 0) return;
109	
110	if (ground->tiles[left + bottom * ground->width] != 0 || ground->tiles[right + bottom * ground->width] != 0)
111	{
112		physics->airborne = 0;
113		physics->dy = 0;
114		position->y = bottom * 128;
115	}
116}
117
118static void mimimi_fall_physics(struct mimimi_physics_data *data)
119{
120	struct mimimi_ground *ground = data->ground;
121	struct mimimi_position *position = data->position;
122	struct mimimi_physics *physics = data->physics;
123	
124	int x0 = position->x;
125	int y0 = position->y;
126	int x1 = physics->width / 2;
127	
128	int bottom = y0 / 128;
129	int center = x0 / 128;
130	int left = (x0 - x1) / 128;
131	int right = (x0 + x1) / 128;
132	
133	if (ground->tiles[left + bottom * ground->width] == 0 && ground->tiles[right + bottom * ground->width] == 0)
134	{
135		if (ground->tiles[center + (bottom + 1) * ground->width] == 0)
136			// fall
137			physics->airborne = 1;
138		else
139			// step down
140			position->y = (bottom + 1) * 128;
141	}
142}
143
144static void mimimi_physics_dynamics(struct mimimi_physics_data *data)
145{
146	struct mimimi_position *position = data->position;
147	struct mimimi_physics *physics = data->physics;
148	
149	position->x += physics->dx;
150	position->y += physics->dy;
151}
152
153static void mimimi_ground_physics(struct mimimi_physics_data *data)
154{
155	struct mimimi_physics *physics = data->physics;
156	
157	physics->dx *= 5;
158	physics->dx /= 6;
159	physics->dy = 0;
160	
161	mimimi_physics_dynamics(data);
162	
163	mimimi_slope_physics(data);
164	mimimi_wall_physics(data);
165	mimimi_fall_physics(data);
166}
167
168static void mimimi_airborne_physics(struct mimimi_physics_data *data)
169{
170	struct mimimi_physics *physics = data->physics;
171	
172	physics->dx *= 17;
173	physics->dx /= 18;
174	physics->dy += physics->gravity;
175	
176	mimimi_physics_dynamics(data);
177	
178	mimimi_ceiling_physics(data);
179	mimimi_wall_physics(data);
180	mimimi_landing_physics(data);
181}