add CompositeAnimation

This commit is contained in:
yushijinhun 2018-01-06 22:01:12 +08:00
parent 9a38f99d8f
commit 846c0b9939
No known key found for this signature in database
GPG Key ID: 5BC167F73EA558E4
4 changed files with 71 additions and 11 deletions

View File

@ -23,8 +23,7 @@ Three.js powered Minecraft skin viewer.
width: 600,
height: 600,
skinUrl: "img/skin.png",
capeUrl: "img/cape.png",
animation: skinview3d.WalkAnimation
capeUrl: "img/cape.png"
});
// change the skin and cape
@ -38,14 +37,17 @@ Three.js powered Minecraft skin viewer.
// enable the mouse control feature
let control = new skinview3d.SkinControl(skinViewer);
// pause the animation
// skinViewer.animationPaused = true;
// change the animation speed
// skinViewer.animationSpeed = 8;
// disable the 'right click to play/pause' feature
// control.enableAnimationControl = false;
skinViewer.animation = new skinview3d.CompositeAnimation();
// add an animation
let walk = skinViewer.animation.add(skinview3d.WalkAnimation);
// set its speed and some others
walk.speed = 1.5;
// walk.paused = true;
</script>
```

View File

@ -1,3 +1,60 @@
function invokeAnimation(animation, player, time) {
if (animation instanceof CompositeAnimation) {
animation.play(player, time);
} else if (animation instanceof Function) {
animation(player, time);
} else {
throw `Not an animation: ${animation}`;
}
}
class AnimationHandle {
constructor(animation) {
this.animation = animation;
this.paused = this._paused = false;
this.speed = this._speed = 1.0;
this._lastChange = null;
this._lastChangeX = null;
}
play(player, time) {
if (this._lastChange === null) {
this._lastChange = time;
this._lastChangeX = 0;
} else if (this.paused !== this._paused || this.speed !== this._speed) {
let dt = time - this._lastChange;
if (this._paused === false) {
this._lastChangeX += dt * this._speed;
}
this._paused = this.paused;
this._speed = this.speed;
this._lastChange = time;
}
if (this.paused === false) {
let dt = time - this._lastChange;
let x = this._lastChangeX + this.speed * dt;
invokeAnimation(this.animation, player, x);
}
}
reset(){
this._lastChange = null;
}
}
class CompositeAnimation {
constructor() {
this.handles = new Set();
}
add(animation) {
let handle = new AnimationHandle(animation);
handle.remove = () => this.handles.delete(handle);
this.handles.add(handle);
return handle;
}
play(player, time) {
this.handles.forEach(handle => handle.play(player, time));
}
}
let WalkAnimation = (player, time) => {
let skin = player.skin;
let angleRot = time + Math.PI / 2;
@ -11,4 +68,4 @@ let WalkAnimation = (player, time) => {
skin.rightArm.rotation.x = Math.cos(angleRot);
};
export { WalkAnimation };
export { CompositeAnimation, WalkAnimation, invokeAnimation };

View File

@ -25,4 +25,4 @@
export { SkinObject, CapeObject, PlayerObject } from "./model";
export { SkinViewer, SkinControl } from "./viewer";
export { WalkAnimation } from "./animation";
export { CompositeAnimation, WalkAnimation } from "./animation";

View File

@ -1,6 +1,7 @@
import THREE from "three";
import { PlayerObject } from "./model";
import { OrbitControls } from "./orbit_controls";
import { invokeAnimation } from "./animation";
function copyImage(context, sX, sY, w, h, dX, dY, flipHorizontal) {
let imgData = context.getImageData(sX, sY, w, h);
@ -160,7 +161,7 @@ class SkinViewer {
if (!this.animationPaused) {
this.animationTime++;
if (this.animation) {
this.animation(this.playerObject, this.animationTime / 100 * this.animationSpeed);
invokeAnimation(this.animation, this.playerObject, this.animationTime / 100.0 * this.animationSpeed);
}
}
this.renderer.render(this.scene, this.camera);