mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Object animation
This commit is contained in:
parent
775224983b
commit
e7bbf3981d
@ -11,4 +11,5 @@ BasicBeam(
|
|||||||
energy_regen: 25,
|
energy_regen: 25,
|
||||||
energy_cost: 50,
|
energy_cost: 50,
|
||||||
energy_drain: 0,
|
energy_drain: 0,
|
||||||
|
orientation_behavior: Normal,
|
||||||
)
|
)
|
@ -11,4 +11,5 @@ BasicBeam(
|
|||||||
energy_regen: 0,
|
energy_regen: 0,
|
||||||
energy_cost: 1,
|
energy_cost: 1,
|
||||||
energy_drain: 350,
|
energy_drain: 350,
|
||||||
|
orientation_behavior: Normal,
|
||||||
)
|
)
|
@ -11,4 +11,5 @@ BasicBeam(
|
|||||||
energy_regen: 0,
|
energy_regen: 0,
|
||||||
energy_cost: 0,
|
energy_cost: 0,
|
||||||
energy_drain: 0,
|
energy_drain: 0,
|
||||||
|
orientation_behavior: Normal,
|
||||||
)
|
)
|
@ -1,15 +1,15 @@
|
|||||||
BasicRanged(
|
BasicBeam(
|
||||||
|
buildup_duration: 250,
|
||||||
|
recover_duration: 250,
|
||||||
|
beam_duration: 500,
|
||||||
|
base_hps: 0,
|
||||||
|
base_dps: 150,
|
||||||
|
tick_rate: 3.0,
|
||||||
|
range: 30.0,
|
||||||
|
max_angle: 5.0,
|
||||||
|
lifesteal_eff: 0.0,
|
||||||
|
energy_regen: 0,
|
||||||
energy_cost: 0,
|
energy_cost: 0,
|
||||||
buildup_duration: 500,
|
energy_drain: 0,
|
||||||
recover_duration: 300,
|
orientation_behavior: Turret(5.0),
|
||||||
projectile: Arrow(
|
|
||||||
damage: 200.0,
|
|
||||||
knockback: 5.0,
|
|
||||||
energy_regen: 100,
|
|
||||||
),
|
|
||||||
projectile_body: Object(ArrowTurret),
|
|
||||||
projectile_light: None,
|
|
||||||
projectile_gravity: Some(Gravity(0.1)),
|
|
||||||
projectile_speed: 100.0,
|
|
||||||
can_continue: true,
|
|
||||||
)
|
)
|
@ -222,9 +222,10 @@ pub enum CharacterAbility {
|
|||||||
range: f32,
|
range: f32,
|
||||||
max_angle: f32,
|
max_angle: f32,
|
||||||
lifesteal_eff: f32,
|
lifesteal_eff: f32,
|
||||||
energy_regen: f32,
|
energy_regen: u32,
|
||||||
energy_cost: f32,
|
energy_cost: u32,
|
||||||
energy_drain: f32,
|
energy_drain: u32,
|
||||||
|
orientation_behavior: basic_beam::OrientationBehavior,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1445,6 +1446,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
energy_regen,
|
energy_regen,
|
||||||
energy_cost,
|
energy_cost,
|
||||||
energy_drain,
|
energy_drain,
|
||||||
|
orientation_behavior,
|
||||||
} => CharacterState::BasicBeam(basic_beam::Data {
|
} => CharacterState::BasicBeam(basic_beam::Data {
|
||||||
static_data: basic_beam::StaticData {
|
static_data: basic_beam::StaticData {
|
||||||
buildup_duration: Duration::from_secs_f32(*buildup_duration),
|
buildup_duration: Duration::from_secs_f32(*buildup_duration),
|
||||||
@ -1460,6 +1462,7 @@ impl From<(&CharacterAbility, AbilityInfo)> for CharacterState {
|
|||||||
energy_cost: *energy_cost,
|
energy_cost: *energy_cost,
|
||||||
energy_drain: *energy_drain,
|
energy_drain: *energy_drain,
|
||||||
ability_info,
|
ability_info,
|
||||||
|
orientation_behavior: *orientation_behavior,
|
||||||
},
|
},
|
||||||
timer: Duration::default(),
|
timer: Duration::default(),
|
||||||
stage_section: StageSection::Buildup,
|
stage_section: StageSection::Buildup,
|
||||||
|
@ -10,10 +10,12 @@ use crate::{
|
|||||||
utils::*,
|
utils::*,
|
||||||
},
|
},
|
||||||
uid::Uid,
|
uid::Uid,
|
||||||
|
util::Dir,
|
||||||
|
Damage, DamageSource, GroupTarget,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use vek::Vec3;
|
use vek::*;
|
||||||
|
|
||||||
/// Separated out to condense update portions of character state
|
/// Separated out to condense update portions of character state
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
@ -42,7 +44,9 @@ pub struct StaticData {
|
|||||||
/// Energy consumed per second for heal ticks
|
/// Energy consumed per second for heal ticks
|
||||||
pub energy_cost: f32,
|
pub energy_cost: f32,
|
||||||
/// Energy drained per
|
/// Energy drained per
|
||||||
pub energy_drain: f32,
|
pub energy_drain: u32,
|
||||||
|
/// Used to dictate how orientation functions in this state
|
||||||
|
pub orientation_behavior: OrientationBehavior,
|
||||||
/// What key is used to press ability
|
/// What key is used to press ability
|
||||||
pub ability_info: AbilityInfo,
|
pub ability_info: AbilityInfo,
|
||||||
}
|
}
|
||||||
@ -66,6 +70,20 @@ impl CharacterBehavior for Data {
|
|||||||
fn behavior(&self, data: &JoinData) -> StateUpdate {
|
fn behavior(&self, data: &JoinData) -> StateUpdate {
|
||||||
let mut update = StateUpdate::from(data);
|
let mut update = StateUpdate::from(data);
|
||||||
|
|
||||||
|
match self.static_data.orientation_behavior {
|
||||||
|
OrientationBehavior::Normal => {},
|
||||||
|
OrientationBehavior::Turret(speed) => {
|
||||||
|
update.ori.0 = data.inputs.look_dir;
|
||||||
|
/*update.ori.0 = Dir::new(
|
||||||
|
Quaternion::from_xyzw(update.ori.0.x, update.ori.0.y, update.ori.0.z, 0.0)
|
||||||
|
.rotated_z(data.dt.0 as f32 * speed)
|
||||||
|
.into_vec3()
|
||||||
|
.try_normalized()
|
||||||
|
.unwrap_or_default(),
|
||||||
|
);*/
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
handle_move(data, &mut update, 0.4);
|
handle_move(data, &mut update, 0.4);
|
||||||
handle_jump(data, &mut update);
|
handle_jump(data, &mut update);
|
||||||
if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
if !ability_key_is_pressed(data, self.static_data.ability_info.key) {
|
||||||
@ -232,3 +250,9 @@ impl CharacterBehavior for Data {
|
|||||||
update
|
update
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||||
|
pub enum OrientationBehavior {
|
||||||
|
Normal,
|
||||||
|
Turret(f32),
|
||||||
|
}
|
||||||
|
@ -191,7 +191,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
let mut inputs = &mut controller.inputs;
|
let mut inputs = &mut controller.inputs;
|
||||||
|
|
||||||
// Default to looking in orientation direction (can be overridden below)
|
// Default to looking in orientation direction (can be overridden below)
|
||||||
//inputs.look_dir = ori.0;
|
inputs.look_dir = ori.0;
|
||||||
|
|
||||||
const AVG_FOLLOW_DIST: f32 = 6.0;
|
const AVG_FOLLOW_DIST: f32 = 6.0;
|
||||||
const MAX_FOLLOW_DIST: f32 = 12.0;
|
const MAX_FOLLOW_DIST: f32 = 12.0;
|
||||||
@ -1378,7 +1378,14 @@ impl<'a> System<'a> for Sys {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
Tactic::Turret => {
|
Tactic::Turret => {
|
||||||
inputs.look_dir = ori.0;
|
//inputs.look_dir = ori.0;
|
||||||
|
inputs.look_dir = Dir::new(
|
||||||
|
Quaternion::from_xyzw(ori.0.x, ori.0.y, 0.0, 0.0)
|
||||||
|
.rotated_z(4.0 * dt.0 as f32)
|
||||||
|
.into_vec3()
|
||||||
|
.try_normalized()
|
||||||
|
.unwrap_or_default(),
|
||||||
|
);
|
||||||
if can_see_tgt(&*terrain, pos, tgt_pos, dist_sqrd)
|
if can_see_tgt(&*terrain, pos, tgt_pos, dist_sqrd)
|
||||||
{
|
{
|
||||||
inputs.primary.set_state(true);
|
inputs.primary.set_state(true);
|
||||||
|
32
voxygen/anim/src/object/idle.rs
Normal file
32
voxygen/anim/src/object/idle.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
use super::{
|
||||||
|
super::{vek::*, Animation},
|
||||||
|
ObjectSkeleton, SkeletonAttr,
|
||||||
|
};
|
||||||
|
use common::comp::item::ToolKind;
|
||||||
|
|
||||||
|
pub struct IdleAnimation;
|
||||||
|
|
||||||
|
impl Animation for IdleAnimation {
|
||||||
|
type Dependency = (Option<ToolKind>, Option<ToolKind>, f64);
|
||||||
|
type Skeleton = ObjectSkeleton;
|
||||||
|
|
||||||
|
#[cfg(feature = "use-dyn-lib")]
|
||||||
|
const UPDATE_FN: &'static [u8] = b"object_idle\0";
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "be-dyn-lib", export_name = "object_idle")]
|
||||||
|
#[allow(clippy::approx_constant)] // TODO: Pending review in #587
|
||||||
|
fn update_skeleton_inner(
|
||||||
|
skeleton: &Self::Skeleton,
|
||||||
|
(_active_tool_kind, _second_tool_kind, _global_time): Self::Dependency,
|
||||||
|
_anim_time: f64,
|
||||||
|
_rate: &mut f32,
|
||||||
|
s_a: &SkeletonAttr,
|
||||||
|
) -> Self::Skeleton {
|
||||||
|
let mut next = (*skeleton).clone();
|
||||||
|
|
||||||
|
next.bone0.position = Vec3::new(s_a.bone0.0, s_a.bone0.1, s_a.bone0.2);
|
||||||
|
next.bone0.orientation = Quaternion::rotation_z(0.0);
|
||||||
|
|
||||||
|
next
|
||||||
|
}
|
||||||
|
}
|
@ -1,24 +1,18 @@
|
|||||||
|
pub mod idle;
|
||||||
|
pub mod shoot;
|
||||||
|
|
||||||
|
// Reexports
|
||||||
|
pub use self::{idle::IdleAnimation, shoot::ShootAnimation};
|
||||||
|
|
||||||
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
|
use super::{make_bone, vek::*, FigureBoneData, Skeleton};
|
||||||
use common::comp::{self};
|
use common::comp::{self};
|
||||||
|
use core::convert::TryFrom;
|
||||||
|
|
||||||
pub type Body = comp::object::Body;
|
pub type Body = comp::object::Body;
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
skeleton_impls!(struct ObjectSkeleton {
|
||||||
pub struct ObjectSkeleton;
|
+ bone0,
|
||||||
|
});
|
||||||
impl<'a, Factor> Lerp<Factor> for &'a ObjectSkeleton {
|
|
||||||
type Output = ObjectSkeleton;
|
|
||||||
|
|
||||||
fn lerp_unclamped_precise(_from: Self, _to: Self, _factor: Factor) -> Self::Output {
|
|
||||||
ObjectSkeleton
|
|
||||||
}
|
|
||||||
|
|
||||||
fn lerp_unclamped(_from: Self, _to: Self, _factor: Factor) -> Self::Output { ObjectSkeleton }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct SkeletonAttr;
|
|
||||||
|
|
||||||
const SCALE: f32 = 1.0 / 11.0;
|
|
||||||
|
|
||||||
impl Skeleton for ObjectSkeleton {
|
impl Skeleton for ObjectSkeleton {
|
||||||
type Attr = SkeletonAttr;
|
type Attr = SkeletonAttr;
|
||||||
@ -34,17 +28,46 @@ impl Skeleton for ObjectSkeleton {
|
|||||||
base_mat: Mat4<f32>,
|
base_mat: Mat4<f32>,
|
||||||
buf: &mut [FigureBoneData; super::MAX_BONE_COUNT],
|
buf: &mut [FigureBoneData; super::MAX_BONE_COUNT],
|
||||||
) -> Vec3<f32> {
|
) -> Vec3<f32> {
|
||||||
buf[0] = make_bone(base_mat * Mat4::scaling_3d(SCALE));
|
let bone0_mat = base_mat * Mat4::<f32>::from(self.bone0);
|
||||||
// TODO: Make dependent on bone, when we find an easier way to make that
|
|
||||||
// information available.
|
*(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) =
|
||||||
Vec3::unit_z() * 0.5
|
[make_bone(bone0_mat * Mat4::scaling_3d(1.0 / 11.0))];
|
||||||
|
Vec3::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct SkeletonAttr {
|
||||||
|
bone0: (f32, f32, f32),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> std::convert::TryFrom<&'a comp::Body> for SkeletonAttr {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn try_from(body: &'a comp::Body) -> Result<Self, Self::Error> {
|
||||||
|
match body {
|
||||||
|
comp::Body::Object(body) => Ok(SkeletonAttr::from(body)),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for SkeletonAttr {
|
impl Default for SkeletonAttr {
|
||||||
fn default() -> Self { Self }
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
bone0: (0.0, 0.0, 0.0),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> From<&'a Body> for SkeletonAttr {
|
impl<'a> From<&'a Body> for SkeletonAttr {
|
||||||
fn from(_body: &'a Body) -> Self { Self }
|
fn from(body: &'a Body) -> Self {
|
||||||
|
use comp::object::Body::*;
|
||||||
|
Self {
|
||||||
|
bone0: match body {
|
||||||
|
CampfireLit => (2.0, 0.5, 1.0),
|
||||||
|
Pouch => (2.0, 0.5, 1.0),
|
||||||
|
_ => (0.0, 0.0, 0.0),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
64
voxygen/anim/src/object/shoot.rs
Normal file
64
voxygen/anim/src/object/shoot.rs
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
use super::{
|
||||||
|
super::{vek::*, Animation},
|
||||||
|
ObjectSkeleton, SkeletonAttr,
|
||||||
|
};
|
||||||
|
use common::{comp::item::ToolKind, states::utils::StageSection};
|
||||||
|
pub struct ShootAnimation;
|
||||||
|
|
||||||
|
type ShootAnimationDependency = (
|
||||||
|
Option<ToolKind>,
|
||||||
|
Option<ToolKind>,
|
||||||
|
f32,
|
||||||
|
Vec3<f32>,
|
||||||
|
Vec3<f32>,
|
||||||
|
f64,
|
||||||
|
Option<StageSection>,
|
||||||
|
);
|
||||||
|
impl Animation for ShootAnimation {
|
||||||
|
type Dependency = ShootAnimationDependency;
|
||||||
|
type Skeleton = ObjectSkeleton;
|
||||||
|
|
||||||
|
#[cfg(feature = "use-dyn-lib")]
|
||||||
|
const UPDATE_FN: &'static [u8] = b"object_shoot\0";
|
||||||
|
|
||||||
|
#[cfg_attr(feature = "be-dyn-lib", export_name = "object_shoot")]
|
||||||
|
#[allow(clippy::approx_constant)] // TODO: Pending review in #587
|
||||||
|
fn update_skeleton_inner(
|
||||||
|
skeleton: &Self::Skeleton,
|
||||||
|
(
|
||||||
|
_active_tool_kind,
|
||||||
|
_second_tool_kind,
|
||||||
|
_velocity,
|
||||||
|
orientation,
|
||||||
|
last_ori,
|
||||||
|
_global_time,
|
||||||
|
_stage_section,
|
||||||
|
): Self::Dependency,
|
||||||
|
anim_time: f64,
|
||||||
|
rate: &mut f32,
|
||||||
|
s_a: &SkeletonAttr,
|
||||||
|
) -> Self::Skeleton {
|
||||||
|
*rate = 1.0;
|
||||||
|
|
||||||
|
let mut next = (*skeleton).clone();
|
||||||
|
|
||||||
|
let ori: Vec2<f32> = Vec2::from(orientation);
|
||||||
|
let last_ori = Vec2::from(last_ori);
|
||||||
|
let _tilt = if ::vek::Vec2::new(ori, last_ori)
|
||||||
|
.map(|o| o.magnitude_squared())
|
||||||
|
.map(|m| m > 0.001 && m.is_finite())
|
||||||
|
.reduce_and()
|
||||||
|
&& ori.angle_between(last_ori).is_finite()
|
||||||
|
{
|
||||||
|
ori.angle_between(last_ori).min(0.2)
|
||||||
|
* last_ori.determine_side(Vec2::zero(), ori).signum()
|
||||||
|
} else {
|
||||||
|
0.0
|
||||||
|
} * 1.3;
|
||||||
|
|
||||||
|
next.bone0.position = Vec3::new(s_a.bone0.0, s_a.bone0.1, s_a.bone0.2);
|
||||||
|
next.bone0.orientation = Quaternion::rotation_z(anim_time as f32 * 1.0);
|
||||||
|
|
||||||
|
next
|
||||||
|
}
|
||||||
|
}
|
@ -3472,7 +3472,7 @@ impl FigureMgr {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
Body::Object(body) => {
|
Body::Object(body) => {
|
||||||
let (model, _) = self.object_model_cache.get_or_create_model(
|
let (model, skeleton_attr) = self.object_model_cache.get_or_create_model(
|
||||||
renderer,
|
renderer,
|
||||||
&mut self.col_lights,
|
&mut self.col_lights,
|
||||||
*body,
|
*body,
|
||||||
@ -3488,6 +3488,72 @@ impl FigureMgr {
|
|||||||
FigureState::new(renderer, ObjectSkeleton::default())
|
FigureState::new(renderer, ObjectSkeleton::default())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let (character, last_character) = match (character, last_character) {
|
||||||
|
(Some(c), Some(l)) => (c, l),
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
if !character.same_variant(&last_character.0) {
|
||||||
|
state.state_time = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
let target_base = match (
|
||||||
|
physics.on_ground,
|
||||||
|
vel.0.magnitude_squared() > MOVING_THRESHOLD_SQR, // Moving
|
||||||
|
physics.in_liquid.is_some(), // In water
|
||||||
|
) {
|
||||||
|
// Standing
|
||||||
|
(true, false, false) => anim::object::IdleAnimation::update_skeleton(
|
||||||
|
&ObjectSkeleton::default(),
|
||||||
|
(active_tool_kind, second_tool_kind, time),
|
||||||
|
state.state_time,
|
||||||
|
&mut state_animation_rate,
|
||||||
|
skeleton_attr,
|
||||||
|
),
|
||||||
|
_ => anim::object::IdleAnimation::update_skeleton(
|
||||||
|
&ObjectSkeleton::default(),
|
||||||
|
(active_tool_kind, second_tool_kind, time),
|
||||||
|
state.state_time,
|
||||||
|
&mut state_animation_rate,
|
||||||
|
skeleton_attr,
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
let target_bones = match &character {
|
||||||
|
CharacterState::BasicRanged(s) => {
|
||||||
|
let stage_time = s.timer.as_secs_f64();
|
||||||
|
|
||||||
|
let stage_progress = match s.stage_section {
|
||||||
|
StageSection::Buildup => {
|
||||||
|
stage_time / s.static_data.buildup_duration.as_secs_f64()
|
||||||
|
},
|
||||||
|
StageSection::Recover => {
|
||||||
|
stage_time / s.static_data.recover_duration.as_secs_f64()
|
||||||
|
},
|
||||||
|
|
||||||
|
_ => 0.0,
|
||||||
|
};
|
||||||
|
anim::object::ShootAnimation::update_skeleton(
|
||||||
|
&target_base,
|
||||||
|
(
|
||||||
|
active_tool_kind,
|
||||||
|
second_tool_kind,
|
||||||
|
vel.0.magnitude(),
|
||||||
|
ori,
|
||||||
|
state.last_ori,
|
||||||
|
time,
|
||||||
|
Some(s.stage_section),
|
||||||
|
),
|
||||||
|
stage_progress,
|
||||||
|
&mut state_animation_rate,
|
||||||
|
skeleton_attr,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
// TODO!
|
||||||
|
_ => target_base,
|
||||||
|
};
|
||||||
|
|
||||||
|
state.skeleton = anim::vek::Lerp::lerp(&state.skeleton, &target_bones, dt_lerp);
|
||||||
state.update(
|
state.update(
|
||||||
renderer,
|
renderer,
|
||||||
pos.0,
|
pos.0,
|
||||||
|
Loading…
Reference in New Issue
Block a user