154 lines
4.8 KiB
TypeScript
154 lines
4.8 KiB
TypeScript
|
const { ccclass, property, requireComponent, menu } = cc._decorator;
|
||
|
|
||
|
@ccclass("State_AnimationRandomPlay")
|
||
|
export class State_AnimationRandomPlay {
|
||
|
@property({ displayName: "最少時間", type: cc.Float })
|
||
|
public mintime: number = 0;
|
||
|
@property({ displayName: "最多時間", type: cc.Float })
|
||
|
public maxtime: number = 0;
|
||
|
@property({ displayName: "權重", type: cc.Integer })
|
||
|
public weight: number = 0;
|
||
|
@property({ displayName: "動畫", type: cc.AnimationClip })
|
||
|
public clip: cc.AnimationClip = null;
|
||
|
}
|
||
|
|
||
|
@ccclass
|
||
|
@menu("Plug-in/Animation/AnimationRandomPlay")
|
||
|
@requireComponent(cc.Animation)
|
||
|
/** 可以根據權重決定多久後隨機播放甚麼動畫 */
|
||
|
export class AnimationRandomPlay extends cc.Component {
|
||
|
//#region public 外調參數
|
||
|
|
||
|
@property({ type: State_AnimationRandomPlay })
|
||
|
public states: State_AnimationRandomPlay[] = [];
|
||
|
|
||
|
//#endregion
|
||
|
|
||
|
//#region public 屬性
|
||
|
|
||
|
public nowPlayName: string = "";
|
||
|
public nextPlayName: string = "";
|
||
|
public nextPlayTime: number = null;
|
||
|
|
||
|
//#endregion
|
||
|
|
||
|
//#region private 屬性
|
||
|
|
||
|
private _animation: cc.Animation = null;
|
||
|
private _weightAll: number[] = [];
|
||
|
private _weightAllNum: number = 0;
|
||
|
|
||
|
//#endregion
|
||
|
|
||
|
//#region get set
|
||
|
|
||
|
get animation(): cc.Animation {
|
||
|
if (this._animation == null) {
|
||
|
this._animation = this.node.getComponent(cc.Animation);
|
||
|
}
|
||
|
return this._animation;
|
||
|
}
|
||
|
|
||
|
//#endregion
|
||
|
|
||
|
//#region Lifecycle
|
||
|
|
||
|
onLoad(): void {
|
||
|
let self: this = this;
|
||
|
let weight: number = 0;
|
||
|
for (let i: number = 0; i < this.states.length; i++) {
|
||
|
weight += this.states[i].weight;
|
||
|
this._weightAll.push(weight);
|
||
|
this._weightAllNum += this.states[i].weight;
|
||
|
}
|
||
|
|
||
|
// 一般動畫
|
||
|
this.animation.on("finished", () => {
|
||
|
self.GetNextAnim();
|
||
|
}, this);
|
||
|
|
||
|
// 不一般動畫 (X
|
||
|
// Loop動畫
|
||
|
this.animation.on("lastframe", () => {
|
||
|
self.animation.setCurrentTime(0);
|
||
|
self.animation.stop();
|
||
|
self.GetNextAnim();
|
||
|
}, this);
|
||
|
}
|
||
|
|
||
|
onEnable(): void {
|
||
|
this.GetNextAnim();
|
||
|
}
|
||
|
|
||
|
onDisable(): void {
|
||
|
this.nextPlayName = "";
|
||
|
this.nextPlayTime = null;
|
||
|
this.animation.setCurrentTime(0);
|
||
|
this.animation.stop();
|
||
|
}
|
||
|
|
||
|
onDestroy(): void {
|
||
|
this.animation.targetOff(this);
|
||
|
// let self: this = this;
|
||
|
// this.animation.off("finished", () => {
|
||
|
// self.GetNextAnim();
|
||
|
// }, this);
|
||
|
// this.animation.off("lastframe", () => {
|
||
|
// self.animation.setCurrentTime(0);
|
||
|
// self.animation.stop();
|
||
|
// self.GetNextAnim();
|
||
|
// }, this);
|
||
|
}
|
||
|
|
||
|
update(dt: number): void {
|
||
|
let time: number = Date.now();
|
||
|
if (this.nextPlayTime && time >= this.nextPlayTime) {
|
||
|
this.nowPlayName = this.nextPlayName;
|
||
|
if (this.animation.getAnimationState(this.nextPlayName)) {
|
||
|
this.animation.play(this.nextPlayName);
|
||
|
} else {
|
||
|
console.error(`this node(${this.node.name}) not has animation(${this.nextPlayName})`);
|
||
|
this.animation.addClip(this.GetClip_From_states(this.nextPlayName));
|
||
|
if (this.animation.getAnimationState(this.nextPlayName)) {
|
||
|
console.warn(`this node(${this.node.name}) add animation(${this.nextPlayName})`);
|
||
|
this.animation.play(this.nextPlayName);
|
||
|
}
|
||
|
}
|
||
|
this.nextPlayName = "";
|
||
|
this.nextPlayTime = null;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//#endregion
|
||
|
|
||
|
//#region Custom Function
|
||
|
|
||
|
/** 取得下一隻動畫的時間&名稱 */
|
||
|
GetNextAnim(): void {
|
||
|
let random: number = Math.floor(Math.random() * this._weightAllNum) + 1;
|
||
|
for (let i: number = 0; i < this._weightAll.length; i++) {
|
||
|
if (random <= this._weightAll[i]) {
|
||
|
let time: number = Math.floor(Math.random() * (this.states[i].maxtime - this.states[i].mintime + 1)) + this.states[i].mintime;
|
||
|
this.nextPlayTime = Date.now() + (time * 1000);
|
||
|
this.nextPlayName = this.states[i].clip.name;
|
||
|
// if (CC_DEBUG) {
|
||
|
// let date: Date = new Date(this.nextPlayTime);
|
||
|
// console.log(`nextWaitTime: ${time}, nextPlayTime: ${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}, nextPlayName: ${this.nextPlayName}`);
|
||
|
// }
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/** 取得下一隻動畫的時間&名稱 */
|
||
|
GetClip_From_states(name: string): cc.AnimationClip {
|
||
|
for (let i: number = 0; i < this.states.length; i++) {
|
||
|
if (this.states[i].clip.name === name) {
|
||
|
return this.states[i].clip;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//#endregion
|
||
|
}
|