180 lines
5.2 KiB
C
180 lines
5.2 KiB
C
#include "./state.h"
|
|
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#include "util/math/algorithm.h"
|
|
#include "util/math/vector.h"
|
|
#include "util/statman/statman.h"
|
|
|
|
#include "core/locommon/easing.h"
|
|
#include "core/loresource/sound.h"
|
|
#include "core/loshader/character.h"
|
|
|
|
#include "./base.h"
|
|
|
|
#define MIDAIR_SPEED_ .8f
|
|
#define BACKWALK_SPEED_ .6f
|
|
|
|
void lochara_state_initialize_any_(
|
|
const statman_meta_t* meta, void* instance, statman_state_t* next) {
|
|
assert(meta != NULL);
|
|
assert(instance != NULL);
|
|
assert(next != NULL);
|
|
|
|
lochara_base_t* base = instance;
|
|
base->param.last_state_changed = base->ticker->time;
|
|
}
|
|
void lochara_state_cancel_transition_(
|
|
const statman_meta_t* meta, void* instance, statman_state_t* state) {
|
|
assert(meta != NULL);
|
|
assert(instance != NULL);
|
|
assert(state != NULL);
|
|
|
|
*state = meta->state;
|
|
}
|
|
|
|
void lochara_state_update_move_(
|
|
const statman_meta_t* meta, void* instance, statman_state_t* state) {
|
|
assert(meta != NULL);
|
|
assert(instance != NULL);
|
|
assert(state != NULL);
|
|
|
|
const lochara_state_move_param_t* p = meta->data;
|
|
lochara_base_t* base = instance;
|
|
|
|
const uint64_t t = base->ticker->time - base->param.last_state_changed;
|
|
const float dt = base->ticker->delta_f;
|
|
|
|
assert(vec2_valid(&p->acceleration));
|
|
assert(MATH_FLOAT_VALID(p->speed));
|
|
assert(vec2_valid(&p->velocity));
|
|
assert(p->period > 0);
|
|
|
|
/* ---- acceleration ---- */
|
|
float speed = p->speed*base->param.recipient.status.speed;
|
|
if (!base->param.on_ground) {
|
|
speed *= MIDAIR_SPEED_;
|
|
}
|
|
if (vec2_dot(&p->velocity, &base->param.direction) < 0) {
|
|
speed *= BACKWALK_SPEED_;
|
|
}
|
|
|
|
vec2_t velocity = p->velocity;
|
|
vec2_muleq(&velocity, speed);
|
|
|
|
locommon_easing_linear_float(
|
|
&base->param.movement.x, velocity.x, p->acceleration.x*dt);
|
|
locommon_easing_linear_float(
|
|
&base->param.movement.y, velocity.y, p->acceleration.y*dt);
|
|
|
|
/* ---- periodic motion ---- */
|
|
base->cache.instance.motion.time =
|
|
(!!base->param.on_ground)*(1-fabs(t%p->period*1.f/p->period*2 - 1));
|
|
base->cache.instance.motion.from = p->motion1;
|
|
base->cache.instance.motion.to = p->motion2;
|
|
}
|
|
|
|
void lochara_state_initialize_dodge_(
|
|
const statman_meta_t* meta, void* instance, statman_state_t* state) {
|
|
assert(meta != NULL);
|
|
assert(instance != NULL);
|
|
assert(state != NULL);
|
|
|
|
lochara_state_initialize_any_(meta, instance, state);
|
|
|
|
lochara_base_t* base = instance;
|
|
loresource_sound_set_play(&base->res->sound, LORESOURCE_SOUND_ID_DODGE);
|
|
}
|
|
|
|
void lochara_state_update_dodge_(
|
|
const statman_meta_t* meta, void* instance, statman_state_t* state) {
|
|
assert(meta != NULL);
|
|
assert(instance != NULL);
|
|
assert(state != NULL);
|
|
|
|
const lochara_state_dodge_param_t* p = meta->data;
|
|
lochara_base_t* base = instance;
|
|
|
|
const uint64_t t = base->ticker->time - base->param.last_state_changed;
|
|
|
|
assert(p->duration > 0);
|
|
assert(vec2_valid(&p->acceleration));
|
|
assert(vec2_valid(&p->velocity));
|
|
|
|
if (t > p->duration) {
|
|
*state = LOCHARA_STATE_STAND;
|
|
return;
|
|
}
|
|
|
|
/* ---- acceleration ---- */
|
|
base->param.movement = p->acceleration;
|
|
|
|
vec2_muleq(&base->param.movement, t/1000.f);
|
|
base->param.movement.x *= -MATH_SIGN(p->velocity.x);
|
|
base->param.movement.y *= -MATH_SIGN(p->velocity.y);
|
|
|
|
vec2_addeq(&base->param.movement, &p->velocity);
|
|
|
|
/* ---- motion ---- */
|
|
base->cache.instance.motion.time = powf(t*1.f/p->duration, 1.2f);
|
|
base->cache.instance.motion.from = p->motion1;
|
|
base->cache.instance.motion.to = p->motion2;
|
|
|
|
const float a = powf(t*2.f/p->duration-1, 2);
|
|
base->cache.instance.size.x *= (1-a)*.8f+1;
|
|
base->cache.instance.color.w *= MATH_MIN(a+.2f, 1);
|
|
}
|
|
|
|
void lochara_state_initialize_jump_(
|
|
const statman_meta_t* meta, void* instance, statman_state_t* next) {
|
|
assert(meta != NULL);
|
|
assert(instance != NULL);
|
|
assert(next != NULL);
|
|
|
|
lochara_state_initialize_any_(meta, instance, next);
|
|
|
|
lochara_base_t* base = instance;
|
|
base->param.gravity += base->param.recipient.status.jump;
|
|
*next = LOCHARA_STATE_STAND;
|
|
}
|
|
|
|
void lochara_state_update_teleport_(
|
|
const statman_meta_t* meta, void* instance, statman_state_t* next) {
|
|
assert(meta != NULL);
|
|
assert(instance != NULL);
|
|
assert(next != NULL);
|
|
|
|
const lochara_state_teleport_param_t* p = meta->data;
|
|
lochara_base_t* base = instance;
|
|
|
|
base->param.movement = vec2(0, 0);
|
|
|
|
const uint64_t t = base->ticker->time - base->param.last_state_changed;
|
|
const uint64_t pt =
|
|
t == 0? 0: base->ticker->prev_time - base->param.last_state_changed;
|
|
|
|
if (pt < p->duration/2 && p->duration/2 <= t) {
|
|
const lochara_base_t* player = base->player->entity;
|
|
|
|
const float pdir =
|
|
MATH_SIGN_NOZERO(player->param.direction.x)*p->direction;
|
|
base->param.direction = vec2(-pdir, 0);
|
|
|
|
vec2_t offset = p->offset;
|
|
offset.x *= pdir;
|
|
|
|
base->super.super.pos = player->super.super.pos;
|
|
vec2_addeq(&base->super.super.pos.fract, &offset);
|
|
locommon_position_reduce(&base->super.super.pos);
|
|
}
|
|
|
|
const float tf = fabsf(t*1.f/p->duration*2 - 1);
|
|
base->cache.instance.motion.from = p->motion2;
|
|
base->cache.instance.motion.to = p->motion1;
|
|
base->cache.instance.motion.time = tf;
|
|
base->cache.instance.color.w = tf;
|
|
}
|