Mirai's Miscellaneous Misadventures
M39 / core / controls.c
#include <mimimi/controls.h>
#include <mimimi/behaviors.h>
#include <mimimi/allocators.h>
#include <mimimi/sprites.h>
#include <mimimi/chapters.h>
struct mimimi_history_data
{
struct mimimi_allocator *allocator;
struct mimimi_behavior *behavior;
struct mimimi_history *history;
struct mimimi_chapter *chapter;
};
static void mimimi_history_behave(void *data0)
{
struct mimimi_history_data *data = data0;
data->history->left <<= 1;
data->history->left |= data->chapter->left;
data->history->left &= 0xFFFF;
data->history->right <<= 1;
data->history->right |= data->chapter->right;
data->history->right &= 0xFFFF;
}
static void mimimi_history_finish(void *data)
{
struct mimimi_history_data *history_data = data;
mimimi_deallocate(history_data->allocator, history_data->behavior);
mimimi_deallocate(history_data->allocator, history_data);
}
struct mimimi_behavior *mimimi_history(struct mimimi_history *history, struct mimimi_chapter *chapter, struct mimimi_allocator *allocator)
{
struct mimimi_history_data *data = mimimi_allocate(allocator, sizeof *data);
data->allocator = allocator;
data->history = history;
data->chapter = chapter;
history->left = 0;
history->right = 0;
data->behavior = mimimi_allocate(allocator, sizeof *data->behavior);
data->behavior->behave = &mimimi_history_behave;
data->behavior->finish = &mimimi_history_finish;
data->behavior->data = data;
return data->behavior;
}
struct mimimi_controls_data
{
struct mimimi_allocator *allocator;
struct mimimi_behavior *behavior;
struct mimimi_controls *controls;
struct mimimi_walk *walk;
struct mimimi_history *history;
};
static unsigned char mimimi_count_oscillations(unsigned int history)
{
unsigned char count = 0;
unsigned char prev = history&1;
for (int i = 0 ; i < 16 ; i++)
{
if ((history&1) != prev) count++;
prev = history&1;
history >>= 1;
}
return count;
}
static void mimimi_control(void *data)
{
struct mimimi_controls_data *controls_data = data;
struct mimimi_walk *walk = controls_data->walk;
struct mimimi_history *history = controls_data->history;
struct mimimi_behavior *jump = controls_data->controls->jump;
unsigned char left_oscillations = mimimi_count_oscillations(history->left);
unsigned char right_oscillations = mimimi_count_oscillations(history->right);
switch (walk->direction)
{
case 0:
if ((history->left&1) != 0)
{
walk->direction = 1;
if (left_oscillations > 1 && (history->left&2) == 0)
(*jump->behave)(jump->data);
}
if ((history->right&1) != 0)
{
walk->direction = 2;
if (right_oscillations > 1 && (history->right&2) == 0)
(*jump->behave)(jump->data);
}
break;
case 1:
if ((history->left&1) == 0)
walk->direction = 0;
break;
case 2:
if ((history->right&1) == 0)
walk->direction = 0;
break;
}
}
static void mimimi_controls_finish(void *data)
{
struct mimimi_controls_data *controls_data = data;
mimimi_deallocate(controls_data->allocator, controls_data->behavior);
mimimi_deallocate(controls_data->allocator, controls_data);
}
struct mimimi_behavior *mimimi_controls(struct mimimi_controls *controls, struct mimimi_walk *walk, struct mimimi_history *history, struct mimimi_allocator *allocator)
{
struct mimimi_controls_data *data = mimimi_allocate(allocator, sizeof *data);
data->allocator = allocator;
data->controls = controls;
data->walk = walk;
data->history = history;
controls->jump = mimimi_noop;
data->behavior = mimimi_allocate(allocator, sizeof *data->behavior);
data->behavior->behave = &mimimi_control;
data->behavior->finish = &mimimi_controls_finish;
data->behavior->data = data;
return data->behavior;
}
struct mimimi_stationary
{
struct mimimi_allocator *allocator;
struct mimimi_behavior *behavior;
int *direction;
int *position;
int *target;
};
static void mimimi_stationary_behave(void *data)
{
struct mimimi_stationary *stationary = data;
if (*stationary->position < *stationary->target)
*stationary->direction = 1;
else
*stationary->direction = 2;
}
static void mimimi_stationary_finish(void *data)
{
struct mimimi_stationary *stationary = data;
mimimi_deallocate(stationary->allocator, stationary->behavior);
mimimi_deallocate(stationary->allocator, stationary);
}
struct mimimi_behavior *mimimi_stationary(int *direction, int *position, int *target, struct mimimi_allocator *allocator)
{
struct mimimi_stationary *data = mimimi_allocate(allocator, sizeof *data);
data->allocator = allocator;
data->direction = direction;
data->position = position;
data->target = target;
data->behavior = mimimi_allocate(allocator, sizeof *data->behavior);
data->behavior->behave = &mimimi_stationary_behave;
data->behavior->finish = &mimimi_stationary_finish;
data->behavior->data = data;
return data->behavior;
}