Merge branch 'timo-animations' into 'master'

Split animations

See merge request veloren/veloren!466
This commit is contained in:
Joshua Barretto 2019-08-31 15:47:16 +00:00
commit 367e7f2351
18 changed files with 647 additions and 412 deletions

View File

@ -100,12 +100,6 @@ impl Client {
// We reduce the thread count by 1 to keep rendering smooth
thread_pool.set_num_threads((num_cpus::get() - 1).max(1));
// Set client-only components
let _ = state
.ecs_mut()
.write_storage()
.insert(entity, comp::AnimationInfo::default());
Ok(Self {
client_state,
thread_pool,
@ -279,10 +273,30 @@ impl Client {
// 2) Build up a list of events for this frame, to be passed to the frontend.
let mut frontend_events = Vec::new();
// Prepare for new events
{
let ecs = self.state.ecs_mut();
for (entity, _) in (&ecs.entities(), &ecs.read_storage::<comp::Body>()).join() {
let mut last_character_states =
ecs.write_storage::<comp::Last<comp::CharacterState>>();
if let Some(client_character_state) =
ecs.read_storage::<comp::CharacterState>().get(entity)
{
if last_character_states
.get(entity)
.map(|&l| !client_character_state.is_same_state(&l.0))
.unwrap_or(true)
{
let _ = last_character_states
.insert(entity, comp::Last(*client_character_state));
}
}
}
}
// Handle new messages from the server.
frontend_events.append(&mut self.handle_new_messages()?);
// 3)
// 3) Update client local data
// 4) Tick the client's LocalState
self.state.tick(dt);
@ -395,7 +409,6 @@ impl Client {
}
// 7) Finish the tick, pass control back to the frontend.
self.tick += 1;
Ok(frontend_events)
}

View File

@ -1,35 +0,0 @@
use specs::{Component, FlaggedStorage};
use specs_idvs::IDVStorage;
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
pub enum Animation {
Idle,
Run,
Jump,
Gliding,
Attack,
Block,
Roll,
Crun,
Cidle,
Cjump,
}
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
pub struct AnimationInfo {
pub animation: Animation,
pub time: f64,
}
impl Default for AnimationInfo {
fn default() -> Self {
Self {
animation: Animation::Idle,
time: 0.0,
}
}
}
impl Component for AnimationInfo {
type Storage = FlaggedStorage<Self, IDVStorage<Self>>;
}

View File

@ -63,6 +63,20 @@ pub struct CharacterState {
pub action: ActionState,
}
impl CharacterState {
pub fn is_same_movement(&self, other: &Self) -> bool {
// Check if enum item is the same without looking at the inner data
std::mem::discriminant(&self.movement) == std::mem::discriminant(&other.movement)
}
pub fn is_same_action(&self, other: &Self) -> bool {
// Check if enum item is the same without looking at the inner data
std::mem::discriminant(&self.action) == std::mem::discriminant(&other.action)
}
pub fn is_same_state(&self, other: &Self) -> bool {
self.is_same_movement(other) && self.is_same_action(other)
}
}
impl Default for CharacterState {
fn default() -> Self {
Self {

View File

@ -7,9 +7,3 @@ pub struct Last<C: Component + PartialEq>(pub C);
impl<C: Component + Send + Sync + PartialEq> Component for Last<C> {
type Storage = VecStorage<Self>;
}
impl<C: Component + PartialEq> PartialEq<C> for Last<C> {
fn eq(&self, other: &C) -> bool {
self.0 == *other
}
}

View File

@ -1,6 +1,5 @@
mod admin;
mod agent;
mod animation;
mod body;
mod character_state;
mod controller;
@ -15,7 +14,6 @@ mod visual;
// Reexports
pub use admin::Admin;
pub use agent::Agent;
pub use animation::{Animation, AnimationInfo};
pub use body::{humanoid, object, quadruped, quadruped_medium, Body};
pub use character_state::{ActionState, CharacterState, MovementState};
pub use controller::Controller;

View File

@ -133,9 +133,6 @@ impl State {
ecs.register::<comp::Ori>();
ecs.register::<comp::Inventory>();
// Register client-local components
ecs.register::<comp::AnimationInfo>();
// Register server-local components
ecs.register::<comp::Last<comp::Pos>>();
ecs.register::<comp::Last<comp::Vel>>();

View File

@ -1,63 +0,0 @@
use crate::{
comp::{
ActionState::*, Animation, AnimationInfo, CharacterState, MovementState::*, PhysicsState,
Stats,
},
state::DeltaTime,
};
use specs::{Entities, Join, Read, ReadStorage, System, WriteStorage};
use std::fmt::Debug;
/// This system will apply the animation that fits best to the users actions
pub struct Sys;
impl<'a> System<'a> for Sys {
type SystemData = (
Entities<'a>,
Read<'a, DeltaTime>,
ReadStorage<'a, Stats>,
ReadStorage<'a, CharacterState>,
ReadStorage<'a, PhysicsState>,
WriteStorage<'a, AnimationInfo>,
);
fn run(
&mut self,
(entities, dt, stats, character_states, physics_states, mut animation_infos): Self::SystemData,
) {
for (entity, stats, character, physics) in
(&entities, &stats, &character_states, &physics_states).join()
{
if stats.is_dead {
continue;
}
let animation = match (physics.on_ground, &character.movement, &character.action) {
(_, Roll { .. }, Idle) => Animation::Roll,
(true, Stand, Idle) => Animation::Idle,
(true, Run, Idle) => Animation::Run,
(false, Jump, Idle) => Animation::Jump,
(true, Stand, Wield { .. }) => Animation::Cidle,
(true, Run, Wield { .. }) => Animation::Crun,
(false, Jump, Wield { .. }) => Animation::Cjump,
(_, Glide, Idle) => Animation::Gliding,
(_, _, Attack { .. }) => Animation::Attack,
(_, _, Block { .. }) => Animation::Block,
// Impossible animation (Caused by missing animations or syncing delays)
_ => Animation::Gliding,
};
let new_time = animation_infos
.get(entity)
.filter(|i| i.animation == animation)
.map(|i| i.time + f64::from(dt.0));
let _ = animation_infos.insert(
entity,
AnimationInfo {
animation,
time: new_time.unwrap_or(0.0),
},
);
}
}
}

View File

@ -1,5 +1,4 @@
pub mod agent;
pub mod animation;
mod cleanup;
pub mod combat;
pub mod controller;
@ -16,7 +15,6 @@ const CONTROLLER_SYS: &str = "controller_sys";
const PHYS_SYS: &str = "phys_sys";
const MOVEMENT_SYS: &str = "movement_sys";
const COMBAT_SYS: &str = "combat_sys";
const ANIMATION_SYS: &str = "animation_sys";
const STATS_SYS: &str = "stats_sys";
const CLEANUP_SYS: &str = "cleanup_sys";
@ -26,7 +24,6 @@ pub fn add_local_systems(dispatch_builder: &mut DispatcherBuilder) {
dispatch_builder.add(phys::Sys, PHYS_SYS, &[CONTROLLER_SYS]);
dispatch_builder.add(movement::Sys, MOVEMENT_SYS, &[PHYS_SYS]);
dispatch_builder.add(combat::Sys, COMBAT_SYS, &[CONTROLLER_SYS]);
dispatch_builder.add(animation::Sys, ANIMATION_SYS, &[MOVEMENT_SYS]);
dispatch_builder.add(stats::Sys, STATS_SYS, &[COMBAT_SYS]);
dispatch_builder.add(cleanup::Sys, CLEANUP_SYS, &[STATS_SYS, ANIMATION_SYS]);
dispatch_builder.add(cleanup::Sys, CLEANUP_SYS, &[STATS_SYS, MOVEMENT_SYS]);
}

View File

@ -20,6 +20,8 @@ const HUMANOID_AIR_SPEED: f32 = 100.0;
const ROLL_SPEED: f32 = 13.0;
const GLIDE_ACCEL: f32 = 15.0;
const GLIDE_SPEED: f32 = 45.0;
const BLOCK_ACCEL: f32 = 30.0;
const BLOCK_SPEED: f32 = 75.0;
// Gravity is 9.81 * 4, so this makes gravity equal to .15
const GLIDE_ANTIGRAV: f32 = 9.81 * 3.95;
@ -80,6 +82,14 @@ impl<'a> System<'a> for Sys {
.try_normalized()
.unwrap_or(Vec2::from(vel.0).try_normalized().unwrap_or_default())
* ROLL_SPEED
}
if character.action.is_block() || character.action.is_attack() {
vel.0 += Vec2::broadcast(dt.0)
* controller.move_dir
* match (physics.on_ground) {
(true) if vel.0.magnitude_squared() < BLOCK_SPEED.powf(2.0) => BLOCK_ACCEL,
_ => 0.0,
}
} else {
// Move player according to move_dir
vel.0 += Vec2::broadcast(dt.0)

View File

@ -243,6 +243,8 @@ impl Server {
let state = &mut self.state;
let clients = &mut self.clients;
let mut todo_remove = None;
match event {
ServerEvent::Explosion { pos, radius } => {
const RAYS: usize = 500;
@ -306,23 +308,21 @@ impl Server {
clients.notify_registered(ServerMsg::kill(msg));
}
{
// Give EXP to the client
let mut stats = ecs.write_storage::<comp::Stats>();
// Give EXP to the client
let mut stats = ecs.write_storage::<comp::Stats>();
if let Some(entity_stats) = stats.get(entity).cloned() {
if let comp::HealthSource::Attack { by } = cause {
ecs.entity_from_uid(by.into()).map(|attacker| {
if let Some(attacker_stats) = stats.get_mut(attacker) {
// TODO: Discuss whether we should give EXP by Player Killing or not.
attacker_stats.exp.change_by(
(entity_stats.health.maximum() as f64 / 10.0
+ entity_stats.level.level() as f64 * 10.0)
as i64,
);
}
});
}
if let Some(entity_stats) = stats.get(entity).cloned() {
if let comp::HealthSource::Attack { by } = cause {
ecs.entity_from_uid(by.into()).map(|attacker| {
if let Some(attacker_stats) = stats.get_mut(attacker) {
// TODO: Discuss whether we should give EXP by Player Killing or not.
attacker_stats.exp.change_by(
(entity_stats.health.maximum() as f64 / 10.0
+ entity_stats.level.level() as f64 * 10.0)
as i64,
);
}
});
}
}
@ -331,7 +331,7 @@ impl Server {
let _ = ecs.write_storage().insert(entity, comp::ForceUpdate);
client.force_state(ClientState::Dead);
} else {
let _ = state.ecs_mut().delete_entity_synced(entity);
todo_remove = Some(entity.clone());
}
}
@ -356,6 +356,10 @@ impl Server {
}
}
}
if let Some(entity) = todo_remove {
let _ = state.ecs_mut().delete_entity_synced(entity);
}
}
}
@ -1101,7 +1105,7 @@ impl Server {
if let Some(client_pos) = ecs.read_storage::<comp::Pos>().get(entity) {
if last_pos
.get(entity)
.map(|&l| l != *client_pos)
.map(|&l| l.0 != *client_pos)
.unwrap_or(true)
{
let _ = last_pos.insert(entity, comp::Last(*client_pos));
@ -1119,7 +1123,7 @@ impl Server {
if let Some(client_vel) = ecs.read_storage::<comp::Vel>().get(entity) {
if last_vel
.get(entity)
.map(|&l| l != *client_vel)
.map(|&l| l.0 != *client_vel)
.unwrap_or(true)
{
let _ = last_vel.insert(entity, comp::Last(*client_vel));
@ -1137,7 +1141,7 @@ impl Server {
if let Some(client_ori) = ecs.read_storage::<comp::Ori>().get(entity) {
if last_ori
.get(entity)
.map(|&l| l != *client_ori)
.map(|&l| l.0 != *client_ori)
.unwrap_or(true)
{
let _ = last_ori.insert(entity, comp::Last(*client_ori));
@ -1157,7 +1161,7 @@ impl Server {
{
if last_character_state
.get(entity)
.map(|&l| l != *client_character_state)
.map(|&l| !client_character_state.is_same_state(&l.0))
.unwrap_or(true)
{
let _ =

View File

@ -107,23 +107,23 @@ impl Animation for BlockAnimation {
next.weapon.scale = Vec3::one();
}
Tool::Hammer => {
next.l_hand.offset = Vec3::new(-5.5, 9.0, 5.5);
next.l_hand.offset = Vec3::new(-5.5, 10.0, 9.5);
next.l_hand.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.57)
* Quaternion::rotation_y(-1.35)
* Quaternion::rotation_z(0.5);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(8.4, 9.3, 5.5);
next.r_hand.offset = Vec3::new(8.4, 9.3, 7.5);
next.r_hand.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.57)
* Quaternion::rotation_y(-1.35)
* Quaternion::rotation_z(0.5);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
7.0 + skeleton_attr.weapon_x,
10.75 + skeleton_attr.weapon_y,
5.5,
7.5,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.57)
* Quaternion::rotation_y(-1.35)
* Quaternion::rotation_z(0.5);
next.weapon.scale = Vec3::one();
}
@ -224,13 +224,13 @@ impl Animation for BlockAnimation {
next.weapon.scale = Vec3::one();
}
}
next.l_foot.offset = Vec3::new(-3.4, 0.3, 8.0 + wave_ultra_slow_cos * 0.1);
next.l_foot.ori = Quaternion::rotation_x(-0.3);
next.l_foot.scale = Vec3::one();
//next.l_foot.offset = Vec3::new(-3.4, 0.3, 8.0 + wave_ultra_slow_cos * 0.1);
//next.l_foot.ori = Quaternion::rotation_x(-0.3);
//next.l_foot.scale = Vec3::one();
next.r_foot.offset = Vec3::new(3.4, 1.2, 8.0 + wave_ultra_slow * 0.1);
next.r_foot.ori = Quaternion::rotation_x(0.3);
next.r_foot.scale = Vec3::one();
//next.r_foot.offset = Vec3::new(3.4, 1.2, 8.0 + wave_ultra_slow * 0.1);
//next.r_foot.ori = Quaternion::rotation_x(0.3);
//next.r_foot.scale = Vec3::one();
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(0.0);

View File

@ -0,0 +1,252 @@
use super::{
super::{Animation, SkeletonAttr},
CharacterSkeleton,
};
use common::comp::item::Tool;
use std::{f32::consts::PI, ops::Mul};
use vek::*;
pub struct Input {
pub attack: bool,
}
pub struct BlockIdleAnimation;
impl Animation for BlockIdleAnimation {
type Skeleton = CharacterSkeleton;
type Dependency = f64;
fn update_skeleton(
skeleton: &Self::Skeleton,
global_time: f64,
anim_time: f64,
skeleton_attr: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let wave_ultra_slow = (anim_time as f32 * 3.0 + PI).sin();
let wave_ultra_slow_cos = (anim_time as f32 * 3.0 + PI).cos();
let wave_slow_cos = (anim_time as f32 * 6.0 + PI).cos();
let _head_look = Vec2::new(
((global_time + anim_time) as f32 / 1.5)
.floor()
.mul(7331.0)
.sin()
* 0.3,
((global_time + anim_time) as f32 / 1.5)
.floor()
.mul(1337.0)
.sin()
* 0.15,
);
next.head.offset = Vec3::new(
0.0 + skeleton_attr.neck_right + wave_slow_cos * 0.2,
1.0 + skeleton_attr.neck_forward,
skeleton_attr.neck_height + 13.5 + wave_ultra_slow * 0.2,
);
next.head.ori = Quaternion::rotation_x(-0.25);
next.head.scale = Vec3::one() * 1.01 * skeleton_attr.head_scale;
next.chest.offset = Vec3::new(0.0 + wave_slow_cos * 0.2, 0.0, 5.0 + wave_ultra_slow * 0.2);
next.chest.ori =
Quaternion::rotation_x(-0.15) * Quaternion::rotation_y(wave_ultra_slow_cos * 0.01);
next.chest.scale = Vec3::one();
next.belt.offset = Vec3::new(0.0 + wave_slow_cos * 0.2, 0.0, 3.0 + wave_ultra_slow * 0.2);
next.belt.ori =
Quaternion::rotation_x(0.0) * Quaternion::rotation_y(wave_ultra_slow_cos * 0.008);
next.belt.scale = Vec3::one() * 1.01;
next.shorts.offset = Vec3::new(0.0 + wave_slow_cos * 0.2, 0.0, 1.0 + wave_ultra_slow * 0.2);
next.shorts.ori = Quaternion::rotation_x(0.1);
next.shorts.scale = Vec3::one();
match Tool::Hammer {
//TODO: Inventory
Tool::Sword => {
next.l_hand.offset = Vec3::new(-6.0, 3.5, 0.0 + wave_ultra_slow * 1.0);
next.l_hand.ori = Quaternion::rotation_x(-0.3);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(-6.0, 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x,
4.5 + skeleton_attr.weapon_y,
0.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
}
Tool::Axe => {
next.l_hand.offset = Vec3::new(
-6.0 + wave_ultra_slow_cos * 1.0,
3.5 + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.l_hand.ori = Quaternion::rotation_x(-0.3);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(
-6.0 + wave_ultra_slow_cos * 1.0,
3.0 + wave_ultra_slow_cos * 0.5,
-2.0 + wave_ultra_slow * 1.0,
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x,
4.5 + skeleton_attr.weapon_y,
0.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
}
Tool::Hammer => {
next.l_hand.offset = Vec3::new(-5.5, 10.0 + wave_ultra_slow * 2.0, 9.5);
next.l_hand.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.35)
* Quaternion::rotation_z(0.5);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(8.4, 9.3 + wave_ultra_slow * 2.0, 7.5);
next.r_hand.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.35)
* Quaternion::rotation_z(0.5);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
7.0 + skeleton_attr.weapon_x,
10.75 + skeleton_attr.weapon_y + wave_ultra_slow * 2.0,
7.5,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.35)
* Quaternion::rotation_z(0.5);
next.weapon.scale = Vec3::one();
}
Tool::Staff => {
next.l_hand.offset = Vec3::new(
-6.0 + wave_ultra_slow_cos * 1.0,
3.5 + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.l_hand.ori = Quaternion::rotation_x(-0.3);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(
-6.0 + wave_ultra_slow_cos * 1.0,
3.0 + wave_ultra_slow_cos * 0.5,
-2.0 + wave_ultra_slow * 1.0,
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
4.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
}
Tool::SwordShield => {
next.l_hand.offset = Vec3::new(
-6.0 + wave_ultra_slow_cos * 1.0,
3.5 + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.l_hand.ori = Quaternion::rotation_x(-0.3);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(
-6.0 + wave_ultra_slow_cos * 1.0,
3.0 + wave_ultra_slow_cos * 0.5,
-2.0 + wave_ultra_slow * 1.0,
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
4.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
}
Tool::Bow => {
next.l_hand.offset = Vec3::new(
-6.0 + wave_ultra_slow_cos * 1.0,
3.5 + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.l_hand.ori = Quaternion::rotation_x(-0.3);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(
-6.0 + wave_ultra_slow_cos * 1.0,
3.0 + wave_ultra_slow_cos * 0.5,
-2.0 + wave_ultra_slow * 1.0,
);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x + wave_ultra_slow_cos * 1.0,
4.5 + skeleton_attr.weapon_y + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
}
Tool::Daggers => {
next.l_hand.offset = Vec3::new(
-6.0 + wave_ultra_slow_cos * 1.0,
3.5 + wave_ultra_slow_cos * 0.5,
0.0 + wave_ultra_slow * 1.0,
);
next.l_hand.ori = Quaternion::rotation_x(-0.3);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(-6.0, 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
-6.0 + skeleton_attr.weapon_x,
4.5 + skeleton_attr.weapon_y,
0.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
}
}
next.l_foot.offset = Vec3::new(-3.4, 0.3, 8.0 + wave_ultra_slow_cos * 0.1);
next.l_foot.ori = Quaternion::rotation_x(-0.3);
next.l_foot.scale = Vec3::one();
next.r_foot.offset = Vec3::new(3.4, 1.2, 8.0 + wave_ultra_slow * 0.1);
next.r_foot.ori = Quaternion::rotation_x(0.3);
next.r_foot.scale = Vec3::one();
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(0.0);
next.l_shoulder.scale = Vec3::one() * 1.1;
next.r_shoulder.offset = Vec3::new(5.0, 0.0, 4.7);
next.r_shoulder.ori = Quaternion::rotation_x(0.0);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, -0.2, 0.1) * skeleton_attr.scaler;
next.torso.ori = Quaternion::rotation_x(0.0);
next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler;
next
}
}

View File

@ -7,9 +7,9 @@ use std::f32::consts::PI;
use std::ops::Mul;
use vek::*;
pub struct CrunAnimation;
pub struct WieldAnimation;
impl Animation for CrunAnimation {
impl Animation for WieldAnimation {
type Skeleton = CharacterSkeleton;
type Dependency = (f32, f64);
@ -40,26 +40,6 @@ impl Animation for CrunAnimation {
* 0.1,
);
next.head.offset = Vec3::new(
0.0,
0.0 + skeleton_attr.neck_forward,
skeleton_attr.neck_height + 15.0 + wave_cos * 1.3,
);
next.head.ori = Quaternion::rotation_z(head_look.x + wave * 0.1)
* Quaternion::rotation_x(head_look.y + 0.35);
next.head.scale = Vec3::one() * skeleton_attr.head_scale;
next.chest.offset = Vec3::new(0.0, 0.0, 7.0 + wave_cos * 1.1);
next.chest.ori = Quaternion::rotation_z(wave * 0.15);
next.chest.scale = Vec3::one();
next.belt.offset = Vec3::new(0.0, 0.0, 5.0 + wave_cos * 1.1);
next.belt.ori = Quaternion::rotation_z(wave * 0.25);
next.belt.scale = Vec3::one();
next.shorts.offset = Vec3::new(0.0, 0.0, 2.0 + wave_cos * 1.1);
next.shorts.ori = Quaternion::rotation_z(wave * 0.4);
next.shorts.scale = Vec3::one();
match Tool::Hammer {
//TODO: Inventory
@ -187,30 +167,6 @@ impl Animation for CrunAnimation {
next.weapon.scale = Vec3::one();
}
}
next.l_foot.offset = Vec3::new(-3.4, 0.0 + wave_cos * 1.0, 6.0 - wave_cos_dub * 0.7);
next.l_foot.ori = Quaternion::rotation_x(-0.0 - wave_cos * 1.5);
next.l_foot.scale = Vec3::one();
next.r_foot.offset = Vec3::new(3.4, 0.0 - wave_cos * 1.0, 6.0 - wave_cos_dub * 0.7);
next.r_foot.ori = Quaternion::rotation_x(-0.0 + wave_cos * 1.5);
next.r_foot.scale = Vec3::one();
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(wave_cos * 0.15);
next.l_shoulder.scale = Vec3::one() * 1.1;
next.r_shoulder.offset = Vec3::new(5.0, 0.0, 4.7);
next.r_shoulder.ori = Quaternion::rotation_x(wave * 0.15);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, -0.2 + wave * -0.08, 0.2) * skeleton_attr.scaler;
next.torso.ori =
Quaternion::rotation_x(wave_stop * velocity * -0.04 + wave_diff * velocity * -0.005);
next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler;
next
}

View File

@ -1,25 +1,27 @@
pub mod attack;
pub mod block;
pub mod blockidle;
pub mod cidle;
pub mod cjump;
pub mod crun;
pub mod gliding;
pub mod idle;
pub mod jump;
pub mod roll;
pub mod run;
pub mod stand;
pub mod wield;
// Reexports
pub use self::attack::AttackAnimation;
pub use self::block::BlockAnimation;
pub use self::blockidle::BlockIdleAnimation;
pub use self::cidle::CidleAnimation;
pub use self::cjump::CjumpAnimation;
pub use self::crun::CrunAnimation;
pub use self::gliding::GlidingAnimation;
pub use self::idle::IdleAnimation;
pub use self::jump::JumpAnimation;
pub use self::roll::RollAnimation;
pub use self::run::RunAnimation;
pub use self::stand::StandAnimation;
pub use self::wield::WieldAnimation;
use super::{Bone, Skeleton};
use crate::render::FigureBoneData;

View File

@ -10,22 +10,22 @@ pub struct RunAnimation;
impl Animation for RunAnimation {
type Skeleton = CharacterSkeleton;
type Dependency = (f32, f64);
type Dependency = (f32, f32, f64);
fn update_skeleton(
skeleton: &Self::Skeleton,
(velocity, global_time): Self::Dependency,
(velocity, orientation, global_time): Self::Dependency,
anim_time: f64,
skeleton_attr: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let wave = (anim_time as f32 * 12.0).sin();
let wave_cos = (anim_time as f32 * 12.0).cos();
let wave_diff = (anim_time as f32 * 12.0 + PI / 2.0).sin();
let wave_cos_dub = (anim_time as f32 * 24.0).cos();
let wave_stop = (anim_time as f32 * 2.6).min(PI / 2.0).sin();
let wave = (anim_time as f32 * velocity * 1.2).sin();
let wave_cos = (anim_time as f32 * velocity * 1.2).cos();
let wave_diff = (anim_time as f32 * velocity * 0.6).sin();
let wave_cos_dub = (anim_time as f32 * velocity * 2.4).cos();
let wave_stop = (anim_time as f32 * 2.6).min(PI / 2.0).sin();
let head_look = Vec2::new(
((global_time + anim_time) as f32 / 2.0)
.floor()
@ -39,6 +39,19 @@ impl Animation for RunAnimation {
* 0.1,
);
let vel = Vec2::from(velocity);
let ori = (Vec2::from(orientation)).normalized();
let _tilt = if Vec2::new(ori, vel)
.map(|v| Vec2::<f32>::from(v).magnitude_squared())
.reduce_partial_min()
> 0.001
{
vel.normalized().dot(ori.normalized()).min(1.0).acos()
} else {
0.0
};
next.head.offset = Vec3::new(
0.0,
-1.0 + skeleton_attr.neck_forward,
@ -107,7 +120,8 @@ impl Animation for RunAnimation {
next.torso.offset = Vec3::new(0.0, -0.2 + wave * -0.08, 0.4) * skeleton_attr.scaler;
next.torso.ori =
Quaternion::rotation_x(wave_stop * velocity * -0.06 + wave_diff * velocity * -0.005);
Quaternion::rotation_x(wave_stop * velocity * -0.06 + wave_diff * velocity * -0.005)
* Quaternion::rotation_y(0.0);
next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler;
next

View File

@ -0,0 +1,112 @@
use super::{
super::{Animation, SkeletonAttr},
CharacterSkeleton,
};
use std::{f32::consts::PI, ops::Mul};
use vek::*;
pub struct Input {
pub attack: bool,
}
pub struct StandAnimation;
impl Animation for StandAnimation {
type Skeleton = CharacterSkeleton;
type Dependency = f64;
fn update_skeleton(
skeleton: &Self::Skeleton,
global_time: f64,
anim_time: f64,
skeleton_attr: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let wave_ultra_slow = (anim_time as f32 * 1.0 + PI).sin();
let wave_ultra_slow_cos = (anim_time as f32 * 1.0 + PI).cos();
let head_look = Vec2::new(
((global_time + anim_time) as f32 / 12.0)
.floor()
.mul(7331.0)
.sin()
* 0.5,
((global_time + anim_time) as f32 / 12.0)
.floor()
.mul(1337.0)
.sin()
* 0.25,
);
next.head.offset = Vec3::new(
0.0 + skeleton_attr.neck_right,
0.0 + skeleton_attr.neck_forward,
skeleton_attr.neck_height + 15.0 + wave_ultra_slow * 0.3,
);
next.head.ori =
Quaternion::rotation_z(head_look.x) * Quaternion::rotation_x(head_look.y.abs());
next.head.scale = Vec3::one() * skeleton_attr.head_scale;
next.chest.offset = Vec3::new(0.0, 0.0, 7.0 + wave_ultra_slow * 0.3);
next.chest.ori = Quaternion::rotation_x(0.0);
next.chest.scale = Vec3::one();
next.belt.offset = Vec3::new(0.0, 0.0, 5.0 + wave_ultra_slow * 0.3);
next.belt.ori = Quaternion::rotation_x(0.0);
next.belt.scale = Vec3::one();
next.shorts.offset = Vec3::new(0.0, 0.0, 2.0 + wave_ultra_slow * 0.3);
next.shorts.ori = Quaternion::rotation_x(0.0);
next.shorts.scale = Vec3::one();
next.l_hand.offset = Vec3::new(
-7.5,
0.0 + wave_ultra_slow_cos * 0.15,
0.0 + wave_ultra_slow * 0.5,
);
next.l_hand.ori = Quaternion::rotation_x(0.0 + wave_ultra_slow * -0.06);
next.l_hand.scale = Vec3::one();
next.r_hand.offset = Vec3::new(
7.5,
0.0 + wave_ultra_slow_cos * 0.15,
0.0 + wave_ultra_slow * 0.5,
);
next.r_hand.ori = Quaternion::rotation_x(0.0 + wave_ultra_slow * -0.06);
next.r_hand.scale = Vec3::one();
next.l_foot.offset = Vec3::new(-3.4, -0.1, 8.0);
next.l_foot.ori = Quaternion::identity();
next.l_foot.scale = Vec3::one();
next.r_foot.offset = Vec3::new(3.4, -0.1, 8.0);
next.r_foot.ori = Quaternion::identity();
next.r_foot.scale = Vec3::one();
next.weapon.offset = Vec3::new(
-7.0 + skeleton_attr.weapon_x,
-5.0 + skeleton_attr.weapon_y,
15.0,
);
next.weapon.ori = Quaternion::rotation_y(2.5) * Quaternion::rotation_z(1.57);
next.weapon.scale = Vec3::one();
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(0.0);
next.l_shoulder.scale = Vec3::one() * 1.1;
next.r_shoulder.offset = Vec3::new(5.0, 0.0, 4.7);
next.r_shoulder.ori = Quaternion::rotation_x(0.0);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, -0.2, 0.1) * skeleton_attr.scaler;
next.torso.ori = Quaternion::rotation_x(0.0);
next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler;
next
}
}

View File

@ -3,59 +3,37 @@ use super::{
CharacterSkeleton,
};
use common::comp::item::Tool;
use std::f32::consts::PI;
use vek::*;
pub struct CjumpAnimation;
pub struct WieldAnimation;
impl Animation for CjumpAnimation {
impl Animation for WieldAnimation {
type Skeleton = CharacterSkeleton;
type Dependency = f64;
type Dependency = (f32, f64);
fn update_skeleton(
skeleton: &Self::Skeleton,
_global_time: f64,
(_velocity, _global_time): Self::Dependency,
anim_time: f64,
skeleton_attr: &SkeletonAttr,
) -> Self::Skeleton {
let mut next = (*skeleton).clone();
let wave_slow = (anim_time as f32 * 7.0).sin();
let wave_stop = (anim_time as f32 * 4.5).min(PI / 2.0).sin();
next.head.offset = Vec3::new(
0.0 + skeleton_attr.neck_right,
0.0 + skeleton_attr.neck_forward,
skeleton_attr.neck_height + 15.0,
);
next.head.ori = Quaternion::rotation_x(0.25 + wave_stop * 0.1 + wave_slow * 0.04);
next.head.scale = Vec3::one() * skeleton_attr.head_scale;
next.chest.offset = Vec3::new(0.0, 0.0, 8.0);
next.chest.ori = Quaternion::rotation_z(0.0);
next.chest.scale = Vec3::one();
next.belt.offset = Vec3::new(0.0, 0.0, 6.0);
next.belt.ori = Quaternion::rotation_z(0.0);
next.belt.scale = Vec3::one();
next.shorts.offset = Vec3::new(0.0, 0.0, 3.0);
next.shorts.ori = Quaternion::rotation_z(0.0);
next.shorts.scale = Vec3::one();
let wave = (anim_time as f32 * 12.0).sin();
match Tool::Hammer {
//TODO: Inventory
Tool::Sword => {
next.l_hand.offset = Vec3::new(-7.0, 3.25, 0.25 + wave_stop * 2.0);
next.l_hand.offset = Vec3::new(-6.0, 3.75, 0.25);
next.l_hand.ori = Quaternion::rotation_x(-0.3);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(-7.0, 3.0, -2.0 + wave_stop * 2.0);
next.r_hand.offset = Vec3::new(-6.0, 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
-7.0 + skeleton_attr.weapon_x,
-6.0 + skeleton_attr.weapon_x,
4.0 + skeleton_attr.weapon_y,
0.0 + wave_stop * 2.0,
0.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(0.0)
@ -80,45 +58,41 @@ impl Animation for CjumpAnimation {
next.weapon.scale = Vec3::one();
}
Tool::Hammer => {
next.l_hand.offset = Vec3::new(-7.0, 8.25, 2.0 + wave_stop * 2.0);
next.l_hand.offset = Vec3::new(-7.0, 8.25, 3.0);
next.l_hand.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.2)
* Quaternion::rotation_z(0.0);
* Quaternion::rotation_z(wave * -0.25);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(7.0, 7.0, -3.0 + wave_stop * 2.0);
next.r_hand.offset = Vec3::new(7.0, 7.0, -1.5);
next.r_hand.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.2)
* Quaternion::rotation_z(0.0);
* Quaternion::rotation_z(wave * -0.25);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
5.0 + skeleton_attr.weapon_x,
8.75 + skeleton_attr.weapon_y,
-2.5 + wave_stop * 2.0,
-2.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.2)
* Quaternion::rotation_z(0.0);
* Quaternion::rotation_z(wave * -0.25);
next.weapon.scale = Vec3::one();
}
Tool::Staff => {
next.l_hand.offset = Vec3::new(-7.0, 7.5, 0.0);
next.l_hand.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.7)
* Quaternion::rotation_z(1.0);
next.l_hand.offset = Vec3::new(-6.0, 3.5, 0.0);
next.l_hand.ori = Quaternion::rotation_x(-0.3);
next.l_hand.scale = Vec3::one() * 1.01;
next.r_hand.offset = Vec3::new(7.0, 6.25, 1.5);
next.r_hand.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.7)
* Quaternion::rotation_z(1.0);
next.r_hand.offset = Vec3::new(-6.0, 3.0, -2.0);
next.r_hand.ori = Quaternion::rotation_x(-0.3);
next.r_hand.scale = Vec3::one() * 1.01;
next.weapon.offset = Vec3::new(
5.0 + skeleton_attr.weapon_x,
8.0 + skeleton_attr.weapon_y,
1.0,
-6.0 + skeleton_attr.weapon_x,
4.5 + skeleton_attr.weapon_y,
0.0,
);
next.weapon.ori = Quaternion::rotation_x(-0.3)
* Quaternion::rotation_y(-1.7)
* Quaternion::rotation_z(1.0);
* Quaternion::rotation_y(0.0)
* Quaternion::rotation_z(0.0);
next.weapon.scale = Vec3::one();
}
Tool::SwordShield => {
@ -174,30 +148,6 @@ impl Animation for CjumpAnimation {
}
}
next.l_foot.offset = Vec3::new(-3.4, 1.0, 6.0);
next.l_foot.ori = Quaternion::rotation_x(wave_stop * -1.2 - wave_slow * 0.2);
next.l_foot.scale = Vec3::one();
next.r_foot.offset = Vec3::new(3.4, -1.0, 6.0);
next.r_foot.ori = Quaternion::rotation_x(wave_stop * 1.2 + wave_slow * 0.2);
next.r_foot.scale = Vec3::one();
next.l_shoulder.offset = Vec3::new(-5.0, 0.0, 4.7);
next.l_shoulder.ori = Quaternion::rotation_x(0.0);
next.l_shoulder.scale = Vec3::one() * 1.1;
next.r_shoulder.offset = Vec3::new(5.0, 0.0, 4.7);
next.r_shoulder.ori = Quaternion::rotation_x(0.0);
next.r_shoulder.scale = Vec3::one() * 1.1;
next.draw.offset = Vec3::new(0.0, 5.0, 0.0);
next.draw.ori = Quaternion::rotation_y(0.0);
next.draw.scale = Vec3::one() * 0.0;
next.torso.offset = Vec3::new(0.0, -0.2, 0.0) * skeleton_attr.scaler;
next.torso.ori = Quaternion::rotation_x(-0.2);
next.torso.scale = Vec3::one() / 11.0 * skeleton_attr.scaler;
next
}
}

View File

@ -1,7 +1,7 @@
use crate::{
anim::{
self, character::CharacterSkeleton, object::ObjectSkeleton, quadruped::QuadrupedSkeleton,
quadrupedmedium::QuadrupedMediumSkeleton, Animation, Skeleton, SkeletonAttr,
quadrupedmedium::QuadrupedMediumSkeleton, Animation as _, Skeleton, SkeletonAttr,
},
mesh::Meshable,
render::{
@ -13,7 +13,8 @@ use client::Client;
use common::{
assets,
comp::{
self, humanoid, item::Tool, object, quadruped, quadruped_medium, Body, Equipment, Item,
humanoid, item::Tool, object, quadruped, quadruped_medium, ActionState::*, Body,
CharacterState, Equipment, Item, Last, MovementState::*, Ori, Pos, Scale, Stats, Vel,
},
figure::Segment,
terrain::TerrainChunkSize,
@ -23,7 +24,7 @@ use dot_vox::DotVoxData;
use hashbrown::HashMap;
use log::debug;
use specs::{Entity as EcsEntity, Join};
use std::f32;
use std::{f32, time::Instant};
use vek::*;
const DAMAGE_FADE_COEFFICIENT: f64 = 5.0;
@ -618,19 +619,20 @@ impl FigureMgr {
let dt = client.state().get_delta_time();
// Get player position.
let player_pos = ecs
.read_storage::<comp::Pos>()
.read_storage::<Pos>()
.get(client.entity())
.map_or(Vec3::zero(), |pos| pos.0);
for (entity, pos, vel, ori, scale, body, animation_info, stats) in (
for (entity, pos, vel, ori, scale, body, character, last_character, stats) in (
&ecs.entities(),
&ecs.read_storage::<comp::Pos>(),
&ecs.read_storage::<comp::Vel>(),
&ecs.read_storage::<comp::Ori>(),
ecs.read_storage::<comp::Scale>().maybe(),
&ecs.read_storage::<comp::Body>(),
ecs.read_storage::<comp::AnimationInfo>().maybe(),
ecs.read_storage::<comp::Stats>().maybe(),
&ecs.read_storage::<Pos>(),
&ecs.read_storage::<Vel>(),
&ecs.read_storage::<Ori>(),
ecs.read_storage::<Scale>().maybe(),
&ecs.read_storage::<Body>(),
ecs.read_storage::<CharacterState>().maybe(),
ecs.read_storage::<Last<CharacterState>>().maybe(),
ecs.read_storage::<Stats>().maybe(),
)
.join()
{
@ -683,80 +685,92 @@ impl FigureMgr {
.character_states
.entry(entity)
.or_insert_with(|| FigureState::new(renderer, CharacterSkeleton::new()));
let animation_info = match animation_info {
Some(a_i) => a_i,
None => continue,
let (character, last_character) = match (character, last_character) {
(Some(c), Some(l)) => (c, l),
_ => continue,
};
let target_skeleton = match animation_info.animation {
comp::Animation::Idle => anim::character::IdleAnimation::update_skeleton(
state.skeleton_mut(),
if !character.is_same_movement(&last_character.0) {
state.last_movement_change = Instant::now();
}
if !character.is_same_action(&last_character.0) {
state.last_action_change = Instant::now();
}
let time_since_movement_change =
state.last_movement_change.elapsed().as_secs_f64();
let time_since_action_change = state.last_action_change.elapsed().as_secs_f64();
let target_base = match &character.movement {
Stand => anim::character::StandAnimation::update_skeleton(
&CharacterSkeleton::new(),
time,
animation_info.time,
time_since_movement_change,
skeleton_attr,
),
comp::Animation::Run => anim::character::RunAnimation::update_skeleton(
state.skeleton_mut(),
Run => anim::character::RunAnimation::update_skeleton(
&CharacterSkeleton::new(),
(vel.0.magnitude(), ori.0.magnitude(), time),
time_since_movement_change,
skeleton_attr,
),
Jump => anim::character::JumpAnimation::update_skeleton(
&CharacterSkeleton::new(),
time,
time_since_movement_change,
skeleton_attr,
),
Roll { .. } => anim::character::RollAnimation::update_skeleton(
&CharacterSkeleton::new(),
time,
time_since_movement_change,
skeleton_attr,
),
Glide => anim::character::GlidingAnimation::update_skeleton(
&CharacterSkeleton::new(),
(vel.0.magnitude(), time),
animation_info.time,
time_since_movement_change,
skeleton_attr,
),
comp::Animation::Jump => anim::character::JumpAnimation::update_skeleton(
state.skeleton_mut(),
};
let target_bones = match (&character.movement, &character.action) {
(Stand, Wield { .. }) => anim::character::CidleAnimation::update_skeleton(
&target_base,
time,
animation_info.time,
time_since_action_change,
skeleton_attr,
),
comp::Animation::Attack => {
anim::character::AttackAnimation::update_skeleton(
state.skeleton_mut(),
(Stand, Block { .. }) => {
anim::character::BlockIdleAnimation::update_skeleton(
&target_base,
time,
animation_info.time,
time_since_action_change,
skeleton_attr,
)
}
comp::Animation::Block => anim::character::BlockAnimation::update_skeleton(
state.skeleton_mut(),
(_, Attack { .. }) => anim::character::AttackAnimation::update_skeleton(
&target_base,
time,
animation_info.time,
time_since_action_change,
skeleton_attr,
),
comp::Animation::Cjump => anim::character::CjumpAnimation::update_skeleton(
state.skeleton_mut(),
time,
animation_info.time,
skeleton_attr,
),
comp::Animation::Roll => anim::character::RollAnimation::update_skeleton(
state.skeleton_mut(),
time,
animation_info.time,
skeleton_attr,
),
comp::Animation::Crun => anim::character::CrunAnimation::update_skeleton(
state.skeleton_mut(),
(_, Wield { .. }) => anim::character::WieldAnimation::update_skeleton(
&target_base,
(vel.0.magnitude(), time),
animation_info.time,
time_since_action_change,
skeleton_attr,
),
comp::Animation::Cidle => anim::character::CidleAnimation::update_skeleton(
state.skeleton_mut(),
(_, Block { .. }) => anim::character::BlockAnimation::update_skeleton(
&target_base,
time,
animation_info.time,
time_since_action_change,
skeleton_attr,
),
comp::Animation::Gliding => {
anim::character::GlidingAnimation::update_skeleton(
state.skeleton_mut(),
(vel.0.magnitude(), time),
animation_info.time,
skeleton_attr,
)
}
_ => target_base,
};
state.skeleton.interpolate(&target_bones, dt);
state.skeleton.interpolate(&target_skeleton, dt);
state.update(renderer, pos.0, ori.0, scale, col, dt);
}
Body::Quadruped(_) => {
@ -765,42 +779,43 @@ impl FigureMgr {
.entry(entity)
.or_insert_with(|| FigureState::new(renderer, QuadrupedSkeleton::new()));
let animation_info = match animation_info {
Some(a_i) => a_i,
None => continue,
let (character, last_character) = match (character, last_character) {
(Some(c), Some(l)) => (c, l),
_ => continue,
};
let target_skeleton = match animation_info.animation {
comp::Animation::Run | comp::Animation::Crun => {
anim::quadruped::RunAnimation::update_skeleton(
state.skeleton_mut(),
(vel.0.magnitude(), time),
animation_info.time,
skeleton_attr,
)
}
comp::Animation::Idle | comp::Animation::Cidle => {
anim::quadruped::IdleAnimation::update_skeleton(
state.skeleton_mut(),
time,
animation_info.time,
skeleton_attr,
)
}
comp::Animation::Jump | comp::Animation::Cjump => {
anim::quadruped::JumpAnimation::update_skeleton(
state.skeleton_mut(),
(vel.0.magnitude(), time),
animation_info.time,
skeleton_attr,
)
}
if !character.is_same_movement(&last_character.0) {
state.last_movement_change = Instant::now();
}
let time_since_movement_change =
state.last_movement_change.elapsed().as_secs_f64();
let target_base = match character.movement {
Stand => anim::quadruped::IdleAnimation::update_skeleton(
&QuadrupedSkeleton::new(),
time,
time_since_movement_change,
skeleton_attr,
),
Run => anim::quadruped::RunAnimation::update_skeleton(
&QuadrupedSkeleton::new(),
(vel.0.magnitude(), time),
time_since_movement_change,
skeleton_attr,
),
Jump => anim::quadruped::JumpAnimation::update_skeleton(
&QuadrupedSkeleton::new(),
(vel.0.magnitude(), time),
time_since_movement_change,
skeleton_attr,
),
// TODO!
_ => state.skeleton_mut().clone(),
};
state.skeleton.interpolate(&target_skeleton, dt);
state.skeleton.interpolate(&target_base, dt);
state.update(renderer, pos.0, ori.0, scale, col, dt);
}
Body::QuadrupedMedium(_) => {
@ -811,42 +826,43 @@ impl FigureMgr {
FigureState::new(renderer, QuadrupedMediumSkeleton::new())
});
let animation_info = match animation_info {
Some(a_i) => a_i,
None => continue,
let (character, last_character) = match (character, last_character) {
(Some(c), Some(l)) => (c, l),
_ => continue,
};
let target_skeleton = match animation_info.animation {
comp::Animation::Run | comp::Animation::Crun => {
anim::quadrupedmedium::RunAnimation::update_skeleton(
state.skeleton_mut(),
(vel.0.magnitude(), time),
animation_info.time,
skeleton_attr,
)
}
comp::Animation::Idle | comp::Animation::Cidle => {
anim::quadrupedmedium::IdleAnimation::update_skeleton(
state.skeleton_mut(),
time,
animation_info.time,
skeleton_attr,
)
}
comp::Animation::Jump | comp::Animation::Cjump => {
anim::quadrupedmedium::JumpAnimation::update_skeleton(
state.skeleton_mut(),
(vel.0.magnitude(), time),
animation_info.time,
skeleton_attr,
)
}
if !character.is_same_movement(&last_character.0) {
state.last_movement_change = Instant::now();
}
let time_since_movement_change =
state.last_movement_change.elapsed().as_secs_f64();
let target_base = match character.movement {
Stand => anim::quadrupedmedium::IdleAnimation::update_skeleton(
&QuadrupedMediumSkeleton::new(),
time,
time_since_movement_change,
skeleton_attr,
),
Run => anim::quadrupedmedium::RunAnimation::update_skeleton(
&QuadrupedMediumSkeleton::new(),
(vel.0.magnitude(), time),
time_since_movement_change,
skeleton_attr,
),
Jump => anim::quadrupedmedium::JumpAnimation::update_skeleton(
&QuadrupedMediumSkeleton::new(),
(vel.0.magnitude(), time),
time_since_movement_change,
skeleton_attr,
),
// TODO!
_ => state.skeleton_mut().clone(),
};
state.skeleton.interpolate(&target_skeleton, dt);
state.skeleton.interpolate(&target_base, dt);
state.update(renderer, pos.0, ori.0, scale, col, dt);
}
Body::Object(_) => {
@ -887,12 +903,12 @@ impl FigureMgr {
for (entity, _, _, _, body, stats, _) in (
&ecs.entities(),
&ecs.read_storage::<comp::Pos>(),
&ecs.read_storage::<comp::Vel>(),
&ecs.read_storage::<comp::Ori>(),
&ecs.read_storage::<comp::Body>(),
ecs.read_storage::<comp::Stats>().maybe(),
ecs.read_storage::<comp::Scale>().maybe(),
&ecs.read_storage::<Pos>(),
&ecs.read_storage::<Vel>(),
&ecs.read_storage::<Ori>(),
&ecs.read_storage::<Body>(),
ecs.read_storage::<Stats>().maybe(),
ecs.read_storage::<Scale>().maybe(),
)
.join()
// Don't render figures outside of frustum (camera viewport, max draw distance is farplane)
@ -901,7 +917,7 @@ impl FigureMgr {
&pos.0.x,
&pos.0.y,
&pos.0.z,
&(scale.unwrap_or(&comp::Scale(1.0)).0 * 2.0),
&(scale.unwrap_or(&Scale(1.0)).0 * 2.0),
)
})
// Don't render dead entities
@ -934,7 +950,7 @@ impl FigureMgr {
if camera.get_mode() == CameraMode::FirstPerson
&& client
.state()
.read_storage::<comp::Body>()
.read_storage::<Body>()
.get(client.entity())
.is_some()
&& entity == client.entity()
@ -953,6 +969,8 @@ impl FigureMgr {
pub struct FigureState<S: Skeleton> {
bone_consts: Consts<FigureBoneData>,
locals: Consts<FigureLocals>,
last_movement_change: Instant,
last_action_change: Instant,
skeleton: S,
pos: Vec3<f32>,
ori: Vec3<f32>,
@ -965,6 +983,8 @@ impl<S: Skeleton> FigureState<S> {
.create_consts(&skeleton.compute_matrices())
.unwrap(),
locals: renderer.create_consts(&[FigureLocals::default()]).unwrap(),
last_movement_change: Instant::now(),
last_action_change: Instant::now(),
skeleton,
pos: Vec3::zero(),
ori: Vec3::zero(),