diff --git a/examples/libraries/createAvatarDetector.js b/examples/drylake/createAvatarDetector.js similarity index 100% rename from examples/libraries/createAvatarDetector.js rename to examples/drylake/createAvatarDetector.js diff --git a/examples/drylake/ratCreator.js b/examples/drylake/ratCreator.js new file mode 100644 index 0000000000..c907183de4 --- /dev/null +++ b/examples/drylake/ratCreator.js @@ -0,0 +1,371 @@ +Script.include('steer.js') +var steer = loadSteer(); +Script.include('tween.js'); +var TWEEN = loadTween(); + +var USE_CONSTANT_SPAWNER = false; + +var RAT_SPAWNER_LOCATION = { + x: 0, + y: 0, + z: 0 +}; + +var RAT_NEST_LOCATION = { + x: 0, + y: 0, + z: 0 +}; + +var RAT_MODEL_URL = ''; +var RAT_RUNNING_ANIMATION_URL = ''; +var RAT_DEATH_ANIMATION_URL = ''; + +var RAT_IN_NEST_DISTANCE = 0.25; + +//how many milliseconds between rats +var RAT_SPAWN_RATE = 1000; + + +function playRatRunningAnimation() { + var animationSettings = JSON.stringify({ + running: true + }); + Entities.editEntity(rat, { + animationURL: RAT_RUNNING_ANIMATION_URL, + animationSettings: animationSettings, + // animation: { + // url: RAT_RUNNING_ANIMATION_URL, + // running: true, + // fps: 180 + // }, + }); +} + +function playRatDeathAnimation() { + var animationSettings = JSON.stringify({ + running: true + }); + + Entities.editEntity(rat, { + animationURL: RAT_DEATH_ANIMATION_URL, + animationSettings: animationSettings, + // animation: { + // url: RAT_DEATH_ANIMATION_URL, + // running: true, + // fps: 180 + // }, + }); +} + +var ratProperties = { + name: 'Hifi-Rat', + type: 'Box', + color: { + red: 0, + green: 0, + blue: 255 + }, + dimensions: { + x: 1, + y: 1, + z: 1 + }, + position: RAT_SPAWNER_LOCATION +}; + +var modelRatProperties = { + name: 'Hifi-Rat', + type: 'Model', + dimensions: RAT_DIMENSIONS, + position: RAT_SPAWNER_LOCATION, + shapeType: 'Box', + collisionsWillMove: true, + gravity: { + x: 0, + y: -9.8 + z: 0 + }, + //enable this if for some reason we want grabbable rats + // userData:JSON.stringify({ + // grabbableKey:{ + // grabbable:false + // } + // }) + +}; + +var targetProperties = { + name: 'Hifi-Rat-Nest', + type: 'Box', + color: { + red: 0, + green: 255, + blue: 0 + }, + dimensions: { + x: 1, + y: 1, + z: 1 + }, + position: RAT_NEST_LOCATION + // script: Script.resolvePath('rat.js') +}; + +var target = Entities.addEntity(targetProperties) + +function addRat() { + var rat = Entities.addEntity(ratProperties); + rats.push(rat); +} + +var rats = []; +addRat(); + + +var FIRST_AVOIDER_START_POSITION = { + x: 0, + y: 0, + z: 0 +}; +var FIRST_AVOIDER_FINISH_POSITION = { + x: 0, + y: 0, + z: 0 +}; +var SECOND_AVOIDER_START_POSITION = { + x: 0, + y: 0, + z: 0 +}; +var SECOND_AVOIDER_FINISH_POSITION = { + x: 0, + y: 0, + z: 0 +}; +var THIRD_AVOIDER_START_POSITION = { + x: 0, + y: 0, + z: 0 +}; +var THIRD_AVOIDER_FINISH_POSITION = { + x: 0, + y: 0, + z: 0 +}; + +var avoiders = [ + addAvoiderBlock(FIRST_AVOIDER_START_POSITION), + addAvoiderBlock(SECOND_AVOIDER_START_POSITION), + addAvoiderBlock(THIRD_AVOIDER_START_POSITION) +]; + +function addAvoiderBlock(position) { + + var avoiderProperties = { + name: 'Hifi-Rat-Avoider', + type: 'Box', + color: { + red: 255, + green: 0, + blue: 255 + }, + dimensions: { + x: 1, + y: 1, + z: 1 + }, + position: { + x: 1, + y: 1, + z: 1 + }, + collisionsWillMove: false, + ignoreForCollisions: true + } + + var avoider = Entities.addEntity(avoiderProperties); + avoiders.push(avoider); +}; + +addAvoiderBlock(); +tweenAvoider(avoiders[0]); + +function tweenAvoider(entityID, startPosition, endPosition) { + var ANIMATION_DURATION = 500; + + var begin = { + x: startPosition.x, + y: startPosition.y, + z: startPosition.z + }; + + var target = endPosition; + + var original = startPosition; + + var tweenHead = new TWEEN.Tween(begin).to(target, ANIMATION_DURATION); + + function updateTo() { + Entities.editEntity(entityID, { + position: { + x: begin.x, + y: begin.y, + z: begin.z + } + }) + }; + + function updateBack() { + Entities.editEntity(entityID, { + position: { + x: begin.x, + y: begin.y, + z: begin.z + } + }) + }; + + var tweenBack = new TWEEN.Tween(begin).to(original, ANIMATION_DURATION).onUpdate(updateBack); + + tweenHead.onUpdate(function() { + updateTo() + }); + + tweenHead.chain(tweenBack); + tweenBack.chain(tweenHead); + tweenHead.start(); + +} + +function updateTweens() { + TWEEN.update(); +} + +function moveRats() { + rats.forEach(function(rat) { + // print('debug1') + + var avatarFlightVectors = steer.fleeAllAvatars(rat); + print('avatarFlightVectors' + avatarFlightVectors) + var i, j; + var averageAvatarFlight; + + for (i = 0; i < avatarFlightVectors.length; i++) { + if (i === 0) { + averageAvatarFlight = avatarFlightVectors[0]; + } else { + averageAvatarFlight = Vec3.sum(avatarFlightVectors[i - 1], avatarFlightVectors[i]) + } + } + + averageAvatarFlight = Vec3.normalize(averageAvatarFlight); + + averageAvatarFlight = Vec3.multiply(averageAvatarFlight, 1 / avatarFlightVectors.length); + + + var avoidBlockVectors = steer.fleeAvoiderBlocks(rat); + + var averageAvoiderFlight; + + for (j = 0; j < avoidBlockVectors.length; j++) { + if (j === 0) { + averageAvoiderFlight = avoidBlockVectors[0]; + } else { + averageAvoiderFlight = Vec3.sum(avoidBlockVectors[j - 1], avoidBlockVectors[j]) + } + }; + + avarageAvoiderFlight = Vec3.normalize(averageAvoiderFlight); + + averageAvoiderFlight = Vec3.multiply(averageAvoiderFlight, 1 / avoidBlockVectors.length); + + var averageVector; + var seek = steer.arrive(rat, target); + averageVector = seek; + var divisorCount = 1; + if (avatarFlightVectors.length > 0) { + divisorCount++; + averageVector = Vec3.sum(averageVector, averageAvatarFlight); + } + if (avoidBlockVectors > 0) { + divisorCount++; + averageVector = Vec3.sum(averageVector, averageAvoiderFlight); + } + + averageVector = Vec3.multiply(averageVector, 1 / divisorCount); + + Entities.editEntity(rat, { + velocity: averageVector + }) + + // castRay(rat); + + }) +} + +Script.update.connect(moveRats) +Script.update.connect(updateTweens); + +function checkDistanceFromNest(rat) { + var ratProps = Entitis.getEntityProperties(rat, "position"); + var distance = Vec3.distance(ratProps.position, RAT_NEST_LOCATION); + if (distance < RAT_IN_NEST_DISTANCE) { + removeRatFromScene(); + } +} + +function removeRatFromScene(rat) { + var index = rats.indexOf(rat); + if (index > -1) { + rats.splice(index, 1); + } + Entities.deleteEntity(rat); +} + + + +function cleanup() { + while (rats.length > 0) { + Entities.deleteEntity(rats.pop()); + } + + while (avoiders.length > 0) { + Entities.deleteEntity(avoiders.pop()); + } + + Entities.deleteEntity(target); + Script.update.disconnect(moveRats); + Script.update.disconnect(updateTweens); + Script.clearInterval(ratSpawnerInterval); +} + +Script.scriptEnding.connect(cleanup) + +var ratSpawnerInterval; + +if (USE_CONSTANT_SPAWNER === true) { + ratSpawnerInterval = Script.setInterval(function() { + addRat(); + }, RAT_SPAWN_RATE) +} + +//unused for now, to be used for some collision avoidance on walls and stuff? + +// function castRay(rat) { +// var ratProps = Entities.getEntityProperties(rat, ["position", "rotation"]); +// var shotDirection = Quat.getFront(ratProps.rotation); +// var pickRay = { +// origin: ratProps.position, +// direction: shotDirection +// }; + +// var intersection = Entities.findRayIntersection(pickRay, true); +// if (intersection.intersects) { +// var distance = Vec3.subtract(intersection.properties.position, ratProps.position); +// distance = Vec3.length(distance); +// // print('INTERSECTION:::'+distance); +// } else { +// //print('no intersection') +// } +// } \ No newline at end of file diff --git a/examples/libraries/steer.js b/examples/drylake/steer.js similarity index 93% rename from examples/libraries/steer.js rename to examples/drylake/steer.js index d7b1a8e295..b54d06b3e4 100644 --- a/examples/libraries/steer.js +++ b/examples/drylake/steer.js @@ -14,7 +14,7 @@ function seek(thisEntity, target) { var steerVector = new V3(desired.x, desired.y, desired.z); steer = steerVector.limit(MAX_FORCE) - return steer + return steer; } @@ -35,9 +35,9 @@ function flee(thisEntity, target) { var steer = Vec3.subtract(desired, velocity); var steerVector = new V3(desired.x, desired.y, desired.z); - steer = steerVector.limit(MAX_FORCE) + steer = steerVector.limit(MAX_FORCE); - return steer + return steer; } else { // print('target too far away to flee' + d); return @@ -59,7 +59,7 @@ function fleeAvatar(thisEntity, avatarPosition) { var steer = Vec3.subtract(desired, velocity); var steerVector = new V3(desired.x, desired.y, desired.z); - steer = steerVector.limit(MAX_FORCE) + steer = steerVector.limit(MAX_FORCE); return steer } else { // print('target too far away to flee' + d); @@ -69,13 +69,13 @@ function fleeAvatar(thisEntity, avatarPosition) { } function fleeAllAvatars(thisEntity) { - print('FLEE AVATARS') + print('FLEE AVATARS'); var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); var location = properties.position; var velocity = properties.velocity; var nearbyEntities = Entities.findEntities(location, 3); - var flightVectors = [] + var flightVectors = []; for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { var entityID = nearbyEntities[entityIndex]; var entityProps = Entities.getEntityProperties(entityID); @@ -97,8 +97,6 @@ function fleeAllAvatars(thisEntity) { } else { print('target too far away from this avatar to flee' + d); } - - } } @@ -107,26 +105,27 @@ function fleeAllAvatars(thisEntity) { } function fleeAvoiderBlocks(thisEntity) { + print('FLEE AVOIDER BLOCKS'); var properties = Entities.getEntityProperties(thisEntity, ["position", "velocity"]); var location = properties.position; var velocity = properties.velocity; - var nearbyEntities = Entities.findEntities(location, 2); - var flightVectors = [] + var nearbyEntities = Entities.findEntities(location, 3); + var flightVectors = []; for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) { var entityID = nearbyEntities[entityIndex]; var entityProps = Entities.getEntityProperties(entityID); if (entityProps.name === 'Hifi-Rat-Avoider') { - print('found an avatar to flee') + print('found an avoiderblock to flee'); var MAX_SPEED = 2; - var MAX_FORCE = 2; + var MAX_FORCE = 0.8; var desired = Vec3.subtract(location, entityProps.position); var d = Vec3.length(desired); desired = Vec3.normalize(desired); desired = Vec3.multiply(MAX_SPEED, desired); - if (d < 2) { + if (d < 3) { var steer = Vec3.subtract(desired, velocity); var steerVector = new V3(desired.x, desired.y, desired.z); steer = steerVector.limit(MAX_FORCE) @@ -134,8 +133,6 @@ function fleeAvoiderBlocks(thisEntity) { } else { print('target too far away from this avoider to flee' + d); } - - } } @@ -153,7 +150,6 @@ function arrive(thisEntity, target) { var MAX_FORCE = 2; var ARRIVAL_DISTANCE = 3; - var desired = Vec3.subtract(targetPosition, location); var d = Vec3.length(desired); desired = Vec3.normalize(desired); @@ -211,7 +207,7 @@ loadSteer = function() { flee: flee, fleeAvatar: fleeAvatar, fleeAllAvatars: fleeAllAvatars, - // fleeAvoiderBlocks:fleeAvoiderBlocks, + fleeAvoiderBlocks:fleeAvoiderBlocks, arrive: arrive } } \ No newline at end of file diff --git a/examples/libraries/ratTest.js b/examples/libraries/ratTest.js index 80c861a1e9..c173de6f2b 100644 --- a/examples/libraries/ratTest.js +++ b/examples/libraries/ratTest.js @@ -1,8 +1,26 @@ -Script.include('steer.js') +Script.include('steer.js'); var steer = loadSteer(); Script.include('tween.js'); var TWEEN = loadTween(); +var RAT_NEST_LOCATION = { + x: 0, + y: 0, + z: 0 +}; + +var RAT_SPAWNER_LOCATION = { + x: 0, + y: 0, + z: 0 +}; + +var AVOIDER_BLOCK_START_LOCATION = { + x: 0, + y: 0, + z: 0 +}; + var ratProperties = { name: 'Hifi-Rat-Nest', type: 'Box', @@ -16,11 +34,7 @@ var ratProperties = { y: 1, z: 1 }, - position: { - x: 0, - y: 0, - z: 0 - } + position: RAT_SPAWNER_LOCATION }; var targetProperties = { @@ -36,11 +50,7 @@ var targetProperties = { y: 1, z: 1 }, - position: { - x: 5, - y: 0, - z: 0 - } + position: RAT_NEST_LOCATION // script: Script.resolvePath('rat.js') }; @@ -75,12 +85,16 @@ function addAvoiderBlock() { x: 1, y: 1, z: 1 - } + }, + collisionsWillMove:false, + ignoreForCollisions:true, + visible: true } var avoider = Entities.addEntity(avoiderProperties); avoiders.push(avoider) } + addAvoiderBlock(); tweenAvoider(avoiders[0]);