128 lines
2.5 KiB
C++
128 lines
2.5 KiB
C++
#pragma once
|
|
|
|
#include "coordinates.hpp"
|
|
|
|
struct actor_t
|
|
{
|
|
enum direction {
|
|
up,
|
|
down,
|
|
left,
|
|
right,
|
|
};
|
|
|
|
enum collision {
|
|
impassable,
|
|
jump,
|
|
passable,
|
|
};
|
|
|
|
world_t world;
|
|
enum direction facing;
|
|
bool moving;
|
|
enum collision collision;
|
|
uint8_t frame;
|
|
uint8_t cycle;
|
|
|
|
constexpr inline int32_t frame_pixels()
|
|
{
|
|
switch (collision) {
|
|
case jump: return frame;
|
|
default: return frame;
|
|
}
|
|
}
|
|
|
|
constexpr inline offset_t offset()
|
|
{
|
|
const int32_t pixels = frame_pixels();
|
|
|
|
switch (collision) {
|
|
default:
|
|
return {0, 0};
|
|
case jump: [[fallthrough]];
|
|
case passable:
|
|
switch (facing) {
|
|
case left:
|
|
return {-pixels, 0};
|
|
case right:
|
|
return {pixels, 0};
|
|
case up:
|
|
return {0, -pixels};
|
|
case down:
|
|
return {0, pixels};
|
|
default:
|
|
return {0, 0};
|
|
}
|
|
}
|
|
}
|
|
|
|
// engine/overworld/player_animations.asm
|
|
// $38, $36, $34, $32, $31, $30, $30, $30, $31, $32, $33, $34, $36, $38, $3C, $3C
|
|
// ^ these are in absolute position, subtract 60 from each to get the offset:
|
|
// an offset of -4 is the same as not jumping
|
|
static constexpr int8_t jump_screen_offset[16] = {-4, -8, -10, -12, -14, -15, -16, -16, -16, -15, -14, -13, -12, -10, -8, -4};
|
|
|
|
// in pixels
|
|
constexpr inline int32_t y_offset()
|
|
{
|
|
if (collision == jump)
|
|
return jump_screen_offset[frame >> 1 & 15];
|
|
else
|
|
return -4;
|
|
}
|
|
|
|
constexpr inline int32_t world_increment()
|
|
{
|
|
switch (collision) {
|
|
case jump: return 2;
|
|
default: return 1;
|
|
}
|
|
}
|
|
|
|
// call tick() before move()
|
|
constexpr inline void tick()
|
|
{
|
|
if (!moving) return;
|
|
|
|
frame = frame + 1;
|
|
if (frame == (16 * world_increment())) {
|
|
cycle += 1;
|
|
frame = 0;
|
|
int32_t inc = world_increment();
|
|
switch (collision) {
|
|
default: break;
|
|
case jump: [[fallthrough]];
|
|
case passable:
|
|
switch (facing) {
|
|
case left: world.x -= inc; break;
|
|
case right: world.x += inc; break;
|
|
case up: world.y -= inc; break;
|
|
case down: world.y += inc; break;
|
|
}
|
|
}
|
|
moving = false;
|
|
}
|
|
}
|
|
|
|
constexpr inline void move(enum collision collision,
|
|
enum direction dir)
|
|
{
|
|
/*
|
|
m 1 . 2 . 3 . 4 .
|
|
| - | - | - | - |
|
|
|
|
*/
|
|
|
|
// don't change directions in the middle of a movement animation
|
|
if (this->collision != impassable && moving) return;
|
|
|
|
// reset animation frame if there is no collision
|
|
// if there is a collision, keep animating
|
|
if (collision != impassable) frame = 0;
|
|
|
|
facing = dir;
|
|
moving = true;
|
|
this->collision = collision;
|
|
}
|
|
};
|