Mirai's Miscellaneous Misadventures
M18 / core / sprites.c
#include <mimimi/sprites.h>
#include <mimimi/compound-behaviors.h>
#include <mimimi/allocators.h>
#include <mimimi/geometry.h>
#include <mimimi/behaviors.h>
#include <mimimi/ground.h>
struct mimimi_physics_data
{
struct mimimi_allocator *allocator;
struct mimimi_behavior *behavior;
struct mimimi_ground *ground;
struct mimimi_position *position;
struct mimimi_physics physics;
};
#include "physics.c"
static void mimimi_physics_behave(void *data)
{
struct mimimi_physics_data *physics_data = data;
struct mimimi_physics *physics = &physics_data->physics;
if (physics->airborne == 0)
mimimi_ground_physics(data);
else
mimimi_airborne_physics(data);
}
static void mimimi_physics_finish(void *data)
{
struct mimimi_physics_data *physics_data = data;
(*physics_data->allocator->deallocate)(physics_data->behavior);
(*physics_data->allocator->deallocate)(physics_data);
}
struct mimimi_behavior *mimimi_physics(struct mimimi_position *position, struct mimimi_ground *ground, struct mimimi_allocator *allocator)
{
struct mimimi_physics_data *data = (*allocator->allocate)(sizeof *data);
data->allocator = allocator;
data->position = position;
data->ground = ground;
data->physics.dx = 0;
data->physics.dy = 0;
data->physics.airborne = 1;
data->physics.width = 0;
data->physics.height = 0;
data->physics.gravity = 4;
data->behavior = (*allocator->allocate)(sizeof *data->behavior);
data->behavior->behave = &mimimi_physics_behave;
data->behavior->finish = &mimimi_physics_finish;
data->behavior->data = data;
return data->behavior;
}
struct mimimi_physics *mimimi_physics_attributes(struct mimimi_behavior *behavior)
{
struct mimimi_physics_data *data = behavior->data;
return &data->physics;
}
struct mimimi_life_data
{
struct mimimi_allocator *allocator;
struct mimimi_behavior *behavior;
struct mimimi_life life;
};
static void mimimi_live(void *data)
{
struct mimimi_life_data *life_data = data;
struct mimimi_life *life = &life_data->life;
if (life->knocked_time != 0)
{
life->knocked_time--;
life->immunity_time = life->recovery_time;
}
if (life->immunity_time != 0)
{
life->pristinity = life->max_pristinity;
life->immunity_time--;
}
if (life->pristinity < life->max_pristinity)
life->pristinity++;
}
static void mimimi_life_finish(void *data)
{
struct mimimi_life_data *life_data = data;
(*life_data->allocator->deallocate)(life_data->behavior);
(*life_data->allocator->deallocate)(life_data);
}
struct mimimi_behavior *mimimi_life(struct mimimi_allocator *allocator)
{
struct mimimi_life_data *data = (*allocator->allocate)(sizeof *data);
data->allocator = allocator;
data->life.knocked_time = 0;
data->life.immunity_time = 0;
data->life.pristinity = 256;
data->life.max_pristinity = 256;
data->life.recovery_time = 64;
data->behavior = (*allocator->allocate)(sizeof *data->behavior);
data->behavior->behave = &mimimi_live;
data->behavior->finish = &mimimi_life_finish;
data->behavior->data = data;
return data->behavior;
}
struct mimimi_life *mimimi_life_attributes(struct mimimi_behavior *behavior)
{
struct mimimi_life_data *data = behavior->data;
return &data->life;
}
struct mimimi_fall_data
{
struct mimimi_allocator *allocator;
struct mimimi_behavior *behavior;
struct mimimi_physics *physics;
struct mimimi_life *life;
struct mimimi_fall fall;
};
static void mimimi_fall_behave(void *data)
{
struct mimimi_fall_data *fall_data = data;
if (fall_data->physics->dy > fall_data->fall.max_speed)
if (fall_data->life->knocked_time < fall_data->fall.knocked_time)
fall_data->life->knocked_time = fall_data->fall.knocked_time;
}
static void mimimi_fall_finish(void *data)
{
struct mimimi_fall_data *fall_data = data;
(*fall_data->allocator->deallocate)(fall_data->behavior);
(*fall_data->allocator->deallocate)(fall_data);
}
struct mimimi_behavior *mimimi_fall(struct mimimi_physics *physics, struct mimimi_life *life, struct mimimi_allocator *allocator)
{
struct mimimi_fall_data *data = (*allocator->allocate)(sizeof *data);
data->allocator = allocator;
data->physics = physics;
data->life = life;
data->fall.max_speed = 128;
data->fall.knocked_time = 64;
data->behavior = (*allocator->allocate)(sizeof *data->behavior);
data->behavior->behave = &mimimi_fall_behave;
data->behavior->finish = &mimimi_fall_finish;
data->behavior->data = data;
return data->behavior;
}
struct mimimi_fall *mimimi_fall_attributes(struct mimimi_behavior *behavior)
{
struct mimimi_fall_data *data = behavior->data;
return &data->fall;
}
struct mimimi_walk_data
{
struct mimimi_allocator *allocator;
struct mimimi_behavior *behavior;
struct mimimi_physics *physics;
struct mimimi_walk walk;
};
static void mimimi_walk_behave(void *data)
{
struct mimimi_walk_data *walk_data = data;
struct mimimi_physics *physics = walk_data->physics;
if (walk_data->walk.direction != 0)
{
int ax;
if (walk_data->physics->airborne)
ax = walk_data->walk.airborne_speed;
else
ax = walk_data->walk.ground_speed;
if (walk_data->walk.direction == 1)
physics->dx -= ax;
if (walk_data->walk.direction == 2)
physics->dx += ax;
}
}
static void mimimi_walk_finish(void *data)
{
struct mimimi_walk_data *walk_data = data;
(*walk_data->allocator->deallocate)(walk_data->behavior);
(*walk_data->allocator->deallocate)(walk_data);
}
struct mimimi_behavior *mimimi_walk(struct mimimi_physics *physics, struct mimimi_allocator *allocator)
{
struct mimimi_walk_data *data = (*allocator->allocate)(sizeof *data);
data->allocator = allocator;
data->physics = physics;
data->walk.ground_speed = 4;
data->walk.airborne_speed = 3;
data->walk.direction = 0;
data->behavior = (*allocator->allocate)(sizeof *data->behavior);
data->behavior->behave = &mimimi_walk_behave;
data->behavior->finish = &mimimi_walk_finish;
data->behavior->data = data;
return data->behavior;
}
struct mimimi_walk *mimimi_walk_attributes(struct mimimi_behavior *behavior)
{
struct mimimi_walk_data *data = behavior->data;
return &data->walk;
}
struct mimimi_sprite_data
{
struct mimimi_behavior *walk_behavior;
struct mimimi_sprite *sprite;
};
static void mimimi_sprite_behave(void *data0)
{
struct mimimi_sprite_data *data = data0;
struct mimimi_sprite *sprite = data->sprite;
struct mimimi_behavior *walk_behavior = data->walk_behavior;
struct mimimi_behavior *awake_behavior = sprite->awake_behavior;
if (sprite->life->knocked_time == 0)
{
(*walk_behavior->behave)(walk_behavior->data);
(*awake_behavior->behave)(awake_behavior->data);
}
}
struct mimimi_sprite *mimimi_sprite(struct mimimi_ground *ground, int x, int y, int width, int height, struct mimimi_allocator *allocator)
{
struct mimimi_behavior *compound = mimimi_compound_behavior(allocator);
struct mimimi_position *position = (*allocator->allocate)(sizeof *position);
struct mimimi_behavior *position_behavior = mimimi_finalizer(position, allocator->deallocate, allocator);
struct mimimi_behavior *physics_behavior = mimimi_physics(position, ground, allocator);
struct mimimi_physics *physics = mimimi_physics_attributes(physics_behavior);
struct mimimi_behavior *life_behavior = mimimi_life(allocator);
struct mimimi_life *life = mimimi_life_attributes(life_behavior);
struct mimimi_behavior *fall_behavior = mimimi_fall(physics, life, allocator);
struct mimimi_fall *fall = mimimi_fall_attributes(fall_behavior);
struct mimimi_behavior *walk_behavior = mimimi_walk(physics, allocator);
struct mimimi_walk *walk = mimimi_walk_attributes(walk_behavior);
mimimi_compound(compound, mimimi_finalizer(walk_behavior->data, walk_behavior->finish, allocator));
position->x = x;
position->y = y;
physics->width = width;
physics->height = height;
struct mimimi_sprite *sprite = (*allocator->allocate)(sizeof *sprite);
mimimi_compound(compound, mimimi_finalizer(sprite, allocator->deallocate, allocator));
struct mimimi_sprite_data *sprite_data = (*allocator->allocate)(sizeof *sprite_data);
mimimi_compound(compound, mimimi_finalizer(sprite_data, allocator->deallocate, allocator));
sprite_data->walk_behavior = walk_behavior;
sprite_data->sprite = sprite;
struct mimimi_behavior *sprite_behavior = mimimi_function(sprite_data, &mimimi_sprite_behave, allocator);
mimimi_compound(compound, sprite_behavior);
mimimi_compound(compound, physics_behavior);
mimimi_compound(compound, life_behavior);
mimimi_compound(compound, fall_behavior);
sprite->position = position;
sprite->physics = physics;
sprite->life = life;
sprite->fall = fall;
sprite->walk = walk;
sprite->behavior = compound;
sprite->awake_behavior = mimimi_noop;
return sprite;
}