<div id="world"></div>
<div id="instructions">The longer you keep clicking, the harder he sneezes<br/><span class="lightInstructions">- Press and drag to turn around -</span></div>
<div id="credits">
<p>Prints on <a class="society6" href="https://society6.com/yakudoo/" target="blank">society6</a> | <a href="https://codepen.io/Yakudoo/" target="blank">my other codepens</a> | <a href="https://www.epic.net" target="blank">epic.net</a></p>
</div>
<div id="power">00</div>
@import url(https://fonts.googleapis.com/css?family=Open+Sans:800);
#world {
background: #652e37;
position:absolute;
width:100%;
height:100%;
overflow:hidden;
}
#instructions{
position:absolute;
width:100%;
top:50%;
margin: auto;
margin-top:120px;
font-family:'Open Sans', sans-serif;
color:#fdde8c;
font-size:.8em;
text-transform: uppercase;
text-align : center;
line-height : 1.5;
user-select: none;
}
.lightInstructions {
color:#f89a78;
font-size:.9em;
}
#credits{
position:absolute;
width:100%;
margin: auto;
bottom:0;
margin-bottom:20px;
font-family:'Open Sans', sans-serif;
color:#f7575f;
font-size:0.6em;
text-transform: uppercase;
text-align : center;
}
#credits a {
color:#f89a78;
}
#power {
position:absolute;
width:100%;
top:50%;
margin: auto;
margin-top:-220px;
font-family:'Open Sans', sans-serif;
color:#481f26;
font-size: 4em;
text-transform: uppercase;
text-align : center;
line-height : 1.5;
user-select: none;
}
//THREEJS RELATED VARIABLES
var scene,
camera,
controls,
fieldOfView,
aspectRatio,
nearPlane,
farPlane,
shadowLight,
backLight,
light,
renderer,
container;
//SCENE
var env, floor, dragon, pepperBottle,
sneezingRate = 0,
fireRate = 0,
maxSneezingRate = 8,
sneezeDelay = 500,
awaitingSmokeParticles = [],
timeSmoke = 0,
timeFire = 0,
globalSpeedRate = 1,
sneezeTimeout,
powerField;
//SCREEN VARIABLES
var HEIGHT,
WIDTH,
windowHalfX,
windowHalfY,
mousePos = {
x: 0,
y: 0
};
//INIT THREE JS, SCREEN AND MOUSE EVENTS
function init() {
powerField = document.getElementById('power');
scene = new THREE.Scene();
scene.fog = new THREE.Fog(0x652e37, 350, 500);
HEIGHT = window.innerHeight;
WIDTH = window.innerWidth;
aspectRatio = WIDTH / HEIGHT;
fieldOfView = 60;
nearPlane = 1;
farPlane = 2000;
camera = new THREE.PerspectiveCamera(
fieldOfView,
aspectRatio,
nearPlane,
farPlane);
camera.position.x = -300;
camera.position.z = 300;
camera.position.y = 100;
camera.lookAt(new THREE.Vector3(0, 0, 0));
renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true
});
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize(WIDTH, HEIGHT);
renderer.shadowMapEnabled = true;
container = document.getElementById('world');
container.appendChild(renderer.domElement);
windowHalfX = WIDTH / 2;
windowHalfY = HEIGHT / 2;
window.addEventListener('resize', onWindowResize, false);
document.addEventListener('mouseup', handleMouseUp, false);
document.addEventListener('touchend', handleTouchEnd, false);
//*
controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.minPolarAngle = -Math.PI / 2;
controls.maxPolarAngle = Math.PI / 2;
controls.noZoom = true;
controls.noPan = true;
//*/
}
function onWindowResize() {
HEIGHT = window.innerHeight;
WIDTH = window.innerWidth;
windowHalfX = WIDTH / 2;
windowHalfY = HEIGHT / 2;
renderer.setSize(WIDTH, HEIGHT);
camera.aspect = WIDTH / HEIGHT;
camera.updateProjectionMatrix();
}
function handleMouseUp(event) {
if (sneezeTimeout) clearTimeout(sneezeTimeout);
sneezingRate += (maxSneezingRate - sneezingRate) / 10;
powerField.innerHTML = parseInt(sneezingRate*100/maxSneezingRate);
dragon.prepareToSneeze(sneezingRate);
sneezeTimeout = setTimeout(sneeze, sneezeDelay*globalSpeedRate);
dragon.isSneezing = true;
}
function sneeze() {
dragon.sneeze(sneezingRate);
sneezingRate = 0;
powerField.innerHTML = "00";
}
function handleTouchEnd(event) {
if (sneezeTimeout) clearTimeout(sneezeTimeout);
sneezingRate += (maxSneezingRate - sneezingRate) / 10;
powerField.innerHTML = parseInt(sneezingRate*100/maxSneezingRate);
dragon.prepareToSneeze(sneezingRate);
sneezeTimeout = setTimeout(sneeze, sneezeDelay*globalSpeedRate);
dragon.isSneezing = true;
}
function createLights() {
light = new THREE.HemisphereLight(0xffffff, 0xb3858c, .8);
shadowLight = new THREE.DirectionalLight(0xffffff, .8);
shadowLight.position.set(-100, 100, 50);
shadowLight.castShadow = true;
shadowLight.shadowDarkness = .15;
backLight = new THREE.DirectionalLight(0xffffff, .4);
backLight.position.set(200, 100, 100);
backLight.shadowDarkness = .1;
backLight.castShadow = true;
scene.add(backLight);
scene.add(light);
scene.add(shadowLight);
}
Dragon = function() {
this.tailAmplitude = 3;
this.tailAngle = 0;
this.tailSpeed = .07;
this.wingAmplitude = Math.PI / 8;
this.wingAngle = 0;
this.wingSpeed = 0.1
this.isSneezing = false;
this.threegroup = new THREE.Group(); // this is a sort of container that will hold all the meshes and will be added to the scene;
// Materials
var greenMat = new THREE.MeshLambertMaterial({
color: 0x5da683,
shading: THREE.FlatShading
});
var lightGreenMat = new THREE.MeshLambertMaterial({
color: 0x95c088,
shading: THREE.FlatShading
});
var yellowMat = new THREE.MeshLambertMaterial({
color: 0xfdde8c,
shading: THREE.FlatShading
});
var redMat = new THREE.MeshLambertMaterial({
color: 0xcb3e4c,
shading: THREE.FlatShading
});
var whiteMat = new THREE.MeshLambertMaterial({
color: 0xfaf3d7,
shading: THREE.FlatShading
});
var brownMat = new THREE.MeshLambertMaterial({
color: 0x874a5c,
shading: THREE.FlatShading
});
var blackMat = new THREE.MeshLambertMaterial({
color: 0x403133,
shading: THREE.FlatShading
});
var pinkMat = new THREE.MeshLambertMaterial({
color: 0xd0838e,
shading: THREE.FlatShading
});
// body
this.body = new THREE.Group();
this.belly = makeCube(greenMat, 30, 30, 40, 0, 0, 0, 0, 0, Math.PI / 4);
// Wings
this.wingL = makeCube(yellowMat, 5, 30, 20, 15, 15, 0, -Math.PI / 4, 0, -Math.PI / 4);
this.wingL.geometry.applyMatrix(new THREE.Matrix4().makeTranslation(0, 15, 10));
this.wingR = this.wingL.clone();
this.wingR.position.x = -this.wingL.position.x;
this.wingR.rotation.z = -this.wingL.rotation.z;
// pike body
var pikeBodyGeom = new THREE.CylinderGeometry(0, 10, 10, 4, 1);
this.pikeBody1 = new THREE.Mesh(pikeBodyGeom, greenMat);
this.pikeBody1.scale.set(.2, 1, 1);
this.pikeBody1.position.z = 10;
this.pikeBody1.position.y = 26;
this.pikeBody2 = this.pikeBody1.clone();
this.pikeBody2.position.z = 0
this.pikeBody3 = this.pikeBody1.clone();
this.pikeBody3.position.z = -10;
// tail
this.tail = new THREE.Group();
this.tail.position.z = -20;
this.tail.position.y = 10;
var tailMat = new THREE.LineBasicMaterial({
color: 0x5da683,
linewidth: 5
});
var tailGeom = new THREE.Geometry();
tailGeom.vertices.push(
new THREE.Vector3(0, 0, 0),
new THREE.Vector3(0, 5, -10),
new THREE.Vector3(0, -5, -20),
new THREE.Vector3(0, 0, -30)
);
this.tailLine = new THREE.Line(tailGeom, tailMat);
// pike
var pikeGeom = new THREE.CylinderGeometry(0, 10, 10, 4, 1);
pikeGeom.applyMatrix(new THREE.Matrix4().makeRotationX(-Math.PI / 2));
this.tailPike = new THREE.Mesh(pikeGeom, yellowMat);
this.tailPike.scale.set(.2, 1, 1);
this.tailPike.position.z = -35;
this.tailPike.position.y = 0;
this.tail.add(this.tailLine);
this.tail.add(this.tailPike);
this.body.add(this.belly);
this.body.add(this.wingL);
this.body.add(this.wingR);
this.body.add(this.tail);
this.body.add(this.pikeBody1);
this.body.add(this.pikeBody2);
this.body.add(this.pikeBody3);
// head
this.head = new THREE.Group();
// head face
this.face = makeCube(greenMat, 60, 50, 80, 0, 25, 40, 0, 0, 0);
// head horn
var hornGeom = new THREE.CylinderGeometry(0, 6, 10, 4, 1);
this.hornL = new THREE.Mesh(hornGeom, yellowMat);
this.hornL.position.y = 55;
this.hornL.position.z = 10;
this.hornL.position.x = 10;
this.hornR = this.hornL.clone();
this.hornR.position.x = -10;
// head ears
this.earL = makeCube(greenMat, 5, 10, 20, 32, 42, 2, 0, 0, 0);
this.earL.geometry.applyMatrix(new THREE.Matrix4().makeTranslation(0, 5, -10));
this.earL.geometry.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI / 4));
this.earL.geometry.applyMatrix(new THREE.Matrix4().makeRotationY(-Math.PI / 4));
this.earR = makeCube(greenMat, 5, 10, 20, -32, 42, 2, 0, 0, 0);
this.earR.geometry.applyMatrix(new THREE.Matrix4().makeTranslation(0, 5, -10));
this.earR.geometry.applyMatrix(new THREE.Matrix4().makeRotationX(Math.PI / 4));
this.earR.geometry.applyMatrix(new THREE.Matrix4().makeRotationY(Math.PI / 4));
// head mouth
this.mouth = new THREE.Group();
this.mouth.position.z = 50;
this.mouth.position.y = 3;
this.mouth.rotation.x = 0//Math.PI / 8;
// head mouth jaw
this.jaw = makeCube(greenMat, 30, 10, 30, 0, -5, 15, 0, 0, 0);
this.mouth.add(this.jaw);
// head mouth tongue
this.tongue = makeCube(redMat, 20, 10, 20, 0, -3, 15, 0, 0, 0);
this.mouth.add(this.tongue);
// head smile
var smileGeom = new THREE.TorusGeometry( 6, 2, 2, 10, Math.PI );
this.smile = new THREE.Mesh(smileGeom, blackMat);
this.smile.position.z = 82;
this.smile.position.y = 5;
this.smile.rotation.z = -Math.PI;
// head cheek
this.cheekL = makeCube(lightGreenMat, 4, 20, 20, 30, 18, 55, 0, 0, 0);
this.cheekR = this.cheekL.clone();
this.cheekR.position.x = -this.cheekL.position.x;
//head spots
this.spot1 = makeCube(lightGreenMat, 2, 2, 2, 20, 16, 80, 0, 0, 0);
this.spot2 = this.spot1.clone();
this.spot2.position.x = 15;
this.spot2.position.y = 14;
this.spot3 = this.spot1.clone();
this.spot3.position.x = 16;
this.spot3.position.y = 20;
this.spot4 = this.spot1.clone();
this.spot4.position.x = 12;
this.spot4.position.y = 18;
this.spot5 = this.spot1.clone();
this.spot5.position.x = -15;
this.spot5.position.y = 14;
this.spot6 = this.spot1.clone();
this.spot6.position.x = -14;
this.spot6.position.y = 20;
this.spot7 = this.spot1.clone();
this.spot7.position.x = -19;
this.spot7.position.y = 17;
this.spot8 = this.spot1.clone();
this.spot8.position.x = -11;
this.spot8.position.y = 17;
// head eye
this.eyeL = makeCube(whiteMat, 10, 22, 22, 27, 34, 18, 0, 0, 0);
this.eyeR = this.eyeL.clone();
this.eyeR.position.x = -27;
// head iris
this.irisL = makeCube(brownMat, 10, 12, 12, 28, 30, 24, 0, 0, 0);
this.irisR = this.irisL.clone();
this.irisR.position.x = -this.irisL.position.x;
// head nose
this.noseL = makeCube(blackMat, 5, 5, 8, 5, 40, 77, 0, 0, 0);
this.noseR = this.noseL.clone();
this.noseR.position.x = -this.noseL.position.x;
this.head.position.z = 30;
this.head.add(this.face);
this.head.add(this.hornL);
this.head.add(this.hornR);
this.head.add(this.earL);
this.head.add(this.earR);
this.head.add(this.mouth);
this.head.add(this.eyeL);
this.head.add(this.eyeR);
this.head.add(this.irisL);
this.head.add(this.irisR);
this.head.add(this.noseL);
this.head.add(this.noseR);
this.head.add(this.cheekL);
this.head.add(this.cheekR);
this.head.add(this.smile);
/*
this.head.add(this.spot1);
this.head.add(this.spot2);
this.head.add(this.spot3);
this.head.add(this.spot4);
this.head.add(this.spot5);
this.head.add(this.spot6);
this.head.add(this.spot7);
this.head.add(this.spot8);
*/
// legs
this.legFL = makeCube(greenMat, 20, 10, 20, 20, -30, 15, 0, 0, 0);
this.legFR = this.legFL.clone();
this.legFR.position.x = -30;
this.legBL = this.legFL.clone();
this.legBL.position.z = -15;
this.legBR = this.legBL.clone();
this.legBR.position.x = -30;
this.threegroup.add(this.body);
this.threegroup.add(this.head);
this.threegroup.add(this.legFL);
this.threegroup.add(this.legFR);
this.threegroup.add(this.legBL);
this.threegroup.add(this.legBR);
//this.threegroup.add(this.pike);
this.threegroup.traverse(function(object) {
if (object instanceof THREE.Mesh) {
object.castShadow = true;
object.receiveShadow = true;
}
});
}
Dragon.prototype.update = function() {
this.tailAngle += this.tailSpeed/globalSpeedRate;
this.wingAngle += this.wingSpeed/globalSpeedRate;
for (var i = 0; i < this.tailLine.geometry.vertices.length; i++) {
var v = this.tailLine.geometry.vertices[i];
v.y = Math.sin(this.tailAngle - (Math.PI / 3) * i) * this.tailAmplitude * i * i;
v.x = Math.cos(this.tailAngle / 2 + (Math.PI / 10) * i) * this.tailAmplitude * i * i;
if (i == this.tailLine.geometry.vertices.length - 1) {
this.tailPike.position.x = v.x;
this.tailPike.position.y = v.y;
this.tailPike.rotation.x = (v.y / 30);
}
}
this.tailLine.geometry.verticesNeedUpdate = true;
this.wingL.rotation.z = -Math.PI / 4 + Math.cos(this.wingAngle) * this.wingAmplitude;
this.wingR.rotation.z = Math.PI / 4 - Math.cos(this.wingAngle) * this.wingAmplitude;
}
Dragon.prototype.prepareToSneeze = function(s) {
var _this = this;
var speed = .7*globalSpeedRate;
TweenLite.to(this.head.rotation, speed, {
x: -s * .12,
ease: Back.easeOut
});
TweenLite.to(this.head.position, speed, {
z: 30 - s * 2.2,
y: s * 2.2,
ease: Back.easeOut
});
TweenLite.to(this.mouth.rotation, speed, {
x: s * .18,
ease: Back.easeOut
});
TweenLite.to(this.smile.position, speed/2, {
z:75,
y:10,
ease: Back.easeOut
});
TweenLite.to(this.smile.scale, speed/2, {
x:0, y:0,
ease: Back.easeOut
});
TweenMax.to(this.noseL.scale, speed, {
x: 1 + s * .1,
y: 1 + s * .1,
ease: Back.easeOut
});
TweenMax.to(this.noseR.scale, speed, {
x: 1 + s * .1,
y: 1 + s * .1,
ease: Back.easeOut
});
TweenMax.to(this.eyeL.scale, speed, {
y: 1 + s * .01,
ease: Back.easeOut
});
TweenMax.to(this.eyeR.scale, speed, {
y: 1 + s * .01,
ease: Back.easeOut
});
TweenMax.to(this.irisL.scale, speed, {
y: 1 + s * .05,
z: 1 + s * .05,
ease: Back.easeOut
});
TweenMax.to(this.irisR.scale, speed, {
y: 1 + s * .05,
z: 1 + s * .05,
ease: Back.easeOut
});
TweenMax.to(this.irisL.position, speed, {
y: 30 + s * .8,
z: 24 - s * .4,
ease: Back.easeOut
});
TweenMax.to(this.irisR.position, speed, {
y: 30 + s * .8,
z: 24 - s * .4,
ease: Back.easeOut
});
TweenMax.to(this.earL.rotation, speed, {
x: -s * .1,
y: -s * .1,
ease: Back.easeOut
});
TweenMax.to(this.earR.rotation, speed, {
x: -s * .1,
y: s * .1,
ease: Back.easeOut
});
TweenMax.to(this.wingL.rotation, speed, {
z: -Math.PI / 4 - s * .1,
ease: Back.easeOut
});
TweenMax.to(this.wingR.rotation, speed, {
z: Math.PI / 4 + s * .1,
ease: Back.easeOut
});
TweenMax.to(this.body.rotation, speed, {
x: -s * .05,
ease: Back.easeOut
});
TweenMax.to(this.body.scale, speed, {
y: 1 + s * .01,
ease: Back.easeOut
});
TweenMax.to(this.body.position, speed, {
z: -s * 2,
ease: Back.easeOut
});
TweenMax.to(this.tail.rotation, speed, {
x: s * 0.1,
ease: Back.easeOut
});
}
Dragon.prototype.sneeze = function(s) {
var _this = this;
var sneezeEffect = 1 - (s / maxSneezingRate);
var speed = .1*globalSpeedRate;
timeFire = Math.round(s * 10);
TweenLite.to(this.head.rotation, speed, {
x: s * .05,
ease: Back.easeOut
});
TweenLite.to(this.head.position, speed, {
z: 30 + s * 2.4,
y: -s * .4,
ease: Back.easeOut
});
TweenLite.to(this.mouth.rotation, speed, {
x: 0,
ease: Strong.easeOut
});
TweenLite.to(this.smile.position, speed*2, {
z:82,
y:5,
ease: Strong.easeIn
});
TweenLite.to(this.smile.scale, speed*2, {
x:1,
y:1,
ease: Strong.easeIn
});
TweenMax.to(this.noseL.scale, speed, {
y: sneezeEffect,
ease: Strong.easeOut
});
TweenMax.to(this.noseR.scale, speed, {
y: sneezeEffect,
ease: Strong.easeOut
});
TweenMax.to(this.noseL.position, speed, {
y: 40, // - (sneezeEffect * 5),
ease: Strong.easeOut
});
TweenMax.to(this.noseR.position, speed, {
y: 40, // - (sneezeEffect * 5),
ease: Strong.easeOut
});
TweenMax.to(this.irisL.scale, speed, {
y: sneezeEffect/2,
z: 1,
ease: Strong.easeOut
});
TweenMax.to(this.irisR.scale, speed, {
y: sneezeEffect/2,
z: 1,
ease: Strong.easeOut
});
TweenMax.to(this.eyeL.scale, speed, {
y: sneezeEffect/2,
ease: Back.easeOut
});
TweenMax.to(this.eyeR.scale, speed, {
y: sneezeEffect/2,
ease: Back.easeOut
});
TweenMax.to(this.wingL.rotation, speed, {
z: -Math.PI / 4 + s * .15,
ease: Back.easeOut
});
TweenMax.to(this.wingR.rotation, speed, {
z: Math.PI / 4 - s * .15,
ease: Back.easeOut
});
TweenMax.to(this.body.rotation, speed, {
x: s * 0.02,
ease: Back.easeOut
});
TweenMax.to(this.body.scale, speed, {
y: 1 - s * .03,
ease: Back.easeOut
});
TweenMax.to(this.body.position, speed, {
z: s * 2,
ease: Back.easeOut
});
TweenMax.to(this.irisL.position, speed*7, {
y: 35,
ease: Back.easeOut
});
TweenMax.to(this.irisR.position, speed*7, {
y: 35,
ease: Back.easeOut
});
TweenMax.to(this.earR.rotation, speed*3, {
x: s * .20,
y: s * .20,
ease: Back.easeOut
});
TweenMax.to(this.earL.rotation, speed*3, {
x: s * .20,
y: -s * .20,
ease: Back.easeOut,
onComplete: function() {
_this.backToNormal(s);
fireRate = s;
console.log(fireRate);
}
});
TweenMax.to(this.tail.rotation, speed*3, {
x: -s * 0.1,
ease: Back.easeOut
});
}
Dragon.prototype.backToNormal = function(s) {
var _this = this;
var speed = 1*globalSpeedRate;
TweenLite.to(this.head.rotation, speed, {
x: 0,
ease: Strong.easeInOut
});
TweenLite.to(this.head.position, speed, {
z: 30,
y: 0,
ease: Back.easeOut
});
TweenMax.to(this.noseL.scale, speed, {
x: 1,
y: 1,
ease: Strong.easeInOut
});
TweenMax.to(this.noseR.scale, speed, {
x: 1,
y: 1,
ease: Strong.easeInOut
});
TweenMax.to(this.noseL.position, speed, {
y: 40,
ease: Strong.easeInOut
});
TweenMax.to(this.noseR.position, speed, {
y: 40,
ease: Strong.easeInOut
});
TweenMax.to(this.irisL.scale, speed, {
y: 1,
z: 1,
ease: Back.easeOut
});
TweenMax.to(this.irisR.scale, speed, {
y: 1,
z: 1,
ease: Back.easeOut
});
TweenMax.to(this.irisL.position, speed*.7, {
y: 30,
ease: Back.easeOut
});
TweenMax.to(this.irisR.position, speed*.7, {
y: 30,
ease: Back.easeOut
});
TweenMax.to(this.eyeL.scale, speed, {
y: 1,
ease: Strong.easeOut
});
TweenMax.to(this.eyeR.scale, speed, {
y: 1,
ease: Strong.easeOut
});
TweenMax.to(this.body.rotation, speed, {
x: 0,
ease: Back.easeOut
});
TweenMax.to(this.body.scale, speed, {
y: 1,
ease: Back.easeOut
});
TweenMax.to(this.body.position, speed, {
z: 0,
ease: Back.easeOut
});
TweenMax.to(this.wingL.rotation, speed*1.3, {
z: -Math.PI / 4,
ease: Back.easeInOut
});
TweenMax.to(this.wingR.rotation, speed*1.3, {
z: Math.PI / 4,
ease: Back.easeInOut
});
TweenMax.to(this.earL.rotation, speed*1.3, {
x: 0,
y: 0,
ease: Back.easeInOut
});
TweenMax.to(this.earR.rotation, speed*1.3, {
x: 0,
y: 0,
ease: Back.easeInOut,
onComplete: function() {
_this.isSneezing = false;
timeSmoke = Math.round(s * 5);
}
});
TweenMax.to(this.tail.rotation, speed*1.3, {
x: 0,
ease: Back.easeOut
});
}
function makeCube(mat, w, h, d, posX, posY, posZ, rotX, rotY, rotZ) {
var geom = new THREE.BoxGeometry(w, h, d);
var mesh = new THREE.Mesh(geom, mat);
mesh.position.x = posX;
mesh.position.y = posY;
mesh.position.z = posZ;
mesh.rotation.x = rotX;
mesh.rotation.y = rotY;
mesh.rotation.z = rotZ;
return mesh;
}
function createFloor() {
env = new THREE.Group();
floor = new THREE.Mesh(new THREE.PlaneBufferGeometry(2000, 2000), new THREE.MeshBasicMaterial({
color: 0X652e37
}));
floor.rotation.x = -Math.PI / 2;
floor.position.y = -36;
floor.receiveShadow = true;
env.add(floor);
scene.add(env);
}
function createDragon() {
dragon = new Dragon();
scene.add(dragon.threegroup);
}
SmokeParticle = function() {
this.color = {
r: 0,
g: 0,
b: 0
};
var particleMat = new THREE.MeshLambertMaterial({
transparent: true,
opacity: .5,
shading: THREE.FlatShading
});
this.mesh = makeCube(particleMat, 4, 4, 4, 0, 0, 0, 0, 0, 0);
awaitingSmokeParticles.push(this);
}
SmokeParticle.prototype.initialize = function() {
this.mesh.rotation.x = 0;
this.mesh.rotation.y = 0;
this.mesh.rotation.z = 0;
this.mesh.position.x = 0;
this.mesh.position.y = 0;
this.mesh.position.z = 0;
this.mesh.scale.x = 1;
this.mesh.scale.y = 1;
this.mesh.scale.z = 1;
this.mesh.material.opacity = .5;
awaitingSmokeParticles.push(this);
}
SmokeParticle.prototype.updateColor = function() {
this.mesh.material.color.setRGB(this.color.r, this.color.g, this.color.b);
}
SmokeParticle.prototype.fly = function() {
var _this = this;
var speed = 10*globalSpeedRate;
var ease = Strong.easeOut;
var initX = this.mesh.position.x;
var initY = this.mesh.position.y;
var initZ = this.mesh.position.z;
var bezier = {
type: "cubic",
values: [{
x: initX,
y: initY,
z: initZ
}, {
x: initX + 30 - Math.random() * 10,
y: initY + 20 + Math.random() * 2,
z: initZ + 20
}, {
x: initX + 10 + Math.random() * 20,
y: initY + 40 + Math.random() * 5,
z: initZ - 30
}, {
x: initX + 50 - Math.random() * 20,
y: initY + 70 + Math.random() * 10,
z: initZ + 20
}]
};
TweenMax.to(this.mesh.position, speed, {
bezier: bezier,
ease: ease
});
TweenMax.to(this.mesh.rotation, speed, {
x: Math.random() * Math.PI * 3,
y: Math.random() * Math.PI * 3,
ease: ease
});
TweenMax.to(this.mesh.scale, speed, {
x: 5 + Math.random() * 5,
y: 5 + Math.random() * 5,
z: 5 + Math.random() * 5,
ease: ease
});
//*
TweenMax.to(this.mesh.material, speed, {
opacity: 0,
ease: ease,
onComplete: function() {
_this.initialize();
}
});
//*/
}
SmokeParticle.prototype.fire = function(f) {
var _this = this;
var speed = 1*globalSpeedRate;
var ease = Strong.easeOut;
var initX = this.mesh.position.x;
var initY = this.mesh.position.y;
var initZ = this.mesh.position.z;
TweenMax.to(this.mesh.position, speed, {
x: 0,
y: initY-2*f,
z: Math.max(initZ+15*f, initZ+40),
ease: ease
});
TweenMax.to(this.mesh.rotation, speed, {
x: Math.random() * Math.PI * 3,
y: Math.random() * Math.PI * 3,
ease: ease
});
var bezierScale = [{
x:1,
y:1,
z:1
},{
x:f/maxSneezingRate+Math.random()*.3,
y:f/maxSneezingRate+Math.random()*.3,
z:f*2/maxSneezingRate+Math.random()*.3
}, {
x:f/maxSneezingRate+Math.random()*.5,
y:f/maxSneezingRate+Math.random()*.5,
z:f*2/maxSneezingRate+Math.random()*.5
},{
x:f*2/maxSneezingRate+Math.random()*.5,
y:f*2/maxSneezingRate+Math.random()*.5,
z:f*4/maxSneezingRate+Math.random()*.5
},{
x:f*2+Math.random()*5,
y:f*2+Math.random()*5,
z:f*2+Math.random()*5
}];
TweenMax.to(this.mesh.scale, speed * 2, {
bezier:bezierScale,
ease: ease,
onComplete: function() {
_this.initialize();
}
});
TweenMax.to(this.mesh.material, speed, {
opacity: 0,
ease: ease
});
//*
var bezierColor = [{
r: 255 / 255,
g: 205 / 255,
b: 74 / 255
},{
r: 255 / 255,
g: 205 / 255,
b: 74 / 255
},{
r: 255 / 255,
g: 205 / 255,
b: 74 / 255
}, {
r: 247 / 255,
g: 34 / 255,
b: 50 / 255
}, {
r: 0 / 255,
g: 0 / 255,
b: 0 / 255
}];
TweenMax.to(this.color, speed, {
bezier: bezierColor,
ease: Strong.easeOut,
onUpdate: function() {
_this.updateColor();
}
});
//*/
}
function getSmokeParticle() {
var p;
if (!awaitingSmokeParticles.length) {
p = new SmokeParticle();
}
p = awaitingSmokeParticles.pop();
return p;
}
function loop() {
render();
if (!dragon.isSneezing) {
dragon.update();
}
if (timeSmoke > 0) {
//if (timeSmoke%2==0){
var noseTarget = (Math.random() > .5) ? dragon.noseL : dragon.noseR;
var p = getSmokeParticle();
var pos = noseTarget.localToWorld(new THREE.Vector3(0, 0, 2));
p.mesh.position.x = pos.x;
p.mesh.position.y = pos.y;
p.mesh.position.z = pos.z;
p.mesh.material.color.setHex(0x555555);
p.mesh.material.opacity = .2;
scene.add(p.mesh);
p.fly();
//}
timeSmoke--;
}
if (timeFire > 0) {
var noseTarget = (Math.random() > .5) ? dragon.noseL : dragon.noseR;
var colTarget = (Math.random() > .5) ? 0xfdde8c : 0xcb3e4c;
var f = getSmokeParticle();
var posF = noseTarget.localToWorld(new THREE.Vector3(0, 0, 2));
f.mesh.position.x = posF.x;
f.mesh.position.y = posF.y;
f.mesh.position.z = posF.z;
f.color = {
r: 255 / 255,
g: 205 / 255,
b: 74 / 255
};
f.mesh.material.color.setRGB(f.color.r, f.color.g, f.color.b);
f.mesh.material.opacity = 1;
scene.add(f.mesh);
f.fire(fireRate);
timeFire--;
}
requestAnimationFrame(loop);
}
function render() {
if (controls) controls.update();
renderer.render(scene, camera);
}
init();
createLights();
createFloor();
createDragon();
loop();
//dragon.threegroup.rotation.y = Math.PI/4;
function clamp(v, min, max) {
return Math.min(Math.max(v, min), max);
}
function rule3(v, vmin, vmax, tmin, tmax) {
var nv = Math.max(Math.min(v, vmax), vmin);
var dv = vmax - vmin;
var pc = (nv - vmin) / dv;
var dt = tmax - tmin;
var tv = tmin + (pc * dt);
return tv;
}
This Pen doesn't use any external CSS resources.