#include #include #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; }