mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Animation States
Former-commit-id: 769f09dc44143b5e54623ea819db2d6149429184
This commit is contained in:
parent
0a2b0e98e8
commit
ddb32eec30
@ -160,6 +160,9 @@ impl Client {
|
||||
self.state.write_component(self.player, comp::phys::Vel(Vec3::from(input.move_dir * PLAYER_VELOCITY) * 0.1));
|
||||
if input.move_dir.magnitude() > 0.01 {
|
||||
self.state.write_component(self.player, comp::phys::Dir(input.move_dir.normalized().into()));
|
||||
self.state.write_component(self.player, comp::Animation::Run);
|
||||
} else {
|
||||
self.state.write_component(self.player, comp::Animation::Idle);
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,6 +181,11 @@ impl Client {
|
||||
_ => {},
|
||||
}
|
||||
|
||||
// Update the server about the player's currently playing animation
|
||||
if let Some(animation) = self.state.read_storage().get(self.player).cloned() {
|
||||
self.postbox.send_message(ClientMsg::PlayerAnimation(animation));
|
||||
}
|
||||
|
||||
// Request chunks from the server
|
||||
if let Some(pos) = self.state.read_storage::<comp::phys::Pos>().get(self.player) {
|
||||
let chunk_pos = self.state.terrain().pos_key(pos.0.map(|e| e as i32));
|
||||
@ -234,6 +242,12 @@ impl Client {
|
||||
},
|
||||
None => {},
|
||||
},
|
||||
ServerMsg::EntityAnimation { entity, animation } => match self.state.ecs().entity_from_uid(entity) {
|
||||
Some(entity) => {
|
||||
self.state.write_component(entity, animation);
|
||||
},
|
||||
None => {},
|
||||
},
|
||||
ServerMsg::TerrainChunkUpdate { key, chunk } => {
|
||||
self.state.insert_chunk(key, *chunk);
|
||||
self.pending_chunks.remove(&key);
|
||||
|
@ -18,6 +18,12 @@ pub enum Gender {
|
||||
Unspecified,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum Animation {
|
||||
Idle,
|
||||
Run,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct Character {
|
||||
race: Race,
|
||||
@ -27,6 +33,7 @@ pub struct Character {
|
||||
belt: (),
|
||||
arms: (),
|
||||
feet: (),
|
||||
|
||||
}
|
||||
|
||||
impl Character {
|
||||
@ -47,3 +54,7 @@ impl Character {
|
||||
impl Component for Character {
|
||||
type Storage = FlaggedStorage<Self, VecStorage<Self>>;
|
||||
}
|
||||
|
||||
impl Component for Animation {
|
||||
type Storage = FlaggedStorage<Self, VecStorage<Self>>;
|
||||
}
|
||||
|
@ -5,3 +5,4 @@ pub mod phys;
|
||||
// Reexports
|
||||
pub use character::Character;
|
||||
pub use player::Player;
|
||||
pub use character::Animation;
|
||||
|
@ -6,10 +6,12 @@ pub enum ClientMsg {
|
||||
Connect {
|
||||
player: comp::Player,
|
||||
character: Option<comp::Character>,
|
||||
|
||||
},
|
||||
Ping,
|
||||
Pong,
|
||||
Chat(String),
|
||||
PlayerAnimation(comp::character::Animation),
|
||||
PlayerPhysics {
|
||||
pos: comp::phys::Pos,
|
||||
vel: comp::phys::Vel,
|
||||
|
@ -23,6 +23,10 @@ pub enum ServerMsg {
|
||||
vel: comp::phys::Vel,
|
||||
dir: comp::phys::Dir,
|
||||
},
|
||||
EntityAnimation {
|
||||
entity: u64,
|
||||
animation: comp::Animation,
|
||||
},
|
||||
TerrainChunkUpdate {
|
||||
key: Vec3<i32>,
|
||||
chunk: Box<TerrainChunk>,
|
||||
|
@ -100,6 +100,7 @@ impl State {
|
||||
ecs.internal_mut().register::<comp::phys::Pos>();
|
||||
ecs.internal_mut().register::<comp::phys::Vel>();
|
||||
ecs.internal_mut().register::<comp::phys::Dir>();
|
||||
ecs.internal_mut().register::<comp::Animation>();
|
||||
|
||||
// Register resources used by the ECS
|
||||
ecs.internal_mut().add_resource(TimeOfDay(0.0));
|
||||
|
@ -234,6 +234,7 @@ impl Server {
|
||||
state.write_component(entity, comp::phys::Dir(Vec3::unit_y()));
|
||||
if let Some(character) = character {
|
||||
state.write_component(entity, character);
|
||||
|
||||
}
|
||||
state.write_component(entity, comp::phys::ForceUpdate);
|
||||
|
||||
@ -257,6 +258,7 @@ impl Server {
|
||||
ClientMsg::Ping => client.postbox.send_message(ServerMsg::Pong),
|
||||
ClientMsg::Pong => {},
|
||||
ClientMsg::Chat(msg) => new_chat_msgs.push((entity, msg)),
|
||||
ClientMsg::PlayerAnimation(animation) => state.write_component(entity, animation),
|
||||
ClientMsg::PlayerPhysics { pos, vel, dir } => {
|
||||
state.write_component(entity, pos);
|
||||
state.write_component(entity, vel);
|
||||
@ -347,11 +349,25 @@ impl Server {
|
||||
};
|
||||
|
||||
match force_update {
|
||||
|
||||
|
||||
Some(_) => self.clients.notify_connected(msg),
|
||||
None => self.clients.notify_connected_except(entity, msg),
|
||||
}
|
||||
}
|
||||
|
||||
// Sync animation states
|
||||
for (entity, &uid, &animation) in (
|
||||
&self.state.ecs().internal().entities(),
|
||||
&self.state.ecs().internal().read_storage::<Uid>(),
|
||||
&self.state.ecs().internal().read_storage::<comp::Animation>(),
|
||||
).join() {
|
||||
self.clients.notify_connected_except(entity, ServerMsg::EntityAnimation {
|
||||
entity: uid.into(),
|
||||
animation,
|
||||
});
|
||||
}
|
||||
|
||||
// Remove all force flags
|
||||
self.state.ecs_mut().internal_mut().write_storage::<comp::phys::ForceUpdate>().clear();
|
||||
}
|
||||
|
48
voxygen/src/anim/character/idle.rs
Normal file
48
voxygen/src/anim/character/idle.rs
Normal file
@ -0,0 +1,48 @@
|
||||
// Standard
|
||||
use std::f32::consts::PI;
|
||||
|
||||
// Library
|
||||
use vek::*;
|
||||
|
||||
// Local
|
||||
use super::{
|
||||
CharacterSkeleton,
|
||||
super::Animation,
|
||||
};
|
||||
|
||||
pub struct IdleAnimation;
|
||||
|
||||
//TODO: Make it actually good, possibly add the head rotating slightly, add breathing, etc.
|
||||
impl Animation for IdleAnimation {
|
||||
type Skeleton = CharacterSkeleton;
|
||||
type Dependency = f64;
|
||||
|
||||
fn update_skeleton(
|
||||
skeleton: &mut Self::Skeleton,
|
||||
time: f64,
|
||||
) {
|
||||
skeleton.head.offset = Vec3::unit_z() * 13.0 / 11.0;
|
||||
skeleton.head.ori = Quaternion::rotation_z(0.0);
|
||||
|
||||
skeleton.chest.offset = Vec3::unit_z() * 9.0 / 11.0;
|
||||
skeleton.chest.ori = Quaternion::rotation_z(0.0);
|
||||
|
||||
skeleton.belt.offset = Vec3::unit_z() * 7.0 / 11.0;
|
||||
skeleton.belt.ori = Quaternion::rotation_z(0.0);
|
||||
|
||||
skeleton.shorts.offset = Vec3::unit_z() * 4.0 / 11.0;
|
||||
skeleton.shorts.ori = Quaternion::rotation_z(0.0);
|
||||
|
||||
skeleton.l_hand.offset = Vec3::new(-8.0, 0.0, 9.0) / 11.0;
|
||||
skeleton.r_hand.offset = Vec3::new(8.0, 0.0, 9.0 ) / 11.0;
|
||||
|
||||
skeleton.l_foot.offset = Vec3::new(-3.5, 0.0, 3.0) / 11.0;
|
||||
skeleton.l_foot.ori = Quaternion::rotation_x(0.0);
|
||||
skeleton.r_foot.offset = Vec3::new(3.5, 0.0, 3.0) / 11.0;
|
||||
skeleton.r_foot.ori = Quaternion::rotation_x(0.0);
|
||||
|
||||
skeleton.back.offset = Vec3::new(-9.0, 5.0, 18.0);
|
||||
skeleton.back.ori = Quaternion::rotation_y(2.5);
|
||||
skeleton.back.scale = Vec3::one();
|
||||
}
|
||||
}
|
@ -1,7 +1,9 @@
|
||||
pub mod run;
|
||||
pub mod idle;
|
||||
|
||||
// Reexports
|
||||
pub use self::run::RunAnimation;
|
||||
pub use self::idle::IdleAnimation;
|
||||
|
||||
// Crate
|
||||
use crate::render::FigureBoneData;
|
||||
|
@ -22,10 +22,10 @@ pub struct ClientInit {
|
||||
impl ClientInit {
|
||||
pub fn new(
|
||||
connection_args: (String, u16, bool),
|
||||
client_args: (comp::Player, Option<comp::Character>, u64),
|
||||
client_args: (comp::Player, Option<comp::Character>, Option<comp::Animation>, u64),
|
||||
) -> Self {
|
||||
let (server_address, default_port, prefer_ipv6) = connection_args;
|
||||
let (player, character, view_distance) = client_args;
|
||||
let (player, character, animation, view_distance) = client_args;
|
||||
|
||||
let (tx, rx) = channel();
|
||||
|
||||
|
@ -95,6 +95,7 @@ impl PlayState for MainMenuState {
|
||||
(
|
||||
comp::Player::new(username.clone()),
|
||||
Some(comp::Character::test()),
|
||||
Some(comp::Animation::Idle),
|
||||
300,
|
||||
),
|
||||
)));
|
||||
|
@ -8,6 +8,7 @@ use client::Client;
|
||||
use common::{
|
||||
comp,
|
||||
figure::Segment,
|
||||
msg
|
||||
};
|
||||
use crate::{
|
||||
Error,
|
||||
@ -27,6 +28,7 @@ use crate::{
|
||||
character::{
|
||||
CharacterSkeleton,
|
||||
RunAnimation,
|
||||
IdleAnimation,
|
||||
},
|
||||
},
|
||||
mesh::Meshable,
|
||||
@ -81,17 +83,21 @@ impl Figures {
|
||||
pub fn maintain(&mut self, renderer: &mut Renderer, client: &mut Client) {
|
||||
let time = client.state().get_time();
|
||||
let ecs = client.state_mut().ecs_mut().internal_mut();
|
||||
for (entity, pos, dir, character) in (
|
||||
for (entity, pos, dir, character, animation) in (
|
||||
&ecs.entities(),
|
||||
&ecs.read_storage::<comp::phys::Pos>(),
|
||||
&ecs.read_storage::<comp::phys::Dir>(),
|
||||
&ecs.read_storage::<comp::Character>(),
|
||||
&ecs.read_storage::<comp::Animation>(),
|
||||
).join() {
|
||||
let state = self.states
|
||||
.entry(entity)
|
||||
.or_insert_with(|| FigureState::new(renderer, CharacterSkeleton::new()));
|
||||
|
||||
RunAnimation::update_skeleton(&mut state.skeleton, time);
|
||||
match animation {
|
||||
comp::character::Animation::Idle => IdleAnimation::update_skeleton(&mut state.skeleton, time),
|
||||
comp::character::Animation::Run => RunAnimation::update_skeleton(&mut state.skeleton, time),
|
||||
}
|
||||
|
||||
state.update(renderer, pos.0, dir.0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user