169 lines
4.8 KiB
C
169 lines
4.8 KiB
C
#include "art/game_player.h"
|
|
#include "art/game_tiles.h"
|
|
#include "device/device.h"
|
|
#include "map/game_map.h"
|
|
#include "game.h"
|
|
#include "sys/sys.h"
|
|
|
|
#define GAME_PLAYER_ORIGIN_X 3
|
|
#define GAME_PLAYER_ORIGIN_Y 4
|
|
|
|
game_bbox game_player_bbox = {
|
|
.x=0x9000,
|
|
// .y=0x5800,
|
|
.y=0x0000,
|
|
.w=0x0a00,
|
|
.h=0x0c00,
|
|
};
|
|
bool game_player_grounded = false;
|
|
sys_i32 game_player_jump_frames = 0;
|
|
sys_i32 game_player_coyote_frames = 0;
|
|
sys_i32 game_player_dx = 0;
|
|
sys_i32 game_player_dy = 0;
|
|
bool game_player_faceleft = false;
|
|
|
|
typedef enum {
|
|
GAME_PLAYER_ANIM_STANDING,
|
|
GAME_PLAYER_ANIM_WALKING,
|
|
GAME_PLAYER_ANIM_FLOATING,
|
|
} game_player_anim;
|
|
|
|
game_player_anim game_player_anim_state = GAME_PLAYER_ANIM_STANDING;
|
|
uint8_t game_player_anim_progress = 0;
|
|
|
|
void game_player_anim_transition(game_player_anim anim);
|
|
void game_player_anim_add_progress(uint8_t amt);
|
|
|
|
void game_player_init() {
|
|
}
|
|
|
|
void game_player_update() {
|
|
game_collision collision = game_collision_move_to_contact(
|
|
&game_player_bbox,
|
|
game_player_dx,
|
|
game_player_dy
|
|
);
|
|
|
|
if (collision.collided_x) { game_player_dx = 0; }
|
|
if (collision.collided_y) { game_player_dy = 0; }
|
|
|
|
game_player_grounded = !game_collision_can_move(
|
|
game_player_bbox, 0, 1
|
|
);
|
|
|
|
{
|
|
sys_i32 fric_numerator = game_player_grounded ? 0x70 : 0x7f;
|
|
game_player_dx = (
|
|
game_player_dx * fric_numerator +
|
|
// round up
|
|
0x7f * sys_sgn_i32(game_player_dx)
|
|
) / 0x80;
|
|
if (sys_abs_i32(game_player_dx) > 0x140) {
|
|
game_player_dx = sys_sgn_i32(game_player_dx) * 0x140;
|
|
}
|
|
|
|
int wanted_dx = game_player_dx;
|
|
if (sys_btn(DEVICE_BUTTON_L)) { wanted_dx -= 0x50; }
|
|
if (sys_btn(DEVICE_BUTTON_R)) { wanted_dx += 0x50; }
|
|
|
|
// allow this if grounded or if it's not a change of direction
|
|
if (
|
|
/*
|
|
game_player_grounded ||
|
|
(sys_sgn_i32(wanted_dx) == sys_sgn_i32(game_player_dx))
|
|
*/
|
|
true
|
|
) {
|
|
game_player_dx = wanted_dx;
|
|
} else {
|
|
// the smallest possible amount of movement without changing sign
|
|
game_player_dx = sys_sgn_i32(game_player_dx);
|
|
}
|
|
}
|
|
|
|
if (game_player_grounded || game_player_coyote_frames > 0) {
|
|
if (sys_btnp(DEVICE_BUTTON_U, false)) {
|
|
game_player_dy = -0x200;
|
|
game_player_jump_frames = 13;
|
|
game_player_grounded = false;
|
|
}
|
|
}
|
|
|
|
if (game_player_dx < 0) { game_player_faceleft = true; }
|
|
if (game_player_dx > 0) { game_player_faceleft = false; }
|
|
|
|
bool wants_to_go_higher = false;
|
|
if (game_player_grounded) {
|
|
game_player_coyote_frames = 5;
|
|
if (game_player_dy > 0) { game_player_dy = 0; }
|
|
if (sys_abs_i32(game_player_dx) < 0x20) { game_player_dx = 0; }
|
|
}
|
|
else {
|
|
game_player_coyote_frames =
|
|
sys_max_i32(0, game_player_coyote_frames - 1);
|
|
wants_to_go_higher = sys_btn(DEVICE_BUTTON_U);
|
|
bool is_going_higher = wants_to_go_higher && game_player_jump_frames > 0;
|
|
if (game_player_dy >= 0 || !is_going_higher) {
|
|
game_player_dy += 48;
|
|
} else {
|
|
game_player_jump_frames -= 1;
|
|
}
|
|
}
|
|
|
|
// deduce animation state
|
|
if (game_player_grounded) {
|
|
if (game_player_dx == 0) {
|
|
game_player_anim_transition(GAME_PLAYER_ANIM_STANDING);
|
|
} else {
|
|
game_player_anim_transition(GAME_PLAYER_ANIM_WALKING);
|
|
game_player_anim_add_progress(
|
|
sys_min_i32(sys_abs_i32(game_player_dx) / 0x10, 0x20)
|
|
);
|
|
}
|
|
} else {
|
|
if (wants_to_go_higher) {
|
|
game_player_anim_transition(GAME_PLAYER_ANIM_FLOATING);
|
|
} else {
|
|
game_player_anim_transition(GAME_PLAYER_ANIM_STANDING);
|
|
}
|
|
}
|
|
}
|
|
|
|
void game_player_draw() {
|
|
int game_player_image;
|
|
switch (game_player_anim_state) {
|
|
case GAME_PLAYER_ANIM_WALKING:
|
|
game_player_image = 2 + (game_player_anim_progress / 0x80) * 2;
|
|
break;
|
|
case GAME_PLAYER_ANIM_FLOATING:
|
|
game_player_image = 6;
|
|
break;
|
|
default:
|
|
case GAME_PLAYER_ANIM_STANDING:
|
|
game_player_image = 0;
|
|
break;
|
|
}
|
|
|
|
sys_sprite_draw_ext(
|
|
spr_game_player,
|
|
game_player_image,
|
|
game_player_bbox.x / 0x100 - GAME_PLAYER_ORIGIN_X,
|
|
game_player_bbox.y / 0x100 - GAME_PLAYER_ORIGIN_Y,
|
|
2, 2,
|
|
game_player_faceleft, false
|
|
);
|
|
}
|
|
|
|
void game_player_anim_transition(game_player_anim anim) {
|
|
if (game_player_anim_state == anim) { return ;}
|
|
game_player_anim_state = anim;
|
|
game_player_anim_progress = 0;
|
|
}
|
|
|
|
void game_player_anim_add_progress(uint8_t amt) {
|
|
game_player_anim_progress = (
|
|
(uint32_t) game_player_anim_progress +
|
|
(uint32_t) amt
|
|
) & 0xff;
|
|
}
|