// // particleBird.js // hifi // // This sample script moves a voxel around like a bird and sometimes makes tweeting noises // function vLength(v) { return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); } function printVector(v) { print(v.x + ", " + v.y + ", " + v.z + "\n"); } // Create a random vector with individual lengths between a,b function randVector(a, b) { var rval = { x: a + Math.random() * (b - a), y: a + Math.random() * (b - a), z: a + Math.random() * (b - a) }; return rval; } function vMinus(a, b) { var rval = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z }; return rval; } function vPlus(a, b) { var rval = { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z }; return rval; } function vCopy(a, b) { a.x = b.x; a.y = b.y; a.z = b.z; return; } // Returns a vector which is fraction of the way between a and b function vInterpolate(a, b, fraction) { var rval = { x: a.x + (b.x - a.x) * fraction, y: a.y + (b.y - a.y) * fraction, z: a.z + (b.z - a.z) * fraction }; return rval; } // Decide what kind of bird we are var tweet; var color; var size; var which = Math.random(); if (which < 0.2) { tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/bushtit_1.raw"); color = { r: 100, g: 50, b: 120 }; size = 0.08; } else if (which < 0.4) { tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/rosyfacedlovebird.raw"); color = { r: 100, g: 150, b: 75 }; size = 0.09; } else if (which < 0.6) { tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/saysphoebe.raw"); color = { r: 84, g: 121, b: 36 }; size = 0.05; } else if (which < 0.8) { tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/mexicanWhipoorwill.raw"); color = { r: 23, g: 197, b: 230 }; size = 0.12; } else { tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/westernscreechowl.raw"); color = { r: 50, g: 67, b: 144 }; size = 0.15; } var startTimeInSeconds = new Date().getTime() / 1000; var birdLifetime = 20; // lifetime of the bird in seconds! var position = { x: 0, y: 0, z: 0 }; var targetPosition = { x: 0, y: 0, z: 0 }; var range = 1.0; // Over what distance in meters do you want your bird to fly around var frame = 0; var moving = false; var tweeting = 0; var moved = false; var CHANCE_OF_MOVING = 0.00; var CHANCE_OF_FLAPPING = 0.05; var CHANCE_OF_TWEETING = 0.05; var START_HEIGHT_ABOVE_ME = 1.5; var BIRD_GRAVITY = -0.1; var BIRD_FLAP = 1.0; var myPosition = MyAvatar.position; var properties = { lifetime: birdLifetime, position: { x: myPosition.x, y: myPosition.y + START_HEIGHT_ABOVE_ME, z: myPosition.z }, velocity: { x: 0, y: Math.random() * BIRD_FLAP, z: 0 }, gravity: { x: 0, y: BIRD_GRAVITY, z: 0 }, radius : 0.1, color: { red: 0, green: 255, blue: 0 } }; var range = 1.0; // Distance around avatar where I can move // Create the actual bird var particleID = Particles.addParticle(properties); function moveBird(deltaTime) { // check to see if we've been running long enough that our bird is dead var nowTimeInSeconds = new Date().getTime() / 1000; if ((nowTimeInSeconds - startTimeInSeconds) >= birdLifetime) { print("our bird is dying, stop our script"); Script.stop(); return; } myPosition = MyAvatar.position; frame++; if (frame % 3 == 0) { // Tweeting behavior if (tweeting == 0) { if (Math.random() < CHANCE_OF_TWEETING) { //print("tweet!" + "\n"); var options = new AudioInjectionOptions(); options.position = position; options.volume = 0.75; Audio.playSound(tweet, options); tweeting = 10; } } else { tweeting -= 1; } if (Math.random() < CHANCE_OF_FLAPPING) { // Add a little upward impulse to our bird // TODO: Get velocity // var newProperties = { velocity: { x:0.0, y: Math.random() * BIRD_FLAP, z: 0.0 } }; Particles.editParticle(particleID, newProperties); print("flap!"); } // Moving behavior if (moving == false) { if (Math.random() < CHANCE_OF_MOVING) { targetPosition = randVector(-range, range); targetPosition = vPlus(targetPosition, myPosition); if (targetPosition.x < 0) { targetPosition.x = 0; } if (targetPosition.y < 0) { targetPosition.y = 0; } if (targetPosition.z < 0) { targetPosition.z = 0; } if (targetPosition.x > TREE_SCALE) { targetPosition.x = TREE_SCALE; } if (targetPosition.y > TREE_SCALE) { targetPosition.y = TREE_SCALE; } if (targetPosition.z > TREE_SCALE) { targetPosition.z = TREE_SCALE; } //printVector(position); moving = true; } } if (moving) { position = vInterpolate(position, targetPosition, 0.5); if (vLength(vMinus(position, targetPosition)) < (size / 5.0)) { moved = false; moving = false; } else { moved = true; } } if (moved || (tweeting > 0)) { if (tweeting > 0) { var newProperties = { position: position, radius : size * 1.5, color: { red: Math.random() * 255, green: 0, blue: 0 } }; } else { var newProperties = { position: position, radius : size, color: { red: color.r, green: color.g, blue: color.b } }; } Particles.editParticle(particleID, newProperties); moved = false; } } } // register the call back so it fires before each data send Script.update.connect(moveBird);