Update bubblewand to not use overlays by default.

This commit is contained in:
James Pollack 2015-09-09 09:48:39 -07:00
parent 66b6d5178f
commit 0ac4da285c
3 changed files with 256 additions and 133 deletions

View file

@ -5,48 +5,140 @@
// 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("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/utilities.js");
Script.include("https://raw.githubusercontent.com/highfidelity/hifi/master/examples/libraries/utils.js");
//var popSound;
var POP_SOUNDS = [
SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop0.wav"),
SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop1.wav"),
SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop2.wav"),
SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop3.wav")
]
BUBBLE_PARTICLE_COLOR = {
red: 0,
green: 40,
blue: 255,
}
var properties;
var checkPositionInterval;
this.preload = function(entityID) {
// print('bubble preload')
this.entityID = entityID;
// popSound = SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop.wav");
// var _t = this;
// _t.entityID = entityID;
// properties = Entities.getEntityProperties(entityID);
// checkPositionInterval = Script.setInterval(function() {
// properties = Entities.getEntityProperties(entityID);
// // print('properties AT CHECK::' + JSON.stringify(properties));
// }, 200);
// _t.loadShader(entityID);
};
this.loadShader = function(entityID) {
setEntityUserData(entityID, {
"ProceduralEntity": {
"shaderUrl": "http://localhost:8080/shaders/bubble.fs?" + randInt(0, 10000),
}
})
};
this.leaveEntity = function(entityID) {
print('LEAVE ENTITY:' + entityID)
};
this.collisionWithEntity = function(myID, otherID, collision) {
//Entities.deleteEntity(myID);
// Entities.deleteEntity(otherID);
};
// this.beforeUnload = function(entityID) {
// print('BEFORE UNLOAD:' + entityID);
// var properties = Entities.getEntityProperties(entityID);
// var position = properties.position;
// print('BEFOREUNLOAD PROPS' + JSON.stringify(position));
// };
this.unload = function(entityID) {
// Script.clearInterval(checkPositionInterval);
// var position = properties.position;
// this.endOfBubble(position);
var properties = Entities.getEntityProperties(entityID)
var position = properties.position;
//print('UNLOAD PROPS' + JSON.stringify(position));
};
this.endOfBubble = function(position) {
this.burstBubbleSound(position);
this.createBurstParticles(position);
}
this.burstBubbleSound = function(position) {
var audioOptions = {
volume: 0.5,
position: position
}
Audio.playSound(POP_SOUNDS[randInt(0, 4)], audioOptions);
}
this.collisionWithEntity = function(myID, otherID, collision) {
//if(Entites.getEntityProperties(otherID).userData.objectType==='') { merge bubbles?}
// Entities.deleteEntity(myID);
// this.burstBubbleSound(collision.contactPoint)
this.createBurstParticles = function(position) {
var _t = this;
//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
});
this.unload = function(entityID) {
// this.properties = Entities.getEntityProperties(entityID);
//var location = this.properties.position;
//this.burstBubbleSound();
};
this.burstBubbleSound = function(location) {
// var audioOptions = {
// volume: 0.5,
// position: location
// }
//Audio.playSound(popSound, audioOptions);
var particleBurst = Entities.addEntity({
type: "ParticleEffect",
animationSettings: animationSettings,
animationIsPlaying: true,
position: position,
lifetime: 1.0,
dimensions: {
x: 1,
y: 1,
z: 1
},
emitVelocity: {
x: 0,
y: -1,
z: 0
},
velocitySpread: {
x: 1,
y: 0,
z: 1
},
emitAcceleration: {
x: 0,
y: -1,
z: 0
},
textures: "https://raw.githubusercontent.com/ericrius1/SantasLair/santa/assets/smokeparticle.png",
color: BUBBLE_PARTICLE_COLOR,
lifespan: 1.0,
visible: true,
locked: false
});
}

View file

@ -13,12 +13,16 @@
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)
var wandModel = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/wand.fbx?' + randInt(0, 10000);
var wandCollisionShape = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/models/wand/collisionHull.obj?' + randInt(0, 10000);
var scriptURL = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/wand.js?' + randInt(0, 10000);
//for local testing
//var scriptURL = "http://localhost:8080/scripts/wand.js?" + randInt(0, 10000);
//create the wand in front of the avatar
var center = Vec3.sum(MyAvatar.position, Vec3.multiply(3, Quat.getFront(Camera.getOrientation())));
var wand = Entities.addEntity({
type: "Model",
modelURL: wandModel,
@ -29,8 +33,9 @@ var wand = Entities.addEntity({
z: 0.1
},
//must be enabled to be grabbable in the physics engine
collisionsWillMove: true,
shapeType: 'box',
compoundShapeURL: wandCollisionShape,
script: scriptURL
});

View file

@ -20,10 +20,22 @@ function convertRange(value, r1, r2) {
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 bubbleScript = 'http://hifi-public.s3.amazonaws.com/james/bubblewand/scripts/bubble.js?' + randInt(1, 10000);
//for local testing
// var bubbleScript = 'http://localhost:8080/scripts/bubble.js?' + randInt(1, 10000);
var TARGET_SIZE = 0.4;
var POP_SOUNDS = [
SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop0.wav"),
SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop1.wav"),
SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop2.wav"),
SoundCache.getSound("http://hifi-public.s3.amazonaws.com/james/bubblewand/sounds/pop3.wav")
]
var overlays = false;
//debug overlays for hand position to detect when wand is near avatar head
var TARGET_SIZE = 0.5;
var TARGET_COLOR = {
red: 128,
green: 128,
@ -36,6 +48,10 @@ function convertRange(value, r1, r2) {
};
var HAND_SIZE = 0.25;
if (overlays) {
var leftCubePosition = MyAvatar.getLeftPalmPosition();
var rightCubePosition = MyAvatar.getRightPalmPosition();
@ -70,6 +86,8 @@ function convertRange(value, r1, r2) {
alpha: 1,
solid: false
});
}
function getGustDetectorPosition() {
@ -98,6 +116,11 @@ function convertRange(value, r1, r2) {
z: 0
}
var BUBBLE_PARTICLE_COLOR = {
red: 0,
blue: 255,
green: 40
}
var wandEntity = this;
@ -108,9 +131,12 @@ function convertRange(value, r1, r2) {
}
this.unload = function(entityID) {
if (overlays) {
Overlays.deleteOverlay(leftHand);
Overlays.deleteOverlay(rightHand);
Overlays.deleteOverlay(gustZoneOverlay)
Overlays.deleteOverlay(gustZoneOverlay);
}
Entities.editEntity(entityID, {
name: ""
});
@ -134,8 +160,24 @@ function convertRange(value, r1, r2) {
//get the current position of the wand
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, BubbleWand.lastPosition)
var velocityStrength = Vec3.length(velocity) * 100;
var mouthMode;
if (hitTargetWithWand) {
mouthMode = true;
} else {
mouthMode = false;
}
//debug overlays for mouth mode
if (overlays) {
var leftHandPos = MyAvatar.getLeftPalmPosition();
var rightHandPos = MyAvatar.getRightPalmPosition();
@ -145,24 +187,18 @@ function convertRange(value, r1, r2) {
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) {
if (mouthMode === true && overlays === true) {
Overlays.editOverlay(gustZoneOverlay, {
position: getGustDetectorPosition(),
color: TARGET_COLOR_HIT
})
mouthMode = true;
} else {
} else if (overlays) {
Overlays.editOverlay(gustZoneOverlay, {
position: getGustDetectorPosition(),
color: TARGET_COLOR
})
mouthMode = false;
}
var volumeLevel = MyAvatar.audioAverageLoudness;
@ -170,7 +206,6 @@ function convertRange(value, r1, r2) {
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;
@ -184,6 +219,8 @@ function convertRange(value, r1, r2) {
//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) {
@ -196,21 +233,17 @@ function convertRange(value, r1, r2) {
//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),
// collisionsWillMove:true,
// ignoreForCollisions:false,
velocity: mouthMode ? avatarFront : velocity,
// angularVelocity: Controller.getSpatialControlRawAngularVelocity(hands.leftHand.tip),
lifetime: lifetime
});
_t.lastBubble = _t.currentBubble;
//release the bubble -- when we create a new bubble, it will carry on and this update loop will affect the new bubble
BubbleWand.spawnBubble();
@ -244,27 +277,18 @@ function convertRange(value, r1, r2) {
});
},
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);
}
checkForEntitiesNearBubble: function() {
var _t = this;
var arrayFound = Entities.findEntities(_t.wandTipPosition, 1);
var foundLength = arrayFound.length;
print('found length:::' + foundLength);
},
enableCollisionsForBubble: function(bubble) {
print('enable bubble collisions:' + bubble)
Entities.editEntity(bubble, {
collisionsWillMove: true,
ignoreForCollisions: false,
})
},
spawnBubble: function() {
var _t = this;
@ -275,10 +299,11 @@ function convertRange(value, r1, r2) {
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);
var upOffset = Vec3.multiply(upVector, 0.4);
// var forwardOffset = Vec3.multiply(frontVector, 0.1);
// var offsetVector = Vec3.sum(upOffset, forwardOffset);
// var wandTipPosition = Vec3.sum(wandPosition, offsetVector);
var wandTipPosition = Vec3.sum(wandPosition, upOffset);
_t.wandTipPosition = wandTipPosition;
//store the position of the tip on spawn for use in velocity calculations
@ -294,10 +319,10 @@ function convertRange(value, r1, r2) {
y: 0.01,
z: 0.01
},
collisionsWillMove: false,
ignoreForCollisions: true,
collisionsWillMove: false, //true
ignoreForCollisions: true, //false
gravity: BUBBLE_GRAVITY,
// collisionSoundURL:popSound,
collisionSoundURL: POP_SOUNDS[randInt(0, 4)],
shapeType: "sphere",
script: bubbleScript,
});
@ -309,6 +334,7 @@ function convertRange(value, r1, r2) {
init: function() {
this.spawnBubble();
Script.update.connect(BubbleWand.update);
}
}