mystnb/src/engine.c

94 lines
1.9 KiB
C

#include <gint/display.h>
#include <gint/keyboard.h>
#include "engine.h"
#define CELL_X(x) (-2 + 10 * (x))
#define CELL_Y(y) (-3 + 10 * (y))
//---
// Animations
//---
void engine_tick(struct game *game, int dt)
{
game->time += dt;
/* Update the animations for every player */
for(int p = 0; game->players[p]; p++)
{
struct player *player = game->players[p];
player->anim.duration -= dt;
if(player->anim.duration > 0) continue;
/* Call the animation function to generate the next frame */
player->idle = !player->anim.function(&player->anim, 0);
}
}
//---
// Rendering
//---
static void engine_draw_player(struct player const *player)
{
dframe(CELL_X(player->x) - 1 + player->anim.dx,
CELL_Y(player->y) - 5 + player->anim.dy,
player->anim.img);
}
void engine_draw(struct game const *game)
{
dclear(C_WHITE);
dimage(0, 0, game->map->img);
for(int p = 0; game->players[p]; p++)
{
engine_draw_player(game->players[p]);
}
}
//---
// Physics
//---
/* Check whether a cell of the map is walkable */
static int map_walkable(struct map const *map, int x, int y)
{
int tile = map->tiles[y * map->w + x];
return (tile != TILE_WALL);
}
int engine_move(struct game *game, struct player *player, int dir)
{
int dx = (dir == DIR_RIGHT) - (dir == DIR_LEFT);
int dy = (dir == DIR_DOWN) - (dir == DIR_UP);
int olddir = player->dir;
/* Don't move players that are already moving */
if(!player->idle) return 0;
/* Update the direction */
player->dir = dir;
player->anim.dir = dir;
/* Only move the player if the destination is walkable */
if(!map_walkable(game->map, player->x + dx, player->y + dy))
{
/* If not, set the new idle animation */
if(dir != olddir)
{
player->idle = !anim_player_idle(&player->anim,1);
}
return 0;
}
player->x += dx;
player->y += dy;
/* Set the walking animation */
player->idle = !anim_player_walking(&player->anim, 1);
return 1;
}