mystnb/src/animation.c

183 lines
4.0 KiB
C

#include <gint/display.h>
#include <gint/defs/util.h>
#include "animation.h"
#include "engine.h"
//---
// Generation of animation frames from sheets
//---
/* struct sheet: Structure of an image with animation frames */
struct sheet
{
/* Source image */
bopti_image_t *img;
/* Width and height of single entry */
int frame_w;
int frame_h;
};
extern bopti_image_t img_spritesheet;
struct sheet const anim_player = {
.img = &img_spritesheet,
.frame_w = 12,
.frame_h = 16,
};
extern bopti_image_t img_tilesheet;
struct sheet const anim_tiles = {
.img = &img_tilesheet,
.frame_w = 10,
.frame_h = 20,
};
/* anim_frame(): Get a frame from a sheet */
static struct anim_frame anim_frame(struct sheet const *sheet, int col,int row)
{
struct anim_frame f = {
.source = sheet->img,
.left = sheet->frame_w * col,
.top = sheet->frame_h * row,
.w = sheet->frame_w,
.h = sheet->frame_h,
};
return f;
}
void dframe(int x, int y, struct anim_frame const frame)
{
dsubimage(x, y, frame.source, frame.left, frame.top, frame.w, frame.h,
DIMAGE_NONE);
}
//---
// Player animation functions
//---
int anim_player_idle(struct anim_data *data, int init)
{
/* Animation initialization; takes [data->dir] as input */
if(init)
{
data->function = anim_player_idle;
data->frame = 0;
data->duration = 500;
}
else
{
data->frame = (data->frame + 1) % 2;
data->duration += 500;
}
data->img = anim_frame(&anim_player, data->dir, data->frame);
data->dx = 0;
data->dy = 0;
return 0;
}
int anim_player_walking(struct anim_data *data, int init)
{
/* Animation initialization; takes [data->dir] as input */
if(init)
{
data->function = anim_player_walking;
data->frame = 0;
data->duration = 50;
int dx = (data->dir == DIR_LEFT) - (data->dir == DIR_RIGHT);
int dy = (data->dir == DIR_UP) - (data->dir == DIR_DOWN);
data->dx = 10 * dx;
data->dy = 10 * dy;
}
else
{
data->dx -= sgn(data->dx);
data->dy -= sgn(data->dy);
/* Animation finishes if both displacements are zero */
if(!data->dx && !data->dy)
{
return anim_player_idle(data, 1);
}
data->frame = (data->frame + 1) % 8;
data->duration += 50;
}
data->img = anim_frame(&anim_player, data->dir + 4, data->frame / 2);
return 1;
}
//---
// Tile animation functions
//---
int anim_tile_start(struct anim_data *data, int init)
{
data->function = anim_tile_start;
data->frame = init ? 0 : (data->frame + 1) % 5;
data->duration = (data->frame == 0 ? 1000 : 150);
data->img = anim_frame(&anim_tiles, data->frame, 0);
return 0;
}
int anim_tile_end(struct anim_data *data, int init)
{
data->function = anim_tile_end;
data->frame = init ? 0 : (data->frame + 1) % 5;
data->duration = (data->frame == 0 ? 1000 : 150);
data->img = anim_frame(&anim_tiles, data->frame, 1);
return 0;
}
int anim_door_closed(struct anim_data *data, GUNUSED int init)
{
/* Init takes [data->dir] as input */
data->function = anim_door_closed;
data->frame = 0 + 16 * (data->dir == DIR_LEFT);
data->duration = 1000;
data->img = anim_frame(&anim_tiles, data->frame & 15,
2 + (data->frame >= 16));
return 0;
}
int anim_door_opening(struct anim_data *data, int init)
{
data->function = anim_door_opening;
data->frame = init ? 1 + 16 * (data->dir == DIR_LEFT): data->frame + 1;
if((data->frame & 15) == 6)
return anim_door_open(data, 1);
data->duration = 75;
data->img = anim_frame(&anim_tiles, data->frame & 15,
2 + (data->frame >= 16));
return 1;
}
int anim_door_open(struct anim_data *data, GUNUSED int init)
{
data->function = anim_door_open;
data->frame = 6 + 16 * (data->dir == DIR_LEFT);
data->duration = 1000;
data->img = anim_frame(&anim_tiles, data->frame & 15,
2 + (data->frame >= 16));
return 0;
}
int anim_door_closing(struct anim_data *data, int init)
{
data->function = anim_door_closing;
data->frame = init ? 7 + 16 * (data->dir == DIR_LEFT): data->frame + 1;
if((data->frame & 15) == 11)
return anim_door_closed(data, 1);
data->duration = 75;
data->img = anim_frame(&anim_tiles, data->frame & 15,
2 + (data->frame >= 16));
return 1;
}