177 lines
5.1 KiB
TypeScript
177 lines
5.1 KiB
TypeScript
/**
|
||
* @author ErSan
|
||
* @email mlt131220@163.com
|
||
* @date 2024/8/29 22:10
|
||
* @description 漫游的人物动画状态机
|
||
*/
|
||
import * as THREE from "three";
|
||
|
||
export class RoamingStatus{
|
||
// 键盘按下状态
|
||
keyDownStatus = {
|
||
w:false,
|
||
s:false,
|
||
a:false,
|
||
d:false,
|
||
shift:false,
|
||
space:false
|
||
}
|
||
|
||
fadeTime = 0.2;
|
||
|
||
person: THREE.Group; // 人物
|
||
mixer: THREE.AnimationMixer; // 动画混合器
|
||
private clipAction: { [s: string]: THREE.AnimationAction } = {}; // 动画 action
|
||
|
||
constructor(person:THREE.Group,clips:THREE.AnimationClip[]) {
|
||
this.person = person;
|
||
this.mixer = new THREE.AnimationMixer(this.person);
|
||
clips.forEach(clip => {
|
||
this.clipAction[clip.name] = (this.mixer as THREE.AnimationMixer).clipAction(clip);
|
||
})
|
||
|
||
this.mixer.addEventListener('loop', (e) => {
|
||
switch (e.action.getClip().name){
|
||
case "Enter":
|
||
this.fadeIn("Idle");
|
||
setTimeout(() => {
|
||
this.clipAction.Enter.stop();
|
||
},200)
|
||
break;
|
||
case "Jumping":
|
||
this.setStatus("space",false);
|
||
break;
|
||
}
|
||
});
|
||
}
|
||
|
||
init(){
|
||
this.clipAction.Idle.play();
|
||
}
|
||
|
||
// 是否正在向前走
|
||
get isWalkingForward(){
|
||
return this.keyDownStatus.w || this.keyDownStatus.a || this.keyDownStatus.d;
|
||
}
|
||
|
||
setStatus(key:string,value: boolean){
|
||
this.keyDownStatus[key] = value;
|
||
|
||
switch (key){
|
||
case "w":
|
||
case "a":
|
||
case "d":
|
||
// 前进动画处理
|
||
if(!this.keyDownStatus.w && !this.keyDownStatus.a && !this.keyDownStatus.d){
|
||
this.fadeOut("Walking");
|
||
|
||
if(this.clipAction.Running.isRunning()){
|
||
this.keyDownStatus.shift = false;
|
||
this.fadeOut("Running")
|
||
}
|
||
}else{
|
||
if(!this.clipAction.Walking.isRunning()){
|
||
this.fadeIn("Walking");
|
||
}
|
||
}
|
||
break;
|
||
case "s":
|
||
// 后退处理
|
||
if(value){
|
||
this.fadeIn("WalkingBackward");
|
||
}else{
|
||
this.fadeOut("WalkingBackward")
|
||
}
|
||
break;
|
||
case "space":
|
||
// 跳跃处理
|
||
if(value){
|
||
this.fadeIn("Jumping");
|
||
|
||
if(this.clipAction.Walking.isRunning()){
|
||
this.fadeOut("Walking")
|
||
}
|
||
if(this.clipAction.Running.isRunning()){
|
||
this.fadeOut("Running")
|
||
}
|
||
}else{
|
||
if(this.keyDownStatus.shift){
|
||
if(!this.clipAction.Running.isRunning()){
|
||
this.fadeIn("Running")
|
||
}
|
||
}else if(this.isWalkingForward){
|
||
if(!this.clipAction.Walking.isRunning()){
|
||
this.fadeIn("Walking")
|
||
}
|
||
}
|
||
|
||
this.fadeOut("Jumping")
|
||
}
|
||
break;
|
||
case "shift":
|
||
if(value){
|
||
this.fadeIn("Running");
|
||
|
||
this.fadeOut("Walking")
|
||
}else{
|
||
if(this.isWalkingForward){
|
||
if(!this.clipAction.Walking.isRunning()){
|
||
this.fadeIn("Walking");
|
||
this.fadeOut("Running");
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
|
||
if(!Object.values(this.keyDownStatus).includes(true)){
|
||
if(!this.clipAction.Idle.isRunning()){
|
||
this.fadeIn("Idle");
|
||
}
|
||
}else{
|
||
if(this.clipAction.Idle.isRunning()){
|
||
this.fadeOut("Idle");
|
||
}
|
||
}
|
||
}
|
||
|
||
fadeIn(name: string) {
|
||
// if(!this.clipAction[name].isScheduled()){
|
||
// this.clipAction[name].reset();
|
||
// this.clipAction[name].play();
|
||
// }
|
||
//
|
||
// this.clipAction[name].fadeIn(this.fadeTime);
|
||
|
||
this.clipAction[name].play();
|
||
}
|
||
|
||
fadeOut(name:string){
|
||
// this.clipAction[name].fadeOut(this.fadeTime)
|
||
// setTimeout(() => {
|
||
// this.clipAction[name].stop();
|
||
// },this.fadeTime * 100)
|
||
|
||
this.clipAction[name].stop();
|
||
}
|
||
|
||
stopAllAction(){
|
||
// 停用混合器上所有预定的动作
|
||
this.mixer.stopAllAction();
|
||
}
|
||
|
||
|
||
update(delta:number){
|
||
this.mixer.update(delta);
|
||
|
||
// THREE.AnimationMixer loop事件不一定有用,此处添加一个检测
|
||
if(!this.clipAction.Jumping.isRunning() && this.keyDownStatus.space){
|
||
//console.log("THREE.AnimationMixer loop事件未生效,手动设置")
|
||
this.keyDownStatus.space = false;
|
||
}
|
||
}
|
||
|
||
dispose(){
|
||
this.stopAllAction();
|
||
}
|
||
} |