feat: implemented slide attack with QCF+H
This commit is contained in:
parent
2f26672fc4
commit
3c15d808b5
|
@ -6,8 +6,10 @@
|
|||
|
||||
#include "PlayerStates.h"
|
||||
#include "Layers.h"
|
||||
#include "program.h"
|
||||
|
||||
const Vector PLAYER_SPEED = { 1.0f, 0.50f };
|
||||
static const float PLAYER_INPUT_RATE = 1.f/15.f;
|
||||
|
||||
START_REFLECT(Player)
|
||||
REFLECT_TYPECLASS(Player, Drop)
|
||||
|
@ -86,8 +88,12 @@ Player* MakePlayer() {
|
|||
.jab_b = NULL,
|
||||
.kick_a = NULL,
|
||||
.air_heavy = NULL,
|
||||
.slide = NULL,
|
||||
|
||||
.animationStateMachine = NULL,
|
||||
|
||||
.pushInputTimer = 0.f,
|
||||
.inputLog = list_from_type(PlayerInputFrame),
|
||||
};
|
||||
|
||||
self->rigidbody = rigidbody_make(Player_as_PhysicsEntity(self));
|
||||
|
@ -113,6 +119,7 @@ Player* MakePlayer() {
|
|||
self->jab_b = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Jab_B.png", IVectorFrom(512)), 10.f, LoopMode_Stop);
|
||||
self->kick_a = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Kick_A.png", IVectorFrom(512)), 12.f, LoopMode_Stop);
|
||||
self->air_heavy = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Air_Heavy.png", IVectorFrom(512)), 10.f, LoopMode_Stop);
|
||||
self->slide = animation_sprite_new(self->sprite, spritesheet_load("assets/Player_Slide.png", IVectorFrom(512)), 1.f, LoopMode_Loop);
|
||||
|
||||
self->animationStateMachine = state_machine_init(self, PlayerIdle());
|
||||
|
||||
|
@ -150,6 +157,24 @@ void PlayerStart(Player* self) {
|
|||
animation_sprite_play_from(self->currentAnimation, 0.0f);
|
||||
}
|
||||
|
||||
static
|
||||
void PlayerPushInput(Player* self) {
|
||||
PlayerInputFrame state = {
|
||||
.time = game_time(),
|
||||
.direction = self->moveInput,
|
||||
.light = self->attackInput == 1,
|
||||
.heavy = self->attackInput == 2,
|
||||
.jump = self->jumpInput,
|
||||
.facing = self->facing,
|
||||
};
|
||||
list_add(&self->inputLog, &state);
|
||||
if(self->inputLog.len >= 5)
|
||||
list_erase(&self->inputLog, 0);
|
||||
LOG_INFO("%f %f, L:%x, H:%x, J:%x",
|
||||
state.direction.x, state.direction.y,
|
||||
state.light, state.heavy, state.jump);
|
||||
}
|
||||
|
||||
void PlayerUpdate(Player* self, float deltaTime) {
|
||||
state_machine_update(self->animationStateMachine, deltaTime);
|
||||
self->height += self->verticalVelocity * deltaTime;
|
||||
|
@ -165,24 +190,33 @@ void PlayerDraw(Player* self) {
|
|||
|
||||
void PlayerHorizontalInput(Player* self, InputEvent value) {
|
||||
self->moveInput.x = value.as_float;
|
||||
PlayerPushInput(self);
|
||||
}
|
||||
|
||||
void PlayerVerticalInput(Player* self, InputEvent value) {
|
||||
self->moveInput.y = -value.as_float;
|
||||
PlayerPushInput(self);
|
||||
}
|
||||
|
||||
void PlayerJumpInput(Player* self, InputEvent value) {
|
||||
self->jumpInput = value.as_bool;
|
||||
if(value.as_bool) {
|
||||
self->jumpInput = value.as_bool;
|
||||
PlayerPushInput(self);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerLightAttackInput(Player* self, InputEvent value) {
|
||||
if(value.as_bool)
|
||||
if(value.as_bool) {
|
||||
self->attackInput = 1;
|
||||
PlayerPushInput(self);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerHeavyAttackInput(Player* self, InputEvent value) {
|
||||
if(value.as_bool)
|
||||
if(value.as_bool) {
|
||||
self->attackInput = 2;
|
||||
PlayerPushInput(self);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerOnCollision(Player* self, Collision collision) {}
|
||||
|
@ -195,3 +229,18 @@ Transform* PlayerGetTransform(Player* self) {
|
|||
RigidBody* PlayerGetRigidBody(Player* self) {
|
||||
return self->rigidbody;
|
||||
}
|
||||
|
||||
PlayerInputFrame* PlayerInputHistory(Player* self) {
|
||||
return (PlayerInputFrame*)self->inputLog.data;
|
||||
}
|
||||
|
||||
int PlayerInputIsQuarterCircleForward(Player* self) {
|
||||
PlayerInputFrame* history = PlayerInputHistory(self);
|
||||
const size_t last = self->inputLog.len-1;
|
||||
const float forward = history[last-3].facing;
|
||||
if(game_time() - history[last-2].time > 0.225f)
|
||||
return 0;
|
||||
return veqf(history[last-3].direction, MakeVector(0.f, 1.f))
|
||||
&& veqf(history[last-2].direction, MakeVector(forward, 1.f))
|
||||
&& veqf(history[last-1].direction, MakeVector(forward, 0.f));
|
||||
}
|
||||
|
|
|
@ -14,6 +14,15 @@
|
|||
|
||||
extern const Vector PLAYER_SPEED;
|
||||
|
||||
typedef struct PlayerInputFrame {
|
||||
float time;
|
||||
Vector direction;
|
||||
int light;
|
||||
int heavy;
|
||||
int jump;
|
||||
float facing;
|
||||
} PlayerInputFrame;
|
||||
|
||||
typedef struct Player {
|
||||
Transform transform;
|
||||
float height;
|
||||
|
@ -42,10 +51,15 @@ typedef struct Player {
|
|||
AnimationSprite* jab_b;
|
||||
AnimationSprite* kick_a;
|
||||
AnimationSprite* air_heavy;
|
||||
AnimationSprite* slide;
|
||||
|
||||
StateMachine* animationStateMachine;
|
||||
|
||||
AnimationSprite* currentAnimation;
|
||||
|
||||
float pushInputTimer;
|
||||
List inputLog;
|
||||
PlayerInputFrame nextInputFrame;
|
||||
} Player;
|
||||
|
||||
Player* MakePlayer();
|
||||
|
@ -68,6 +82,9 @@ void PlayerOnOverlap(Player* self, Collider* other);
|
|||
Transform* PlayerGetTransform(Player* self);
|
||||
RigidBody* PlayerGetRigidBody(Player* self);
|
||||
|
||||
PlayerInputFrame* PlayerInputHistory(Player* self);
|
||||
|
||||
int PlayerInputIsQuarterCircleForward(Player* self);
|
||||
|
||||
static long PlayerGetDepth(Player* self) { return (int)(-10-self->transform.position.y * 1000); }
|
||||
|
||||
|
|
|
@ -18,6 +18,22 @@ void PlayerAnimationExit(Player* self) {
|
|||
self->attackInput = 0;
|
||||
}
|
||||
|
||||
static
|
||||
const State* PlayerTryStartNewChain(Player* self) {
|
||||
if(self->attackInput == 1) {
|
||||
return PlayerJabA();
|
||||
}
|
||||
if(self->attackInput == 2) {
|
||||
if(self->height > 0.f)
|
||||
return PlayerAirHeavy();
|
||||
else if(PlayerInputIsQuarterCircleForward(self))
|
||||
return PlayerSlide();
|
||||
else
|
||||
return PlayerKickA();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void PlayerIdleEnter(Player* self) {
|
||||
self->currentAnimation = self->idle;
|
||||
rigidbody_set_velocity(self->rigidbody, ZeroVector);
|
||||
|
@ -46,10 +62,9 @@ const State* PlayerWalk_Update(Player* self, float deltaTime) {
|
|||
|
||||
if(veqf(self->moveInput, ZeroVector))
|
||||
return PlayerIdle();
|
||||
if(self->attackInput == 1)
|
||||
return PlayerJabA();
|
||||
if(self->attackInput == 2)
|
||||
return PlayerKickA();
|
||||
const State* attackState = PlayerTryStartNewChain(self);
|
||||
if(attackState)
|
||||
return attackState;
|
||||
if(self->jumpInput)
|
||||
return PlayerJump();
|
||||
InternalSpriteFlipWithMovement(self);
|
||||
|
@ -148,7 +163,7 @@ const State* PlayerKickA_Update(Player* self, float deltaTime) {
|
|||
};
|
||||
const float ntime = animation_sprite_get_time_normalized(self->currentAnimation);
|
||||
const size_t frame = sprite_get_tile(self->sprite);
|
||||
if(frame >= 2 && frame <= 3) {
|
||||
if(frame >= 3 && frame <= 4) {
|
||||
PlayerHurtbox(self, damage, MakeVector(0.16f, 0.06f), MakeVector(0.33f, -0.4f));
|
||||
}
|
||||
if(!veqf(self->moveInput, ZeroVector) && ntime > 1.05f)
|
||||
|
@ -158,6 +173,31 @@ const State* PlayerKickA_Update(Player* self, float deltaTime) {
|
|||
return PlayerKickA();
|
||||
}
|
||||
|
||||
void PlayerSlide_Enter(Player* self) {
|
||||
PlayerAttackEnter(self);
|
||||
self->currentAnimation = self->slide;
|
||||
// adjust for the downward motion of the quartercircle
|
||||
Transform* trans = rigidbody_get_transform(self->rigidbody);
|
||||
trans->position.y -= 0.03f;
|
||||
animation_sprite_play_from(self->currentAnimation, 0.f);
|
||||
}
|
||||
|
||||
const State* PlayerSlide_Update(Player* self, float deltaTime) {
|
||||
static const DamageEventData damage = {
|
||||
.damageAmount = 3,
|
||||
.knockdown = 1,
|
||||
.stun = 1.f,
|
||||
.knockback = 0.3f,
|
||||
};
|
||||
const float time = animation_sprite_get_time(self->currentAnimation);
|
||||
rigidbody_set_velocity(self->rigidbody, MakeVector(self->facing * 3.f, 0.f));
|
||||
if(time > 0.34f)
|
||||
return PlayerIdle();
|
||||
if(time > 0.1f)
|
||||
PlayerHurtbox(self, damage, MakeVector(0.16, 0.06f), MakeVector(0.33f, -0.03f));
|
||||
return PlayerSlide();
|
||||
}
|
||||
|
||||
void PlayerJump_Enter(Player* self) {
|
||||
if(self->jumpInput) {
|
||||
self->currentAnimation = self->jump;
|
||||
|
|
|
@ -54,6 +54,15 @@ DefineState(PlayerKickA, Player,
|
|||
PlayerAnimationExit
|
||||
)
|
||||
|
||||
extern void PlayerSlide_Enter(Player* self);
|
||||
extern const State* PlayerSlide_Update(Player* self, float deltaTime);
|
||||
|
||||
DefineState(PlayerSlide, Player,
|
||||
PlayerSlide_Enter,
|
||||
PlayerSlide_Update,
|
||||
PlayerAnimationExit
|
||||
)
|
||||
|
||||
extern void PlayerJump_Enter(Player *self);
|
||||
extern const State* PlayerJump_Update(Player* self, float deltaTime);
|
||||
|
||||
|
|
Loading…
Reference in a new issue