Mirai's Miscellaneous Misadventures

M48 / core / effects.c

/* license: AGPLv3 or later */
/* copyright 2023 zamfofex */

#include <mimimi.h>

void mimimi_conveyor_tick(struct mimimi_conveyor *conveyor)
{
	struct mimimi_sprite *sprite;
	struct mimimi_ground *ground;
	unsigned char was_airborne;
	int x1, x2, y;
	
	sprite = conveyor->sprite;
	ground = conveyor->ground;
	was_airborne = conveyor->was_airborne;
	
	conveyor->was_airborne = sprite->physics.airborne;
	
	if (sprite->physics.airborne != 0)
	{
		if (was_airborne == 0)
			sprite->physics.dx += conveyor->speed;
		return;
	}
	
	x1 = (sprite->position.x - sprite->physics.width / 2) / 128;
	x2 = (sprite->position.x + sprite->physics.width / 2) / 128;
	y = (sprite->position.y + 64) / 128;
	
	if (mimimi_ground_tile(ground, x1, y) != 0 || mimimi_ground_tile(ground, x2, y) != 0)
		sprite->position.x += conveyor->speed;
}

void mimimi_positioned_physics_tick(struct mimimi_positioned_physics *physics, struct mimimi_ground *ground)
{
	int dx, dy;
	unsigned char was_airborne;
	struct mimimi_position other_position;
	unsigned char airborne;
	
	dx = physics->transform.x - physics->previous.x;
	dy = physics->transform.y - physics->previous.y;
	
	physics->previous = physics->transform;
	
	was_airborne = physics->was_airborne;
	physics->was_airborne = physics->other.airborne;
	
	airborne = physics->physics->airborne;
	
	physics->other.dx = physics->physics->dx;
	physics->other.dy = physics->physics->dy;
	physics->other.width = physics->physics->width;
	physics->other.height = physics->physics->height;
	
	other_position = *physics->position;
	other_position.x -= physics->transform.x;
	other_position.y -= physics->transform.y;
	
	if (physics->other.airborne == 0)
	{
		other_position.x += dx;
		other_position.y += dy;
	}
	
	if (physics->physics->airborne != 0) physics->other.airborne = 1;
	mimimi_collision_physics_tick(&physics->other, &other_position, ground);
	if (physics->other.airborne == 0) physics->physics->airborne = 0;
	
	if (airborne == 0) return;
	
	other_position.x += physics->transform.x;
	other_position.y += physics->transform.y;
	
	*physics->position = other_position;
	
	physics->physics->dx = physics->other.dx;
	physics->physics->dy = physics->other.dy;
	
	if (physics->other.airborne != 0 && was_airborne == 0)
	{
		physics->physics->dx += dx;
		physics->physics->dy += dy;
	}
}

void mimimi_positioned_physics(struct mimimi_positioned_physics *physics, struct mimimi_physics *other, struct mimimi_position *position)
{
	mimimi_physics(&physics->other, 0, 0);
	physics->physics = other;
	physics->position = position;
	physics->transform.x = 0;
	physics->transform.y = 0;
	physics->previous = *position;
	physics->was_airborne = other->airborne;
}

void mimimi_trampoline_tick(struct mimimi_trampoline *trampoline)
{
	struct mimimi_sprite *sprite;
	struct mimimi_ground *ground;
	int dy;
	int x1, x2, y;
	
	sprite = trampoline->sprite;
	ground = trampoline->ground;
	
	dy = trampoline->dy;
	trampoline->dy = 0;
	
	if (sprite->physics.airborne != 0)
	{
		trampoline->dy = sprite->physics.dy;
		return;
	}
	
	if (dy == 0) return;
	
	x1 = (sprite->position.x - sprite->physics.width / 2) / 128;
	x2 = (sprite->position.x + sprite->physics.width / 2) / 128;
	y = (sprite->position.y + 64) / 128;
	
	if (mimimi_ground_tile(ground, x1, y) != 0) return;
	if (mimimi_ground_tile(ground, x2, y) != 0) return;
	
	sprite->physics.airborne = 1;
	sprite->physics.dy -= dy * trampoline->restitution / 256;
}