Made characters carry lanterns higher when possible

This commit is contained in:
Joshua Barretto 2021-04-21 15:59:29 +01:00
parent b10718c568
commit ed7cc12213
11 changed files with 159 additions and 31 deletions

View File

@ -167,6 +167,18 @@ impl CharacterState {
)
}
pub fn is_using_hands(&self) -> bool {
matches!(
self,
CharacterState::Climb(_)
| CharacterState::Equipping(_)
| CharacterState::Dance
| CharacterState::Glide
| CharacterState::GlideWield
| CharacterState::Roll(_),
)
}
pub fn is_block(&self) -> bool { matches!(self, CharacterState::BasicBlock) }
pub fn is_dodge(&self) -> bool { matches!(self, CharacterState::Roll(_)) }

View File

@ -192,6 +192,16 @@ impl Animation for JumpAnimation {
next.lantern.scale = Vec3::one() * 0.65;
next.hold.scale = Vec3::one() * 0.0;
if skeleton.holding_lantern {
next.hand_r.position = Vec3::new(s_a.hand.0, s_a.hand.1 + 5.0, s_a.hand.2 + 9.0);
next.hand_r.orientation = Quaternion::rotation_x(2.25) * Quaternion::rotation_z(0.9);
next.lantern.position = Vec3::new(0.0, 0.0, -3.5);
next.lantern.orientation = next.hand_r.orientation.inverse()
* Quaternion::rotation_x(slow * 0.5)
* Quaternion::rotation_y(tilt * 4.0 * slow + tilt * 3.0);
}
next.torso.position = Vec3::new(0.0, 0.0, 0.0) * s_a.scaler;
next.torso.orientation = Quaternion::rotation_x(0.0);
next.torso.scale = Vec3::one() / 11.0 * s_a.scaler;

View File

@ -69,8 +69,19 @@ skeleton_impls!(struct CharacterSkeleton {
control,
control_l,
control_r,
:: // Begin non-bone fields
holding_lantern: bool,
});
impl CharacterSkeleton {
pub fn new(holding_lantern: bool) -> Self {
Self {
holding_lantern,
..Self::default()
}
}
}
impl Skeleton for CharacterSkeleton {
type Attr = SkeletonAttr;
type Body = Body;
@ -93,9 +104,14 @@ impl Skeleton for CharacterSkeleton {
let control_mat = chest_mat * Mat4::<f32>::from(self.control);
let control_l_mat = control_mat * Mat4::<f32>::from(self.control_l);
let control_r_mat = control_mat * Mat4::<f32>::from(self.control_r);
let hand_r_mat = control_r_mat * Mat4::<f32>::from(self.hand_r);
let hand_l_mat = Mat4::<f32>::from(self.hand_l);
let lantern_mat = Mat4::<f32>::from(self.lantern);
let lantern_mat = if self.holding_lantern {
hand_r_mat
} else {
shorts_mat
} * Mat4::<f32>::from(self.lantern);
*(<&mut [_; Self::BONE_COUNT]>::try_from(&mut buf[0..Self::BONE_COUNT]).unwrap()) = [
make_bone(head_mat),
@ -104,7 +120,7 @@ impl Skeleton for CharacterSkeleton {
make_bone(chest_mat * Mat4::<f32>::from(self.back)),
make_bone(shorts_mat),
make_bone(control_l_mat * hand_l_mat),
make_bone(control_r_mat * Mat4::<f32>::from(self.hand_r)),
make_bone(hand_r_mat),
make_bone(torso_mat * Mat4::<f32>::from(self.foot_l)),
make_bone(torso_mat * Mat4::<f32>::from(self.foot_r)),
make_bone(chest_mat * Mat4::<f32>::from(self.shoulder_l)),
@ -112,12 +128,11 @@ impl Skeleton for CharacterSkeleton {
make_bone(chest_mat * Mat4::<f32>::from(self.glider)),
make_bone(control_l_mat * Mat4::<f32>::from(self.main)),
make_bone(control_r_mat * Mat4::<f32>::from(self.second)),
make_bone(shorts_mat * lantern_mat),
make_bone(lantern_mat),
// FIXME: Should this be control_l_mat?
make_bone(control_mat * hand_l_mat * Mat4::<f32>::from(self.hold)),
];
// NOTE: lantern_mat.cols.w = lantern_mat * Vec4::unit_w()
Vec3::new(-0.3, 0.1, 0.8) + (lantern_mat.cols.w / 13.0).xyz()
(lantern_mat * Vec4::new(-0.0, -0.0, -1.5, 1.0)).xyz()
}
}

View File

@ -256,6 +256,20 @@ impl Animation for RunAnimation {
next.lantern.scale = Vec3::one() * 0.65;
next.hold.scale = Vec3::one() * 0.0;
if skeleton.holding_lantern {
next.hand_r.position = Vec3::new(
s_a.hand.0,
s_a.hand.1 + 5.0 - impact * 0.2,
s_a.hand.2 + 11.0 + impact * -0.1,
);
next.hand_r.orientation = Quaternion::rotation_x(2.25) * Quaternion::rotation_z(0.9);
next.lantern.position = Vec3::new(0.0, 0.0, -3.5);
next.lantern.orientation = next.hand_r.orientation.inverse()
* Quaternion::rotation_x((foothorir + 0.5) * 1.0 * speednorm)
* Quaternion::rotation_y(tilt * 4.0 * foothorir + tilt * 3.0);
}
next.torso.position = Vec3::new(0.0, 0.0, 0.0) * s_a.scaler;
next.torso.scale = Vec3::one() / 11.0 * s_a.scaler;

View File

@ -29,8 +29,16 @@ impl Animation for SitAnimation {
let stop = (anim_time * 3.0).min(PI / 2.0).sin();
let head_look = Vec2::new(
(global_time + anim_time / 18.0).floor().mul(7331.0).sin() * 0.25,
(global_time + anim_time / 18.0).floor().mul(1337.0).sin() * 0.125,
(global_time * 0.05 + anim_time / 15.0)
.floor()
.mul(7331.0)
.sin()
* 0.25,
(global_time * 0.05 + anim_time / 15.0)
.floor()
.mul(1337.0)
.sin()
* 0.125,
);
next.head.position = Vec3::new(0.0, s_a.head.0, s_a.head.1 + slow * 0.1 + stop * -0.8);
next.head.orientation = Quaternion::rotation_z(head_look.x + slow * 0.2 - slow * 0.1)
@ -79,6 +87,21 @@ impl Animation for SitAnimation {
next.torso.position = Vec3::new(0.0, -0.2, stop * -0.16) * s_a.scaler;
if skeleton.holding_lantern {
next.hand_r.position = Vec3::new(
s_a.hand.0 - head_look.x * 10.0,
s_a.hand.1 + 5.0 - head_look.y * 8.0,
s_a.hand.2 + 11.0,
);
next.hand_r.orientation = Quaternion::rotation_x(2.25)
* Quaternion::rotation_z(0.9)
* Quaternion::rotation_y(head_look.x * 3.0)
* Quaternion::rotation_x(head_look.y * 3.0);
next.lantern.position = Vec3::new(0.0, 0.0, -3.5);
next.lantern.orientation = next.hand_r.orientation.inverse();
}
next
}
}

View File

@ -158,6 +158,15 @@ impl Animation for SneakAnimation {
next.foot_r.position = Vec3::new(s_a.foot.0, 4.0 + s_a.foot.1, s_a.foot.2);
}
if skeleton.holding_lantern {
next.hand_r.position = Vec3::new(s_a.hand.0, s_a.hand.1 + 5.0, s_a.hand.2 + 9.0);
next.hand_r.orientation = Quaternion::rotation_x(2.5);
next.lantern.position = Vec3::new(0.0, 1.5, -5.5);
next.lantern.orientation = next.hand_r.orientation.inverse();
}
next
}
}

View File

@ -32,6 +32,7 @@ impl Animation for StandAnimation {
let mut next = (*skeleton).clone();
let slow = (anim_time * 1.0).sin();
let fast = (anim_time * 5.0).sin();
let impact = (avg_vel.z).max(-15.0);
let head_look = Vec2::new(
((global_time + anim_time) / 10.0).floor().mul(7331.0).sin() * 0.15,
@ -142,6 +143,22 @@ impl Animation for StandAnimation {
next.lantern.position = Vec3::new(s_a.lantern.0, s_a.lantern.1, s_a.lantern.2);
next.lantern.orientation = Quaternion::rotation_x(0.1) * Quaternion::rotation_y(0.1);
if skeleton.holding_lantern {
next.hand_r.position = Vec3::new(
s_a.hand.0 - head_look.x * 10.0,
s_a.hand.1 + 5.0 - head_look.y * 8.0 + slow * 0.15 - impact * 0.2,
s_a.hand.2 + 11.0 + slow * 0.5 + impact * -0.1,
);
next.hand_r.orientation = Quaternion::rotation_x(2.25 + slow * -0.06 + impact * -0.1)
* Quaternion::rotation_z(0.9)
* Quaternion::rotation_y(head_look.x * 3.0)
* Quaternion::rotation_x(head_look.y * 3.0);
next.lantern.position = Vec3::new(0.0, 0.0, -3.5);
next.lantern.orientation =
next.hand_r.orientation.inverse() * Quaternion::rotation_x(fast * 0.1);
}
next.torso.position = Vec3::new(0.0, 0.0, 0.0) * s_a.scaler;
next.second.scale = Vec3::one();
next.second.scale = match hands {

View File

@ -320,15 +320,17 @@ impl Animation for WieldAnimation {
};
match hands {
(None, None) | (None, Some(Hands::One)) => {
next.hand_l.position = Vec3::new(-4.5, 8.0, 5.0);
next.hand_l.orientation = Quaternion::rotation_x(1.9) * Quaternion::rotation_y(-0.5)
//next.hand_l.position = Vec3::new(-4.5, 8.0, 5.0);
//next.hand_l.orientation = Quaternion::rotation_x(1.9) *
// Quaternion::rotation_y(-0.5)
},
(_, _) => {},
};
match hands {
(None, None) | (Some(Hands::One), None) => {
next.hand_r.position = Vec3::new(4.5, 8.0, 5.0);
next.hand_r.orientation = Quaternion::rotation_x(1.9) * Quaternion::rotation_y(0.5)
//next.hand_r.position = Vec3::new(4.5, 8.0, 5.0);
//next.hand_r.orientation = Quaternion::rotation_x(1.9) *
// Quaternion::rotation_y(0.5)
},
(_, _) => {},
};
@ -337,6 +339,21 @@ impl Animation for WieldAnimation {
next.second = next.main;
}
if skeleton.holding_lantern {
next.hand_r.position = Vec3::new(
s_a.hand.0 - head_look.x * 10.0,
s_a.hand.1 + 5.0 + slow * 0.15,
s_a.hand.2 + 9.0 + head_look.y * 18.0 + slow * 0.5,
);
next.hand_r.orientation = Quaternion::rotation_x(2.25 + slow * -0.06)
* Quaternion::rotation_z(0.9)
* Quaternion::rotation_y(head_look.x * 3.0)
* Quaternion::rotation_x(head_look.y * 3.0);
next.lantern.position = Vec3::new(0.0, 0.0, -3.5);
next.lantern.orientation = next.hand_r.orientation.inverse();
}
next
}
}

View File

@ -5,12 +5,15 @@
compile_error!("Can't use both \"be-dyn-lib\" and \"use-dyn-lib\" features at once");
macro_rules! skeleton_impls {
{ struct $Skeleton:ident { $( $(+)? $bone:ident ),* $(,)? } } => {
{ struct $Skeleton:ident { $( $(+)? $bone:ident ),* $(,)? $(:: $($field:ident : $field_ty:ty),* $(,)? )? } } => {
#[derive(Clone, Default)]
pub struct $Skeleton {
$(
$bone: $crate::Bone,
)*
$($(
$field : $field_ty,
)*)?
}
impl<'a, Factor> $crate::vek::Lerp<Factor> for &'a $Skeleton
@ -25,6 +28,9 @@ macro_rules! skeleton_impls {
$(
$bone: Lerp::lerp_unclamped_precise(from.$bone, to.$bone, factor),
)*
$($(
$field : to.$field.clone(),
)*)?
}
}
@ -33,6 +39,9 @@ macro_rules! skeleton_impls {
$(
$bone: Lerp::lerp_unclamped(from.$bone, to.$bone, factor),
)*
$($(
$field : to.$field.clone(),
)*)?
}
}
}

View File

@ -28,7 +28,7 @@ use anim::{
use common::{
comp::{
inventory::slot::EquipSlot,
item::{ItemKind, ToolKind},
item::{Hands, ItemKind, ToolKind},
Body, CharacterState, Controller, Health, Inventory, Item, Last, LightAnimation,
LightEmitter, Ori, PhysicsState, PoiseState, Pos, Scale, Vel,
},
@ -584,6 +584,7 @@ impl FigureMgr {
health,
inventory,
item,
light_emitter,
),
) in (
&ecs.entities(),
@ -599,6 +600,7 @@ impl FigureMgr {
ecs.read_storage::<Health>().maybe(),
ecs.read_storage::<Inventory>().maybe(),
ecs.read_storage::<Item>().maybe(),
ecs.read_storage::<LightEmitter>().maybe(),
)
.join()
.enumerate()
@ -760,12 +762,20 @@ impl FigureMgr {
&slow_jobs,
);
let holding_lantern = inventory
.map_or(false, |i| i.equipped(EquipSlot::Lantern).is_some())
&& light_emitter.is_some()
&& !(matches!(second_tool_hand, Some(_))
&& character.map_or(false, |c| c.is_wield()))
&& !character.map_or(false, |c| c.is_using_hands())
&& physics.in_liquid().is_none();
let state = self
.states
.character_states
.entry(entity)
.or_insert_with(|| {
FigureState::new(renderer, CharacterSkeleton::default())
FigureState::new(renderer, CharacterSkeleton::new(holding_lantern))
});
// Average velocity relative to the current ground
@ -787,7 +797,7 @@ impl FigureMgr {
) {
// Standing
(true, false, false) => anim::character::StandAnimation::update_skeleton(
&CharacterSkeleton::default(),
&CharacterSkeleton::new(holding_lantern),
(active_tool_kind, second_tool_kind, hands, time, rel_avg_vel),
state.state_time,
&mut state_animation_rate,
@ -795,7 +805,7 @@ impl FigureMgr {
),
// Running
(true, true, false) => anim::character::RunAnimation::update_skeleton(
&CharacterSkeleton::default(),
&CharacterSkeleton::new(holding_lantern),
(
active_tool_kind,
second_tool_kind,
@ -814,7 +824,7 @@ impl FigureMgr {
),
// In air
(false, _, false) => anim::character::JumpAnimation::update_skeleton(
&CharacterSkeleton::default(),
&CharacterSkeleton::new(holding_lantern),
(
active_tool_kind,
second_tool_kind,
@ -831,7 +841,7 @@ impl FigureMgr {
),
// Swim
(_, _, true) => anim::character::SwimAnimation::update_skeleton(
&CharacterSkeleton::default(),
&CharacterSkeleton::new(holding_lantern),
(
active_tool_kind,
second_tool_kind,
@ -1376,7 +1386,7 @@ impl FigureMgr {
},
CharacterState::BasicBlock { .. } => {
anim::character::BlockAnimation::update_skeleton(
&CharacterSkeleton::default(),
&CharacterSkeleton::new(holding_lantern),
(active_tool_kind, second_tool_kind, time),
state.state_time,
&mut state_animation_rate,

View File

@ -560,7 +560,6 @@ impl Scene {
lights.extend(
(
&scene_data.state.ecs().read_storage::<comp::Pos>(),
scene_data.state.ecs().read_storage::<comp::Ori>().maybe(),
scene_data
.state
.ecs()
@ -572,23 +571,16 @@ impl Scene {
.read_storage::<comp::LightAnimation>(),
)
.join()
.filter(|(pos, _, _, light_anim)| {
.filter(|(pos, _, light_anim)| {
light_anim.col != Rgb::zero()
&& light_anim.strength > 0.0
&& (pos.0.distance_squared(player_pos) as f32)
< loaded_distance.powi(2) + LIGHT_DIST_RADIUS
})
.map(|(pos, ori, interpolated, light_anim)| {
.map(|(pos, interpolated, light_anim)| {
// Use interpolated values if they are available
let (pos, rot) = interpolated
.map_or((pos.0, ori.copied().unwrap_or_default()), |i| {
(i.pos, i.ori)
});
Light::new(
pos + (rot.to_quat() * light_anim.offset),
light_anim.col,
light_anim.strength,
)
let pos = interpolated.map_or(pos.0, |i| i.pos);
Light::new(pos + light_anim.offset, light_anim.col, light_anim.strength)
})
.chain(
self.event_lights