content/hifi-content/thoys/dev/2017/whackAMole/mole.js
2022-02-14 02:04:11 +01:00

222 lines
7.8 KiB
JavaScript

//
// whackAMole/mole.js
//
// Created by Thijs Wenker on 5/8/17.
// Copyright 2017 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
/* global module */
// @module mole
var constants = Script.require('./constants.js');
var helpers = Script.require('./helpers.js');
var MOLE_STATE = constants.MOLE_STATE;
// Frame numbers for popping animation
var POPUP_FRAME_START = 1;
var POPUP_FRAME_END = 28;
var DROPDOWN_FRAME_START = 29;
var DROPDOWN_FRAME_END = 55;
// Frame numbers for attract animation
var ATTRACT_FRAME_START = 56;
var ATTRACT_FRAME_END = 340;
var DEFAULT_FPS = 30;
// Make the mole go down faster on hit:
var HIT_FPS = 60;
var SFX_HIT = SoundCache.getSound(helpers.getSoundURL('whackaMole_hit.wav'));
var SFX_LIFT = SoundCache.getSound(helpers.getSoundURL('moleLiftMechanism.wav'));
var SFX_LONG_LAUGH = SoundCache.getSound(helpers.getSoundURL('whackaMole_longLaugh.wav'));
var SFX_RANDOM_SQUEAKS = [
SoundCache.getSound(helpers.getSoundURL('whackaMole_randomSqueak_1.wav')),
SoundCache.getSound(helpers.getSoundURL('whackaMole_randomSqueak_2.wav')),
SoundCache.getSound(helpers.getSoundURL('whackaMole_randomSqueak_3.wav')),
SoundCache.getSound(helpers.getSoundURL('whackaMole_randomSqueak_4.wav'))
];
var DEFAULT_SFX_VOLUME = 0.2;
var Mole = function(entityID, column, row, defaultIdleTime, masterVolume) {
this.defaultIdleTime = defaultIdleTime;
this.moleEntityID = entityID;
this.column = column;
this.row = row;
this.state = MOLE_STATE.DOWN;
this.lastFPS = 0;
this.speed = 1.0;
this.idleTime = 2000;
this.nextMoveAt = -1;
this.masterVolume = masterVolume;
try {
var userData = JSON.parse(Entities.getEntityProperties(entityID, ['userData']).userData);
this.colliderID = userData.whackAMole.colliderID;
} catch (e) {
// e
}
};
// TODO: make a sub-mole (more physical, so it can really pop out of the hole with the spring action)
Mole.prototype = {
moleEntityID: null,
colliderID: null,
column: null,
row: null,
speed: null,
idleTime: null,
nextMoveAt: null,
_animate: function(firstFrame, lastFrame, fps) {
if (fps === undefined) {
fps = DEFAULT_FPS;
}
var entityProperties = {
animation: {
currentFrame: firstFrame,
firstFrame: firstFrame,
lastFrame: lastFrame,
running: true,
url: helpers.getModelURL('moleRig_Opt.fbx'),
loop: false,
fps: fps,
hold: true
}
};
helpers.debugPrint('playing animation -> ' + JSON.stringify(entityProperties));
Entities.editEntity(this.moleEntityID, entityProperties);
return (Math.abs(firstFrame - lastFrame) / fps) * constants.MILLISECONDS_PER_SECOND;
},
_playSound: function(sound, properties) {
if (properties === undefined) {
properties = {};
}
if (properties.position === undefined) {
properties.position = Entities.getEntityProperties(this.moleEntityID, 'position').position;
}
if (properties.volume === undefined) {
properties.volume = DEFAULT_SFX_VOLUME;
}
return Audio.playSound(sound, properties);
},
// makes the mole spin
spin: function() {
Entities.editEntity(this.moleEntityID, {
angularVelocity: Quat.fromVec3Degrees({
x: 0,
y: 20,
z: 0
}),
angularDamping: 0.0
});
},
reset: function() {
this._animate(0, 0);
},
reactAngry: function() {
var position = Entities.getEntityProperties(this.moleEntityID, 'position').position;
position.y += 0.3;
Entities.addEntity({
azimuthStart: 2.5,
dimensions: {
x: 0.26400002837181091,
y: 0.26400002837181091,
z: 0.26400002837181091
},
emitAcceleration: {
x: 0,
y: 0,
z: 0
},
emitOrientation: {
w: 0.7070610523223877,
x: -0.70715254545211792,
y: -1.5258869098033756e-05,
z: -1.5258869098033756e-05
},
emitRate: 3,
emitSpeed: 0.20000000298023224,
lifespan: 0.40000000596046448,
maxParticles: 5,
particleRadius: 0.045000001788139343,
radiusFinish: 0.045000001788139343,
radiusStart: 0.045000001788139343,
speedSpread: 0.10000000149011612,
textures: Script.resolvePath('particles/cartoonSwear_wide.png'),
type: "ParticleEffect",
lifetime: 0.6,
position: position
});
},
hit: function() {
var currentMilliseconds = Date.now();
helpers.debugPrint('HIT!!');
this.reactAngry();
this._playSound(SFX_HIT);
if (this.state === MOLE_STATE.POPUP) {
var startFrame = DROPDOWN_FRAME_START;
try {
var animation = Entities.getEntityProperties(this.moleEntityID, 'animation').animation;
var maxDropDownFrames = DROPDOWN_FRAME_END - DROPDOWN_FRAME_START;
startFrame = DROPDOWN_FRAME_END - Math.min(animation.currentFrame - POPUP_FRAME_START, maxDropDownFrames);
} catch (e) {
// e
}
this.nextMoveAt = currentMilliseconds + this.dropDown(HIT_FPS, startFrame);
} else if (this.state === MOLE_STATE.UP) {
this.nextMoveAt = currentMilliseconds + this.dropDown(HIT_FPS);
}
},
beginMove: function(currentMilliseconds, speed) {
this.speed = speed;
this.nextMoveAt = currentMilliseconds + this.popUp();
},
nextMove: function(currentMilliseconds) {
if (this.state === MOLE_STATE.POPUP) {
this.idle();
this.nextMoveAt = currentMilliseconds + (this.idleTime / this.speed);
} else if (this.state === MOLE_STATE.UP) {
this.nextMoveAt = currentMilliseconds + this.dropDown();
} else if (this.state === MOLE_STATE.DROPDOWN) {
this.state = MOLE_STATE.DOWN;
}
},
popUp: function(fps) {
this._playSound(SFX_LIFT);
this.state = MOLE_STATE.POPUP;
var runtimeMilliseconds = this._animate(POPUP_FRAME_START, POPUP_FRAME_END, fps);
helpers.debugPrint('popUp Mole -> ' + this.moleEntityID);
return runtimeMilliseconds;
},
idle: function() {
this.state = MOLE_STATE.UP;
var runtimeMilliseconds = this._animate(POPUP_FRAME_END, POPUP_FRAME_END);
helpers.debugPrint('idle Mole -> ' + this.moleEntityID);
return runtimeMilliseconds;
},
dropDown: function(fps, startFrame) {
if (startFrame === undefined) {
startFrame = DROPDOWN_FRAME_START;
}
this.state = MOLE_STATE.DROPDOWN;
var randomSqueak = SFX_RANDOM_SQUEAKS[Math.floor(Math.random() * SFX_RANDOM_SQUEAKS.length)];
this._playSound(randomSqueak);
var runtimeMilliseconds = this._animate(startFrame, DROPDOWN_FRAME_END, fps);
helpers.debugPrint('dropDown Mole -> ' + this.moleEntityID);
return runtimeMilliseconds;
},
attract: function() {
if (Math.random() < 0.20) {
this._playSound(SFX_LONG_LAUGH);
}
this.state = MOLE_STATE.LURE;
return this._animate(ATTRACT_FRAME_START, ATTRACT_FRAME_END);
}
};
module.exports = Mole;