mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-16 13:32:49 +02:00
pre-test with eric
This commit is contained in:
parent
f3c1ca8220
commit
455ed27c2b
3 changed files with 388 additions and 339 deletions
|
@ -1,54 +1,110 @@
|
|||
// bubble.js
|
||||
// part of bubblewand
|
||||
//
|
||||
// Script Type: Entity
|
||||
// Created by James B. Pollack @imgntn -- 09/03/2015
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// example of a nested entity. it doesn't do much now besides delete itself if it collides with something (bubbles are fragile! it would be cool if it sometimes merged with other bubbbles it hit)
|
||||
// todo: play bubble sounds from the bubble itself instead of the wand.
|
||||
// todo: play bubble sounds & particle bursts from the bubble itself instead of the wand.
|
||||
// blocker: needs some sound fixes and a way to find its own position before unload for spatialization
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
|
||||
(function() {
|
||||
// Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js");
|
||||
// Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js");
|
||||
Script.include("../../utilities.js");
|
||||
Script.include("../../libraries/utils.js");
|
||||
|
||||
var BUBBLE_PARTICLE_TEXTURE = "https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png"
|
||||
|
||||
|
||||
BUBBLE_PARTICLE_COLOR = {
|
||||
red: 0,
|
||||
green: 40,
|
||||
blue: 255,
|
||||
};
|
||||
|
||||
var _this = this;
|
||||
|
||||
var properties;
|
||||
|
||||
//var popSound;
|
||||
this.preload = function(entityID) {
|
||||
// print('bubble preload')
|
||||
this.entityID = entityID;
|
||||
// popSound = SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop.wav");
|
||||
|
||||
}
|
||||
|
||||
this.collisionWithEntity = function(myID, otherID, collision) {
|
||||
//if(Entites.getEntityProperties(otherID).userData.objectType==='') { merge bubbles?}
|
||||
// Entities.deleteEntity(myID);
|
||||
// this.burstBubbleSound(collision.contactPoint)
|
||||
_this.entityID = entityID;
|
||||
Script.update.connect(_t.internalUpdate);
|
||||
};
|
||||
|
||||
this.internalUpdate = function() {
|
||||
// we want the position at unload but for some reason it keeps getting set to 0,0,0 -- so i just exclude that location. sorry origin bubbles.
|
||||
var tmpProperties = Entities.getEntityProperties(_this.entityID);
|
||||
if (tmpProperties.position.x !== 0 && tmpProperties.position.y !== 0 && tmpProperties.position.z !== 0) {
|
||||
properties = tmpProperties;
|
||||
}
|
||||
};
|
||||
|
||||
this.unload = function(entityID) {
|
||||
// this.properties = Entities.getEntityProperties(entityID);
|
||||
//var location = this.properties.position;
|
||||
//this.burstBubbleSound();
|
||||
Script.update.disconnect(this.internalUpdate);
|
||||
var position = properties.position;
|
||||
_this.endOfBubble(position);
|
||||
|
||||
};
|
||||
|
||||
this.endOfBubble = function(position) {
|
||||
this.createBurstParticles(position);
|
||||
};
|
||||
|
||||
this.createBurstParticles = function(position) {
|
||||
//get the current position of the bubble
|
||||
var position = properties.position;
|
||||
//var orientation = properties.orientation;
|
||||
|
||||
var animationSettings = JSON.stringify({
|
||||
fps: 30,
|
||||
frameIndex: 0,
|
||||
running: true,
|
||||
firstFrame: 0,
|
||||
lastFrame: 30,
|
||||
loop: false
|
||||
});
|
||||
|
||||
var particleBurst = Entities.addEntity({
|
||||
type: "ParticleEffect",
|
||||
animationSettings: animationSettings,
|
||||
animationIsPlaying: true,
|
||||
position: position,
|
||||
lifetime: 0.2,
|
||||
dimensions: {
|
||||
x: 1,
|
||||
y: 1,
|
||||
z: 1
|
||||
},
|
||||
emitVelocity: {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: 0
|
||||
},
|
||||
velocitySpread: {
|
||||
x: 0.45,
|
||||
y: 0.45,
|
||||
z: 0.45
|
||||
},
|
||||
emitAcceleration: {
|
||||
x: 0,
|
||||
y: -0.1,
|
||||
z: 0
|
||||
},
|
||||
alphaStart: 1.0,
|
||||
alpha: 1,
|
||||
alphaFinish: 0.0,
|
||||
textures: BUBBLE_PARTICLE_TEXTURE,
|
||||
color: BUBBLE_PARTICLE_COLOR,
|
||||
lifespan: 0.2,
|
||||
visible: true,
|
||||
locked: false
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
this.burstBubbleSound = function(location) {
|
||||
|
||||
// var audioOptions = {
|
||||
// volume: 0.5,
|
||||
// position: location
|
||||
// }
|
||||
|
||||
//Audio.playSound(popSound, audioOptions);
|
||||
|
||||
}
|
||||
|
||||
|
||||
})
|
|
@ -1,41 +1,42 @@
|
|||
// createWand.js
|
||||
// part of bubblewand
|
||||
//
|
||||
// Script Type: Entity Spawner
|
||||
// Created by James B. Pollack @imgntn -- 09/03/2015
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Loads a wand model and attaches the bubble wand behavior.
|
||||
// Loads a wand model and attaches the bubble wand behavior.
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
|
||||
|
||||
Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js");
|
||||
Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js");
|
||||
|
||||
var wandModel = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx?" + randInt(0, 10000);
|
||||
var scriptURL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/wand.js?" + randInt(1, 100500)
|
||||
|
||||
Script.include("../../utilities.js");
|
||||
Script.include("../../libraries/utils.js");
|
||||
|
||||
var WAND_MODEL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx';
|
||||
var WAND_COLLISION_SHAPE = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj';
|
||||
var WAND_SCRIPT_URL = Script.resolvePath("wand.js?"+randInt(0,4000));
|
||||
//create the wand in front of the avatar
|
||||
var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(Camera.getOrientation())));
|
||||
var center = Vec3.sum(MyAvatar.position, Vec3.multiply(1, Quat.getFront(Camera.getOrientation())));
|
||||
|
||||
var wand = Entities.addEntity({
|
||||
type: "Model",
|
||||
modelURL: wandModel,
|
||||
position: center,
|
||||
dimensions: {
|
||||
x: 0.1,
|
||||
y: 1,
|
||||
z: 0.1
|
||||
},
|
||||
//must be enabled to be grabbable in the physics engine
|
||||
collisionsWillMove: true,
|
||||
shapeType: 'box',
|
||||
script: scriptURL
|
||||
type: "Model",
|
||||
modelURL: WAND_MODEL,
|
||||
position: center,
|
||||
dimensions: {
|
||||
x: 0.05,
|
||||
y: 0.5,
|
||||
z: 0.05
|
||||
},
|
||||
//must be enabled to be grabbable in the physics engine
|
||||
collisionsWillMove: true,
|
||||
compoundShapeURL: WAND_COLLISION_SHAPE,
|
||||
script: WAND_SCRIPT_URL
|
||||
});
|
||||
|
||||
function cleanup() {
|
||||
Entities.deleteEntity(wand);
|
||||
Entities.deleteEntity(wand);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// wand.js
|
||||
// part of bubblewand
|
||||
//
|
||||
// Script Type: Entity Script
|
||||
// Created by James B. Pollack @imgntn -- 09/03/2015
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
|
@ -11,307 +12,298 @@
|
|||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
'use strict';
|
||||
|
||||
function convertRange(value, r1, r2) {
|
||||
return (value - r1[0]) * (r2[1] - r2[0]) / (r1[1] - r1[0]) + r2[0];
|
||||
return (value - r1[0]) * (r2[1] - r2[0]) / (r1[1] - r1[0]) + r2[0];
|
||||
}
|
||||
|
||||
(function() {
|
||||
Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js");
|
||||
Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js");
|
||||
|
||||
var bubbleModel = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx";
|
||||
var bubbleScript = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000);
|
||||
var popSound = SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop.wav");
|
||||
|
||||
var TARGET_SIZE = 0.4;
|
||||
var TARGET_COLOR = {
|
||||
red: 128,
|
||||
green: 128,
|
||||
blue: 128
|
||||
};
|
||||
var TARGET_COLOR_HIT = {
|
||||
red: 0,
|
||||
green: 255,
|
||||
blue: 0
|
||||
};
|
||||
|
||||
var HAND_SIZE = 0.25;
|
||||
var leftCubePosition = MyAvatar.getLeftPalmPosition();
|
||||
var rightCubePosition = MyAvatar.getRightPalmPosition();
|
||||
|
||||
var leftHand = Overlays.addOverlay("cube", {
|
||||
position: leftCubePosition,
|
||||
size: HAND_SIZE,
|
||||
color: {
|
||||
red: 0,
|
||||
green: 0,
|
||||
blue: 255
|
||||
},
|
||||
alpha: 1,
|
||||
solid: false
|
||||
});
|
||||
|
||||
var rightHand = Overlays.addOverlay("cube", {
|
||||
position: rightCubePosition,
|
||||
size: HAND_SIZE,
|
||||
color: {
|
||||
red: 255,
|
||||
green: 0,
|
||||
blue: 0
|
||||
},
|
||||
alpha: 1,
|
||||
solid: false
|
||||
});
|
||||
|
||||
var gustZoneOverlay = Overlays.addOverlay("cube", {
|
||||
position: getGustDetectorPosition(),
|
||||
size: TARGET_SIZE,
|
||||
color: TARGET_COLOR,
|
||||
alpha: 1,
|
||||
solid: false
|
||||
});
|
||||
Script.include("../../utilities.js");
|
||||
Script.include("../../libraries/utils.js");
|
||||
|
||||
|
||||
function getGustDetectorPosition() {
|
||||
//put the zone in front of your avatar's face
|
||||
var DISTANCE_IN_FRONT = 0.2;
|
||||
var DISTANCE_UP = 0.5;
|
||||
var DISTANCE_TO_SIDE = 0.0;
|
||||
var BUBBLE_MODEL = "http://hifi-public.s3.amazonaws.com/james/bubblewand/models/bubble/bubble.fbx";
|
||||
var BUBBLE_SCRIPT = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000);
|
||||
Script.resolvePath('bubble.js?' + randInt(0, 5000));
|
||||
|
||||
var up = Quat.getUp(MyAvatar.orientation);
|
||||
var front = Quat.getFront(MyAvatar.orientation);
|
||||
var right = Quat.getRight(MyAvatar.orientation);
|
||||
|
||||
var upOffset = Vec3.multiply(up, DISTANCE_UP);
|
||||
var rightOffset = Vec3.multiply(right, DISTANCE_TO_SIDE);
|
||||
var frontOffset = Vec3.multiply(front, DISTANCE_IN_FRONT);
|
||||
|
||||
var offset = Vec3.sum(Vec3.sum(rightOffset, frontOffset), upOffset);
|
||||
var position = Vec3.sum(MyAvatar.position, offset);
|
||||
return position;
|
||||
}
|
||||
var HAND_SIZE = 0.25;
|
||||
var TARGET_SIZE = 0.04;
|
||||
|
||||
|
||||
var BUBBLE_GRAVITY = {
|
||||
x: 0,
|
||||
y: -0.05,
|
||||
z: 0
|
||||
}
|
||||
|
||||
var BUBBLE_GRAVITY = {
|
||||
x: 0,
|
||||
y: -0.1,
|
||||
z: 0
|
||||
}
|
||||
|
||||
var MOUTH_MODE_GROWTH_FACTOR = 0.005;
|
||||
var WAVE_MODE_GROWTH_FACTOR = 0.005;
|
||||
var SHRINK_LOWER_LIMIT = 0.02;
|
||||
var SHRINK_FACTOR = 0.001;
|
||||
var VELOCITY_STRENGTH_LOWER_LIMIT = 0.01;
|
||||
var BUBBLE_DIVISOR = 50;
|
||||
var BUBBLE_LIFETIME_MIN = 3;
|
||||
var BUBBLE_LIFETIME_MAX = 8;
|
||||
|
||||
function getGustDetectorPosition() {
|
||||
//put the zone in front of your avatar's face
|
||||
var DISTANCE_IN_FRONT = 0.2;
|
||||
var DISTANCE_UP = 0.5;
|
||||
var DISTANCE_TO_SIDE = 0.0;
|
||||
|
||||
var up = Quat.getUp(MyAvatar.orientation);
|
||||
var front = Quat.getFront(MyAvatar.orientation);
|
||||
var right = Quat.getRight(MyAvatar.orientation);
|
||||
|
||||
var upOffset = Vec3.multiply(up, DISTANCE_UP);
|
||||
var rightOffset = Vec3.multiply(right, DISTANCE_TO_SIDE);
|
||||
var frontOffset = Vec3.multiply(front, DISTANCE_IN_FRONT);
|
||||
|
||||
var offset = Vec3.sum(Vec3.sum(rightOffset, frontOffset), upOffset);
|
||||
var position = Vec3.sum(MyAvatar.position, offset);
|
||||
return position;
|
||||
}
|
||||
|
||||
|
||||
var wandEntity = this;
|
||||
|
||||
this.preload = function(entityID) {
|
||||
// print('PRELOAD')
|
||||
this.entityID = entityID;
|
||||
this.properties = Entities.getEntityProperties(this.entityID);
|
||||
}
|
||||
|
||||
this.unload = function(entityID) {
|
||||
Overlays.deleteOverlay(leftHand);
|
||||
Overlays.deleteOverlay(rightHand);
|
||||
Overlays.deleteOverlay(gustZoneOverlay)
|
||||
Entities.editEntity(entityID, {
|
||||
name: ""
|
||||
});
|
||||
Script.update.disconnect(BubbleWand.update);
|
||||
Entities.deleteEntity(BubbleWand.currentBubble);
|
||||
while (BubbleWand.bubbles.length > 0) {
|
||||
Entities.deleteEntity(BubbleWand.bubbles.pop());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
var BubbleWand = {
|
||||
bubbles: [],
|
||||
currentBubble: null,
|
||||
update: function() {
|
||||
BubbleWand.internalUpdate();
|
||||
},
|
||||
internalUpdate: function() {
|
||||
var _t = this;
|
||||
//get the current position of the wand
|
||||
var properties = Entities.getEntityProperties(wandEntity.entityID);
|
||||
var wandPosition = properties.position;
|
||||
|
||||
//debug overlays for mouth mode
|
||||
var leftHandPos = MyAvatar.getLeftPalmPosition();
|
||||
var rightHandPos = MyAvatar.getRightPalmPosition();
|
||||
|
||||
Overlays.editOverlay(leftHand, {
|
||||
position: leftHandPos
|
||||
});
|
||||
Overlays.editOverlay(rightHand, {
|
||||
position: rightHandPos
|
||||
});
|
||||
|
||||
//if the wand is in the gust detector, activate mouth mode and change the overlay color
|
||||
var hitTargetWithWand = findSphereSphereHit(wandPosition, HAND_SIZE / 2, getGustDetectorPosition(), TARGET_SIZE / 2)
|
||||
|
||||
var mouthMode;
|
||||
if (hitTargetWithWand) {
|
||||
Overlays.editOverlay(gustZoneOverlay, {
|
||||
position: getGustDetectorPosition(),
|
||||
color: TARGET_COLOR_HIT
|
||||
})
|
||||
mouthMode = true;
|
||||
|
||||
} else {
|
||||
Overlays.editOverlay(gustZoneOverlay, {
|
||||
position: getGustDetectorPosition(),
|
||||
color: TARGET_COLOR
|
||||
})
|
||||
mouthMode = false;
|
||||
}
|
||||
|
||||
var volumeLevel = MyAvatar.audioAverageLoudness;
|
||||
//volume numbers are pretty large, so lets scale them down.
|
||||
var convertedVolume = convertRange(volumeLevel, [0, 5000], [0, 10]);
|
||||
|
||||
// default is 'wave mode', where waving the object around grows the bubbles
|
||||
var velocity = Vec3.subtract(wandPosition, BubbleWand.lastPosition)
|
||||
|
||||
//store the last position of the wand for velocity calculations
|
||||
_t.lastPosition = wandPosition;
|
||||
|
||||
// velocity numbers are pretty small, so lets make them a bit bigger
|
||||
var velocityStrength = Vec3.length(velocity) * 100;
|
||||
|
||||
if (velocityStrength > 10) {
|
||||
velocityStrength = 10
|
||||
}
|
||||
|
||||
//actually grow the bubble
|
||||
var dimensions = Entities.getEntityProperties(_t.currentBubble).dimensions;
|
||||
|
||||
if (velocityStrength > 1 || convertedVolume > 1) {
|
||||
|
||||
//add some variation in bubble sizes
|
||||
var bubbleSize = randInt(1, 5);
|
||||
bubbleSize = bubbleSize / 10;
|
||||
|
||||
//release the bubble if its dimensions are bigger than the bubble size
|
||||
if (dimensions.x > bubbleSize) {
|
||||
//bubbles pop after existing for a bit -- so set a random lifetime
|
||||
var lifetime = randInt(3, 8);
|
||||
|
||||
//sound is somewhat unstable at the moment so this is commented out. really audio should be played by the bubbles, but there's a blocker.
|
||||
// Script.setTimeout(function() {
|
||||
// _t.burstBubbleSound(_t.currentBubble)
|
||||
// }, lifetime * 1000)
|
||||
|
||||
|
||||
//todo: angular velocity without the controller -- forward velocity for mouth mode bubbles
|
||||
// var angularVelocity = Controller.getSpatialControlRawAngularVelocity(hands.leftHand.tip);
|
||||
|
||||
Entities.editEntity(_t.currentBubble, {
|
||||
velocity: Vec3.normalize(velocity),
|
||||
// angularVelocity: Controller.getSpatialControlRawAngularVelocity(hands.leftHand.tip),
|
||||
lifetime: lifetime
|
||||
});
|
||||
|
||||
//release the bubble -- when we create a new bubble, it will carry on and this update loop will affect the new bubble
|
||||
BubbleWand.spawnBubble();
|
||||
|
||||
return
|
||||
} else {
|
||||
if (mouthMode) {
|
||||
dimensions.x += 0.015 * convertedVolume;
|
||||
dimensions.y += 0.015 * convertedVolume;
|
||||
dimensions.z += 0.015 * convertedVolume;
|
||||
|
||||
} else {
|
||||
dimensions.x += 0.015 * velocityStrength;
|
||||
dimensions.y += 0.015 * velocityStrength;
|
||||
dimensions.z += 0.015 * velocityStrength;
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if (dimensions.x >= 0.02) {
|
||||
dimensions.x -= 0.001;
|
||||
dimensions.y -= 0.001;
|
||||
dimensions.z -= 0.001;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//update the bubble to stay with the wand tip
|
||||
Entities.editEntity(_t.currentBubble, {
|
||||
position: _t.wandTipPosition,
|
||||
dimensions: dimensions
|
||||
});
|
||||
|
||||
},
|
||||
burstBubbleSound: function(bubble) {
|
||||
//we want to play the sound at the same location and orientation as the bubble
|
||||
var position = Entities.getEntityProperties(bubble).position;
|
||||
var orientation = Entities.getEntityProperties(bubble).orientation;
|
||||
|
||||
//set the options for the audio injector
|
||||
var audioOptions = {
|
||||
volume: 0.5,
|
||||
position: position,
|
||||
orientation: orientation
|
||||
}
|
||||
|
||||
|
||||
//var audioInjector = Audio.playSound(popSound, audioOptions);
|
||||
|
||||
//remove this bubble from the array to keep things clean
|
||||
var i = BubbleWand.bubbles.indexOf(bubble);
|
||||
if (i != -1) {
|
||||
BubbleWand.bubbles.splice(i, 1);
|
||||
}
|
||||
|
||||
},
|
||||
spawnBubble: function() {
|
||||
var _t = this;
|
||||
//create a new bubble at the tip of the wand
|
||||
//the tip of the wand is going to be in a different place than the center, so we move in space relative to the model to find that position
|
||||
|
||||
var properties = Entities.getEntityProperties(wandEntity.entityID);
|
||||
var wandPosition = properties.position;
|
||||
var upVector = Quat.getUp(properties.rotation);
|
||||
var frontVector = Quat.getFront(properties.rotation);
|
||||
var upOffset = Vec3.multiply(upVector, 0.5);
|
||||
var forwardOffset = Vec3.multiply(frontVector, 0.1);
|
||||
var offsetVector = Vec3.sum(upOffset, forwardOffset);
|
||||
var wandTipPosition = Vec3.sum(wandPosition, offsetVector);
|
||||
_t.wandTipPosition = wandTipPosition;
|
||||
|
||||
//store the position of the tip on spawn for use in velocity calculations
|
||||
_t.lastPosition = wandTipPosition;
|
||||
|
||||
//create a bubble at the wand tip
|
||||
_t.currentBubble = Entities.addEntity({
|
||||
type: 'Model',
|
||||
modelURL: bubbleModel,
|
||||
position: wandTipPosition,
|
||||
dimensions: {
|
||||
x: 0.01,
|
||||
y: 0.01,
|
||||
z: 0.01
|
||||
},
|
||||
collisionsWillMove: false,
|
||||
ignoreForCollisions: true,
|
||||
gravity: BUBBLE_GRAVITY,
|
||||
// collisionSoundURL:popSound,
|
||||
shapeType: "sphere",
|
||||
script: bubbleScript,
|
||||
});
|
||||
|
||||
//add this bubble to an array of bubbles so we can keep track of them
|
||||
_t.bubbles.push(_t.currentBubble)
|
||||
|
||||
},
|
||||
init: function() {
|
||||
this.spawnBubble();
|
||||
Script.update.connect(BubbleWand.update);
|
||||
}
|
||||
}
|
||||
var wandEntity = this;
|
||||
|
||||
this.preload = function(entityID) {
|
||||
this.entityID = entityID;
|
||||
this.properties = Entities.getEntityProperties(this.entityID);
|
||||
BubbleWand.originalProperties = this.properties;
|
||||
BubbleWand.init();
|
||||
print('initial position' + JSON.stringify(BubbleWand.originalProperties.position));
|
||||
}
|
||||
|
||||
this.unload = function(entityID) {
|
||||
Entities.editEntity(entityID, {
|
||||
name: ""
|
||||
});
|
||||
Script.update.disconnect(BubbleWand.update);
|
||||
Entities.deleteEntity(BubbleWand.currentBubble);
|
||||
while (BubbleWand.bubbles.length > 0) {
|
||||
Entities.deleteEntity(BubbleWand.bubbles.pop());
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
var BubbleWand = {
|
||||
bubbles: [],
|
||||
timeSinceMoved: 0,
|
||||
resetAtTime: 2,
|
||||
currentBubble: null,
|
||||
atOriginalLocation: true,
|
||||
update: function(deltaTime) {
|
||||
BubbleWand.internalUpdate(deltaTime);
|
||||
},
|
||||
internalUpdate: function(deltaTime) {
|
||||
var _t = this;
|
||||
|
||||
var GRAB_USER_DATA_KEY = "grabKey";
|
||||
var defaultGrabData = {
|
||||
activated: false,
|
||||
avatarId: null
|
||||
};
|
||||
|
||||
var grabData = getEntityCustomData(GRAB_USER_DATA_KEY, wandEntity.entityID, defaultGrabData);
|
||||
if (grabData.activated && grabData.avatarId == MyAvatar.sessionUUID) {
|
||||
|
||||
// remember we're being grabbed so we can detect being released
|
||||
_t.beingGrabbed = true;
|
||||
|
||||
// print out that we're being grabbed
|
||||
// print("I'm being grabbed...");
|
||||
_t.handleGrabbedWand();
|
||||
|
||||
} else if (_t.beingGrabbed) {
|
||||
|
||||
// if we are not being grabbed, and we previously were, then we were just released, remember that
|
||||
// and print out a message
|
||||
_t.beingGrabbed = false;
|
||||
// print("I'm was released...");
|
||||
return
|
||||
}
|
||||
|
||||
},
|
||||
handleGrabbedWand: function() {
|
||||
var _t = this;
|
||||
|
||||
// print('HANDLE GRAB 1')
|
||||
var properties = Entities.getEntityProperties(wandEntity.entityID);
|
||||
var wandPosition = properties.position;
|
||||
//if the wand is in the gust detector, activate mouth mode and change the overlay color
|
||||
var hitTargetWithWand = findSphereSphereHit(wandPosition, HAND_SIZE / 2, getGustDetectorPosition(), TARGET_SIZE / 2)
|
||||
|
||||
var velocity = Vec3.subtract(wandPosition, _t.lastPosition)
|
||||
|
||||
// print('VELOCITY:' + JSON.stringify(velocity));
|
||||
// print('HANDLE GRAB 2')
|
||||
var velocityStrength = Vec3.length(velocity) * 100;
|
||||
|
||||
var upVector = Quat.getUp(properties.rotation);
|
||||
var frontVector = Quat.getFront(properties.rotation);
|
||||
var upOffset = Vec3.multiply(upVector, 0.2);
|
||||
var wandTipPosition = Vec3.sum(wandPosition, upOffset);
|
||||
_t.wandTipPosition = wandTipPosition;
|
||||
|
||||
var mouthMode;
|
||||
|
||||
if (hitTargetWithWand) {
|
||||
mouthMode = true;
|
||||
} else {
|
||||
mouthMode = false;
|
||||
}
|
||||
|
||||
if (velocityStrength < VELOCITY_STRENGTH_LOWER_LIMIT) {
|
||||
velocityStrength = 0
|
||||
}
|
||||
|
||||
var isMoving;
|
||||
if (velocityStrength === 0) {
|
||||
isMoving = false;
|
||||
} else {
|
||||
isMoving = true;
|
||||
}
|
||||
// print('MOVING?' + isMoving)
|
||||
if (isMoving === true) {
|
||||
_t.timeSinceMoved = 0;
|
||||
_t.atOriginalLocation = false;
|
||||
} else {
|
||||
_t.timeSinceMoved = _t.timeSinceMoved + deltaTime;
|
||||
}
|
||||
|
||||
if (isMoving === false && _t.atOriginalLocation === false) {
|
||||
if (_t.timeSinceMoved > _t.resetAtTime) {
|
||||
_t.timeSinceMoved = 0;
|
||||
_t.returnToOriginalLocation();
|
||||
}
|
||||
}
|
||||
|
||||
var volumeLevel = MyAvatar.audioAverageLoudness;
|
||||
//volume numbers are pretty large, so lets scale them down.
|
||||
var convertedVolume = convertRange(volumeLevel, [0, 5000], [0, 10]);
|
||||
|
||||
// default is 'wave mode', where waving the object around grows the bubbles
|
||||
|
||||
//store the last position of the wand for velocity calculations
|
||||
_t.lastPosition = wandPosition;
|
||||
|
||||
if (velocityStrength > 10) {
|
||||
velocityStrength = 10
|
||||
}
|
||||
|
||||
//actually grow the bubble
|
||||
var dimensions = Entities.getEntityProperties(_t.currentBubble).dimensions;
|
||||
var avatarFront = Quat.getFront(MyAvatar.orientation);
|
||||
var forwardOffset = Vec3.multiply(avatarFront, 0.1);
|
||||
|
||||
if (velocityStrength > 1 || convertedVolume > 1) {
|
||||
|
||||
//add some variation in bubble sizes
|
||||
var bubbleSize = randInt(1, 5);
|
||||
bubbleSize = bubbleSize / BUBBLE_DIVISOR;
|
||||
|
||||
//release the bubble if its dimensions are bigger than the bubble size
|
||||
if (dimensions.x > bubbleSize) {
|
||||
//bubbles pop after existing for a bit -- so set a random lifetime
|
||||
var lifetime = randInt(BUBBLE_LIFETIME_MIN, BUBBLE_LIFETIME_MAX);
|
||||
|
||||
Entities.editEntity(_t.currentBubble, {
|
||||
velocity: mouthMode ? avatarFront : velocity,
|
||||
lifetime: lifetime
|
||||
});
|
||||
|
||||
//release the bubble -- when we create a new bubble, it will carry on and this update loop will affect the new bubble
|
||||
BubbleWand.spawnBubble();
|
||||
|
||||
return
|
||||
} else {
|
||||
|
||||
if (mouthMode) {
|
||||
dimensions.x += WAVE_MODE_GROWTH_FACTOR * convertedVolume;
|
||||
dimensions.y += WAVE_MODE_GROWTH_FACTOR * convertedVolume;
|
||||
dimensions.z += WAVE_MODE_GROWTH_FACTOR * convertedVolume;
|
||||
|
||||
} else {
|
||||
dimensions.x += WAVE_MODE_GROWTH_FACTOR * velocityStrength;
|
||||
dimensions.y += WAVE_MODE_GROWTH_FACTOR * velocityStrength;
|
||||
dimensions.z += WAVE_MODE_GROWTH_FACTOR * velocityStrength;
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
if (dimensions.x >= SHRINK_LOWER_LIMIT) {
|
||||
dimensions.x -= SHRINK_FACTOR;
|
||||
dimensions.y -= SHRINK_FACTOR;
|
||||
dimensions.z -= SHRINK_FACTOR;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//update the bubble to stay with the wand tip
|
||||
Entities.editEntity(_t.currentBubble, {
|
||||
position: _t.wandTipPosition,
|
||||
dimensions: dimensions
|
||||
});
|
||||
},
|
||||
spawnBubble: function() {
|
||||
var _t = this;
|
||||
//create a new bubble at the tip of the wand
|
||||
//the tip of the wand is going to be in a different place than the center, so we move in space relative to the model to find that position
|
||||
|
||||
var properties = Entities.getEntityProperties(wandEntity.entityID);
|
||||
var wandPosition = properties.position;
|
||||
var upVector = Quat.getUp(properties.rotation);
|
||||
var frontVector = Quat.getFront(properties.rotation);
|
||||
var upOffset = Vec3.multiply(upVector, 0.2);
|
||||
var wandTipPosition = Vec3.sum(wandPosition, upOffset);
|
||||
_t.wandTipPosition = wandTipPosition;
|
||||
|
||||
//store the position of the tip on spawn for use in velocity calculations
|
||||
_t.lastPosition = wandPosition;
|
||||
|
||||
//create a bubble at the wand tip
|
||||
_t.currentBubble = Entities.addEntity({
|
||||
type: 'Model',
|
||||
modelURL: BUBBLE_MODEL,
|
||||
position: wandTipPosition,
|
||||
dimensions: {
|
||||
x: 0.01,
|
||||
y: 0.01,
|
||||
z: 0.01
|
||||
},
|
||||
collisionsWillMove: true, //true
|
||||
ignoreForCollisions: false, //false
|
||||
gravity: BUBBLE_GRAVITY,
|
||||
shapeType: "sphere",
|
||||
script: BUBBLE_SCRIPT,
|
||||
});
|
||||
//add this bubble to an array of bubbles so we can keep track of them
|
||||
_t.bubbles.push(_t.currentBubble)
|
||||
|
||||
},
|
||||
returnToOriginalLocation: function() {
|
||||
var _t = this;
|
||||
_t.atOriginalLocation = true;
|
||||
Script.update.disconnect(BubbleWand.update)
|
||||
Entities.deleteEntity(_t.currentBubble);
|
||||
Entities.editEntity(wandEntity.entityID, _t.originalProperties)
|
||||
_t.spawnBubble();
|
||||
Script.update.connect(BubbleWand.update);
|
||||
|
||||
},
|
||||
init: function() {
|
||||
var _t = this;
|
||||
this.spawnBubble();
|
||||
Script.update.connect(BubbleWand.update);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
})
|
Loading…
Reference in a new issue