Needs a lot of cleanup. Data has been de-duplicated, and where identical copies existed, one of them has been replaced with a symlink. Some files have been excluded, such as binaries, installers and debug dumps. Some of that may still be present.
469 lines
23 KiB
JavaScript
469 lines
23 KiB
JavaScript
//
|
|
// flockingBirds.js
|
|
// examples
|
|
//
|
|
// Created by Brad Hefta-Gaub on 3/4/14.
|
|
// Copyright 2014 High Fidelity, Inc.
|
|
//
|
|
// This is an example script that generates particles that act like flocking birds
|
|
//
|
|
// All birds, even flying solo...
|
|
// birds don't like to fall too fast
|
|
// if they fall to fast, they will go into a state of thrusting up, until they reach some max upward velocity, then
|
|
// go back to gliding
|
|
// birds don't like to be below a certain altitude
|
|
// if they are below that altitude they will keep thrusting up, until they get ove
|
|
//
|
|
// flocking
|
|
// try to align your velocity with velocity of other birds
|
|
// try to fly toward center of flock
|
|
// but dont get too close
|
|
//
|
|
//
|
|
// Distributed under the Apache License, Version 2.0.
|
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
//
|
|
|
|
var birdsInFlock = 20;
|
|
|
|
var birdLifetime = 300; // 1 minute
|
|
var count=0; // iterations
|
|
|
|
var enableFlyTowardPoints = true; // some birds have a point they want to fly to
|
|
var enabledClustedFlyTowardPoints = true; // the flyToward points will be generally near each other
|
|
var flyToFrames = 100; // number of frames the bird would like to attempt to fly to it's flyTo point
|
|
var PROBABILITY_OF_FLY_TOWARD_CHANGE = 0.01; // chance the bird will decide to change its flyTo point
|
|
var PROBABILITY_EACH_BIRD_WILL_FLY_TOWARD = 0.2; // chance the bird will decide to flyTo, otherwise it follows
|
|
var flyingToCount = 0; // count of birds currently flying to someplace
|
|
var flyToCluster = { }; // the point that the cluster of flyTo points is based on when in enabledClustedFlyTowardPoints
|
|
|
|
// Bird behaviors
|
|
var enableAvoidDropping = true; // birds will resist falling too fast, and will thrust up if falling
|
|
var enableAvoidMinHeight = true; // birds will resist being below a certain height and thrust up to get above it
|
|
var enableAvoidMaxHeight = true; // birds will resist being above a certain height and will glide to get below it
|
|
var enableMatchFlockVelocity = true; // birds will thrust to match the flocks average velocity
|
|
var enableThrustTowardCenter = true; // birds will thrust to try to move toward the center of the flock
|
|
var enableAvoidOtherBirds = true; // birds will thrust away from all other birds
|
|
var startWithVelocity = true;
|
|
var flockGravity = { x: 0, y: -1, z: 0};
|
|
|
|
// NOTE: these two features don't seem to be very interesting, they cause odd behaviors
|
|
var enableRandomXZThrust = false; // leading birds randomly decide to thrust in some random direction.
|
|
var enableSomeBirdsLead = false; // birds randomly decide not fly toward flock, causing other birds to follow
|
|
var leaders = 0; // number of birds leading
|
|
var PROBABILITY_TO_LEAD = 0.1; // probability a bird will choose to lead
|
|
|
|
var birds = new Array(); // array of bird state data
|
|
|
|
|
|
var flockStartPosition = MyAvatar.position;
|
|
var flockStartVelocity = { x: 0, y: 0, z: 0};
|
|
var flockStartThrust = { x: 0, y: 0, z: 0}; // slightly upward against gravity
|
|
var INITIAL_XY_VELOCITY_SCALE = 2;
|
|
var birdRadius = 0.2;
|
|
var baseBirdColor = { red: 0, green: 255, blue: 255 };
|
|
var glidingColor = { red: 255, green: 0, blue: 0 };
|
|
var thrustUpwardColor = { red: 0, green: 255, blue: 0 };
|
|
var thrustXYColor = { red: 128, green: 0, blue: 128 }; // will be added to any other color
|
|
var leadingOrflyToColor = { red: 200, green: 200, blue: 255 };
|
|
|
|
var tooClose = birdRadius * 3; // how close birds are willing to be to each other
|
|
var droppingTooFast = -1; // birds don't like to fall too fast
|
|
var risingTooFast = 1; // birds don't like to climb too fast
|
|
var upwardThrustAgainstGravity = -10; // how hard a bird will attempt to thrust up to avoid downward motion
|
|
var droppingAdjustFrames = 5; // birds try to correct their min height in only a couple frames
|
|
var minHeight = 10; // meters off the ground
|
|
var maxHeight = 50; // meters off the ground
|
|
var adjustFrames = 10; // typical number of frames a bird will assume for it's adjustments
|
|
var PROBABILITY_OF_RANDOM_XZ_THRUST = 0.25;
|
|
var RANDOM_XZ_THRUST_SCALE = 5; // random -SCALE...to...+SCALE in X or Z direction
|
|
var MAX_XY_VELOCITY = 10;
|
|
|
|
// These are multiplied by every frame since a change. so after 50 frames, there's a 50% probability of change
|
|
var PROBABILITY_OF_STARTING_XZ_THRUST = 0.0025;
|
|
var PROBABILITY_OF_STOPPING_XZ_THRUST = 0.01;
|
|
|
|
var FLY_TOWARD_XZ_DISTANCE = 100;
|
|
var FLY_TOWARD_Y_DISTANCE = 0;
|
|
var FLY_TOWARD_XZ_CLUSTER_DELTA = 5;
|
|
var FLY_TOWARD_Y_CLUSTER_DELTA = 0;
|
|
|
|
function createBirds() {
|
|
if (enabledClustedFlyTowardPoints) {
|
|
flyToCluster = { x: flockStartPosition.x + Math.random() * FLY_TOWARD_XZ_DISTANCE,
|
|
y: flockStartPosition.y + Math.random() * FLY_TOWARD_Y_DISTANCE,
|
|
z: flockStartPosition.z + Math.random() * FLY_TOWARD_XZ_DISTANCE};
|
|
}
|
|
|
|
for(var i =0; i < birdsInFlock; i++) {
|
|
var velocity;
|
|
|
|
position = Vec3.sum(flockStartPosition, { x: Math.random(), y: Math.random(), z: Math.random() }); // add random
|
|
|
|
var flyingToward = position;
|
|
var isFlyingToward = false;
|
|
if (enableFlyTowardPoints) {
|
|
if (Math.random() < PROBABILITY_EACH_BIRD_WILL_FLY_TOWARD) {
|
|
flyingToCount++;
|
|
isFlyingToward = true;
|
|
if (enabledClustedFlyTowardPoints) {
|
|
flyingToward = { x: flyToCluster.x + Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA,
|
|
y: flyToCluster.y + Math.random() * FLY_TOWARD_Y_CLUSTER_DELTA,
|
|
z: flyToCluster.z + Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA};
|
|
} else {
|
|
flyingToward = { x: flockStartPosition.x + Math.random() * FLY_TOWARD_XZ_DISTANCE,
|
|
y: flockStartPosition.y + Math.random() * FLY_TOWARD_Y_DISTANCE,
|
|
z: flockStartPosition.z + Math.random() * FLY_TOWARD_XZ_DISTANCE};
|
|
}
|
|
}
|
|
|
|
Vec3.print("birds["+i+"].flyingToward=",flyingToward);
|
|
}
|
|
|
|
birds[i] = {
|
|
particle: {},
|
|
properties: {},
|
|
thrust: Vec3.sum(flockStartThrust, { x:0, y: 0, z: 0 }),
|
|
gliding: true,
|
|
xzThrust: { x:0, y: 0, z: 0},
|
|
xzthrustCount: 0,
|
|
isLeading: false,
|
|
flyingToward: flyingToward,
|
|
isFlyingToward: isFlyingToward,
|
|
};
|
|
|
|
if (enableSomeBirdsLead) {
|
|
if (Math.random() < PROBABILITY_TO_LEAD) {
|
|
birds[i].isLeading = true;
|
|
}
|
|
if (leaders == 0 && i == (birdsInFlock-1)) {
|
|
birds[i].isLeading = true;
|
|
}
|
|
if (birds[i].isLeading) {
|
|
leaders++;
|
|
velocity = { x: 2, y: 0, z: 2};
|
|
print(">>>>>>THIS BIRD LEADS!!!! i="+i);
|
|
}
|
|
}
|
|
|
|
if (startWithVelocity) {
|
|
velocity = Vec3.sum(flockStartVelocity, { x: (Math.random() * INITIAL_XY_VELOCITY_SCALE),
|
|
y: 0,
|
|
z: (Math.random() * INITIAL_XY_VELOCITY_SCALE) }); // add random
|
|
} else {
|
|
velocity = { x: 0, y: 0, z: 0};
|
|
}
|
|
birds[i].particle = Entities.addEntity({
|
|
type: "Sphere",
|
|
position: position,
|
|
velocity: velocity,
|
|
gravity: flockGravity,
|
|
damping: 0,
|
|
dimensions: { x: birdRadius, y: birdRadius, z: birdRadius},
|
|
color: baseBirdColor,
|
|
lifetime: birdLifetime
|
|
});
|
|
|
|
}
|
|
print("flyingToCount=" + flyingToCount);
|
|
}
|
|
|
|
var wantDebug = false;
|
|
function updateBirds(deltaTime) {
|
|
count++;
|
|
|
|
// get all our bird properties, and calculate the current flock velocity
|
|
var averageVelocity = { x: 0, y: 0, z: 0};
|
|
var averagePosition = { x: 0, y: 0, z: 0};
|
|
var knownBirds = 0;
|
|
for(var i =0; i < birdsInFlock; i++) {
|
|
// identifyParticle() will check to see that the particle handle we have is in sync with the domain/server
|
|
// context. If the handle is for a created particle that now has a known ID it will be updated to be a
|
|
// handle with a known ID.
|
|
birds[i].particle = Entities.identifyEntity(birds[i].particle);
|
|
|
|
if (birds[i].particle.isKnownID) {
|
|
birds[i].properties = Entities.getEntityProperties(birds[i].particle);
|
|
if (birds[i].properties.isKnownID) {
|
|
knownBirds++;
|
|
averageVelocity = Vec3.sum(averageVelocity, birds[i].properties.velocity);
|
|
averagePosition = Vec3.sum(averagePosition, birds[i].properties.position);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (knownBirds == 0 && count > 100) {
|
|
Script.stop();
|
|
return;
|
|
}
|
|
averageVelocity = Vec3.multiply(averageVelocity, (1 / Math.max(1, knownBirds)));
|
|
averagePosition = Vec3.multiply(averagePosition, (1 / Math.max(1, knownBirds)));
|
|
|
|
if (wantDebug) {
|
|
Vec3.print("averagePosition=",averagePosition);
|
|
Vec3.print("averageVelocity=",averageVelocity);
|
|
print("knownBirds="+knownBirds);
|
|
}
|
|
|
|
var flyToClusterChanged = false;
|
|
if (enabledClustedFlyTowardPoints) {
|
|
if (Math.random() < PROBABILITY_OF_FLY_TOWARD_CHANGE) {
|
|
flyToClusterChanged = true;
|
|
flyToCluster = { x: averagePosition.x + (Math.random() * FLY_TOWARD_XZ_DISTANCE) - FLY_TOWARD_XZ_DISTANCE/2,
|
|
y: averagePosition.y + (Math.random() * FLY_TOWARD_Y_DISTANCE) - FLY_TOWARD_Y_DISTANCE/2,
|
|
z: averagePosition.z + (Math.random() * FLY_TOWARD_XZ_DISTANCE) - FLY_TOWARD_XZ_DISTANCE/2};
|
|
}
|
|
}
|
|
|
|
// iterate all birds again, adjust their thrust for various goals
|
|
for(var i =0; i < birdsInFlock; i++) {
|
|
|
|
birds[i].thrust = { x: 0, y: 0, z: 0 }; // assume no thrust...
|
|
|
|
if (birds[i].particle.isKnownID) {
|
|
|
|
if (enableFlyTowardPoints) {
|
|
// if we're flying toward clusters, and the cluster changed, and this bird is flyingToward
|
|
// then we need to update it's flyingToward
|
|
if (enabledClustedFlyTowardPoints && flyToClusterChanged && birds[i].isFlyingToward) {
|
|
flyingToward = { x: flyToCluster.x + (Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA) - FLY_TOWARD_XZ_CLUSTER_DELTA/2,
|
|
y: flyToCluster.y + (Math.random() * FLY_TOWARD_Y_CLUSTER_DELTA) - FLY_TOWARD_Y_CLUSTER_DELTA/2,
|
|
z: flyToCluster.z + (Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA) - FLY_TOWARD_XZ_CLUSTER_DELTA/2};
|
|
birds[i].flyingToward = flyingToward;
|
|
}
|
|
|
|
// there a random chance this bird will decide to change it's flying toward state
|
|
if (Math.random() < PROBABILITY_OF_FLY_TOWARD_CHANGE) {
|
|
var wasFlyingTo = birds[i].isFlyingToward;
|
|
|
|
// there's some chance it will decide it should be flying toward
|
|
if (Math.random() < PROBABILITY_EACH_BIRD_WILL_FLY_TOWARD) {
|
|
|
|
// if we're flying toward clustered points, then we randomize from the cluster, otherwise we pick
|
|
// completely random places based on flocks current averagePosition
|
|
if (enabledClustedFlyTowardPoints) {
|
|
flyingToward = { x: flyToCluster.x + (Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA) - FLY_TOWARD_XZ_CLUSTER_DELTA/2,
|
|
y: flyToCluster.y + (Math.random() * FLY_TOWARD_Y_CLUSTER_DELTA) - FLY_TOWARD_Y_CLUSTER_DELTA/2,
|
|
z: flyToCluster.z + (Math.random() * FLY_TOWARD_XZ_CLUSTER_DELTA) - FLY_TOWARD_XZ_CLUSTER_DELTA/2};
|
|
} else {
|
|
flyingToward = { x: averagePosition.x + (Math.random() * FLY_TOWARD_XZ_DISTANCE) - FLY_TOWARD_XZ_DISTANCE/2,
|
|
y: averagePosition.y + (Math.random() * FLY_TOWARD_Y_DISTANCE) - FLY_TOWARD_Y_DISTANCE/2,
|
|
z: averagePosition.z + (Math.random() * FLY_TOWARD_XZ_DISTANCE) - FLY_TOWARD_XZ_DISTANCE/2};
|
|
}
|
|
birds[i].flyingToward = flyingToward;
|
|
birds[i].isFlyingToward = true;
|
|
} else {
|
|
birds[i].flyingToward = {};
|
|
birds[i].isFlyingToward = false;
|
|
}
|
|
|
|
// keep track of our bookkeeping
|
|
if (!wasFlyingTo && birds[i].isFlyingToward) {
|
|
flyingToCount++;
|
|
}
|
|
if (wasFlyingTo && !birds[i].isFlyingToward) {
|
|
flyingToCount--;
|
|
}
|
|
print(">>>> CHANGING flyingToCount="+flyingToCount);
|
|
if (birds[i].isFlyingToward) {
|
|
Vec3.print("... now birds["+i+"].flyingToward=", birds[i].flyingToward);
|
|
}
|
|
}
|
|
|
|
// actually apply the thrust after all that
|
|
if (birds[i].isFlyingToward) {
|
|
var flyTowardDelta = Vec3.subtract(birds[i].flyingToward, birds[i].properties.position);
|
|
var thrustTowardFlyTo = Vec3.multiply(flyTowardDelta, 1/flyToFrames);
|
|
birds[i].thrust = Vec3.sum(birds[i].thrust, thrustTowardFlyTo);
|
|
}
|
|
}
|
|
|
|
|
|
// adjust thrust to avoid dropping to fast
|
|
if (enableAvoidDropping) {
|
|
if (birds[i].gliding) {
|
|
if (birds[i].properties.velocity.y < droppingTooFast) {
|
|
birds[i].gliding = false; // leave thrusting against gravity till it gets too high
|
|
//print("birdGliding["+i+"]=false <<<< try to conteract gravity <<<<<<<<<<<<<<<<<<<<");
|
|
}
|
|
}
|
|
}
|
|
|
|
// if the bird is currently not gliding, check to see if it's rising too fast
|
|
if (!birds[i].gliding && birds[i].properties.velocity.y > risingTooFast) {
|
|
//Vec3.print("bird rising too fast will glide bird["+i+"]=",birds[i].properties.velocity.y);
|
|
birds[i].gliding = true;
|
|
}
|
|
|
|
// adjust thrust to avoid minHeight, we don't care about rising too fast in this case, so we do it
|
|
// after the rising too fast check
|
|
if (enableAvoidMinHeight) {
|
|
if (birds[i].properties.position.y < minHeight) {
|
|
//Vec3.print("**** enableAvoidMinHeight... enable thrust against gravity... bird["+i+"].position=",birds[i].properties.position);
|
|
birds[i].gliding = false;
|
|
}
|
|
}
|
|
|
|
// adjust thrust to avoid maxHeight
|
|
if (enableAvoidMaxHeight) {
|
|
if (birds[i].properties.position.y > maxHeight) {
|
|
//Vec3.print("********************* bird above max height will glide bird["+i+"].position=",birds[i].properties.position);
|
|
birds[i].gliding = true;
|
|
}
|
|
}
|
|
|
|
// if the bird is currently not gliding, then it is applying a thrust upward against gravity
|
|
if (!birds[i].gliding) {
|
|
// as long as we're not rising too fast, keep thrusting...
|
|
if (birds[i].properties.velocity.y < risingTooFast) {
|
|
var thrustAdjust = {x: 0, y: (flockGravity.y * upwardThrustAgainstGravity), z: 0};
|
|
//Vec3.print("bird fighting gravity thrustAdjust for bird["+i+"]=",thrustAdjust);
|
|
birds[i].thrust = Vec3.sum(birds[i].thrust, thrustAdjust);
|
|
} else {
|
|
//print("%%% non-gliding bird, thrusting too much...");
|
|
}
|
|
}
|
|
|
|
if (enableRandomXZThrust && birds[i].isLeading) {
|
|
birds[i].xzThrustCount++;
|
|
|
|
// we will randomly decide to enable XY thrust, in which case we will set the thrust and leave it
|
|
// that way till we randomly shut it off.
|
|
|
|
// if we don't have a thrust, check against probability of starting it, and create a random thrust if
|
|
// probability occurs
|
|
if (Vec3.length(birds[i].xzThrust) == 0) {
|
|
var probabilityToStart = (PROBABILITY_OF_STARTING_XZ_THRUST * birds[i].xzThrustCount);
|
|
//print("probabilityToStart=" + probabilityToStart);
|
|
if (Math.random() < probabilityToStart) {
|
|
var xThrust = (Math.random() * (RANDOM_XZ_THRUST_SCALE * 2)) - RANDOM_XZ_THRUST_SCALE;
|
|
var zThrust = (Math.random() * (RANDOM_XZ_THRUST_SCALE * 2)) - RANDOM_XZ_THRUST_SCALE;
|
|
|
|
birds[i].xzThrust = { x: zThrust, y: 0, z: zThrust };
|
|
birds[i].xzThrustCount = 0;
|
|
//Vec3.print(">>>>>>>>>> STARTING XY THRUST birdXYthrust["+i+"]=", birds[i].xzThrust);
|
|
}
|
|
}
|
|
|
|
// if we're thrusting... then check for probability of stopping
|
|
if (Vec3.length(birds[i].xzThrust)) {
|
|
var probabilityToStop = (PROBABILITY_OF_STOPPING_XZ_THRUST * birds[i].xzThrustCount);
|
|
//print("probabilityToStop=" + probabilityToStop);
|
|
if (Math.random() < probabilityToStop) {
|
|
birds[i].xzThrust = { x: 0, y: 0, z: 0};
|
|
//Vec3.print(">>>>>>>>>> STOPPING XY THRUST birdXYthrust["+i+"]=", birds[i].xzThrust);
|
|
birds[i].xzThrustCount = 0;
|
|
}
|
|
|
|
if (birds[i].properties.velocity.x > MAX_XY_VELOCITY) {
|
|
birds[i].xzThrust.x = 0;
|
|
//Vec3.print(">>>>>>>>>> CLEARING X THRUST birdXYthrust["+i+"]=", birds[i].xzThrust);
|
|
}
|
|
if (birds[i].properties.velocity.z > MAX_XY_VELOCITY) {
|
|
birds[i].xzThrust.z = 0;
|
|
//Vec3.print(">>>>>>>>>> CLEARING Y THRUST birdXYthrust["+i+"]=", birds[i].xzThrust);
|
|
}
|
|
|
|
if (Vec3.length(birds[i].xzThrust)) {
|
|
birds[i].thrust = Vec3.sum(birds[i].thrust, birds[i].xzThrust);
|
|
}
|
|
}
|
|
}
|
|
|
|
// adjust thrust to move their velocity toward average flock velocity
|
|
if (enableMatchFlockVelocity) {
|
|
if (birds[i].isLeading) {
|
|
print("this bird is leading... i="+i);
|
|
} else {
|
|
var velocityDelta = Vec3.subtract(averageVelocity, birds[i].properties.velocity);
|
|
var thrustAdjust = velocityDelta;
|
|
birds[i].thrust = Vec3.sum(birds[i].thrust, thrustAdjust);
|
|
}
|
|
}
|
|
|
|
// adjust thrust to move their velocity toward average flock position
|
|
if (enableThrustTowardCenter) {
|
|
if (birds[i].isLeading) {
|
|
print("this bird is leading... i="+i);
|
|
} else {
|
|
var positionDelta = Vec3.subtract(averagePosition, birds[i].properties.position);
|
|
var thrustTowardCenter = Vec3.multiply(positionDelta, 1/adjustFrames);
|
|
birds[i].thrust = Vec3.sum(birds[i].thrust, thrustTowardCenter);
|
|
}
|
|
}
|
|
|
|
|
|
// adjust thrust to avoid other birds
|
|
if (enableAvoidOtherBirds) {
|
|
var sumThrustThisBird = { x: 0, y: 0, z: 0 };
|
|
|
|
for(var j =0; j < birdsInFlock; j++) {
|
|
|
|
// if this is not me, and a known bird, then check our position
|
|
if (birds[i].properties.isKnownID && j != i) {
|
|
var positionMe = birds[i].properties.position;
|
|
var positionYou = birds[j].properties.position;
|
|
var awayFromYou = Vec3.subtract(positionMe, positionYou); // vector pointing away from "you"
|
|
var distance = Vec3.length(awayFromYou);
|
|
if (distance < tooClose) {
|
|
// NOTE: this was Philip's recommendation for "avoiding" other birds...
|
|
// Vme -= Vec3.multiply(Vme, normalize(PositionMe - PositionYou))
|
|
//
|
|
// But it doesn't seem to work... Here's my JS implementation...
|
|
//
|
|
// var velocityMe = birds[i].properties.velocity;
|
|
// var thrustAdjust = Vec3.cross(velocityMe, Vec3.normalize(awayFromYou));
|
|
// sumThrustThisBird = Vec3.sum(sumThrustThisBird, thrustAdjust);
|
|
//
|
|
// Instead I just apply a thrust equal to the vector away from all the birds
|
|
sumThrustThisBird = Vec3.sum(sumThrustThisBird, awayFromYou);
|
|
}
|
|
}
|
|
}
|
|
birds[i].thrust = Vec3.sum(birds[i].thrust, sumThrustThisBird);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// iterate all birds again, apply their thrust
|
|
for(var i =0; i < birdsInFlock; i++) {
|
|
if (birds[i].particle.isKnownID) {
|
|
|
|
var color;
|
|
if (birds[i].gliding) {
|
|
color = glidingColor;
|
|
} else {
|
|
color = thrustUpwardColor;
|
|
}
|
|
if (Vec3.length(birds[i].xzThrust)) {
|
|
color = Vec3.sum(color, thrustXYColor);
|
|
}
|
|
|
|
var velocityMe = birds[i].properties.velocity;
|
|
// add thrust to velocity
|
|
var newVelocity = Vec3.sum(velocityMe, Vec3.multiply(birds[i].thrust, deltaTime));
|
|
|
|
if (birds[i].isLeading || birds[i].isFlyingToward) {
|
|
Vec3.print("this bird is leading/flying toward... i="+i+" velocity=",newVelocity);
|
|
color = leadingOrflyToColor;
|
|
}
|
|
|
|
if (wantDebug) {
|
|
Vec3.print("birds["+i+"].position=", birds[i].properties.position);
|
|
Vec3.print("birds["+i+"].oldVelocity=", velocityMe);
|
|
Vec3.print("birdThrusts["+i+"]=", birds[i].thrust);
|
|
Vec3.print("birds["+i+"].newVelocity=", newVelocity);
|
|
}
|
|
|
|
birds[i].particle = Entities.editEntity(birds[i].particle,{ velocity: newVelocity, color: color });
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
createBirds();
|
|
// register the call back for simulation loop
|
|
Script.update.connect(updateBirds);
|
|
|