babylon-steering
Version:
Steering behaviours library for Babylon.js
309 lines (269 loc) • 13.3 kB
HTML
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Pursue, evade</title>
<script src="https://code.jquery.com/pep/0.4.2/pep.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/stats.js/r16/Stats.min.js"></script>
<script src="https://preview.babylonjs.com/babylon.js"></script>
<script src="../steering_two.js"></script>
<link rel="stylesheet" type="text/css" href="main.css">
</head>
<body>
<div class="container">
<!-- Sidebar -->
<aside>
<h3>Babylon-steer</h3>
<h4>Examples</h4>
<ul>
<li><a href="index.html">Seek, Flee, Avoid</a></li>
<li><a href="two.html">Pursue, Evade</a></li>
<li><a href="two.html">Interpose, Hide</a></li>
<li><a href="two.html">Follow path</a></li>
<li><a href="two.html">Wander</a></li>
<li><a href="two.html">Follow Leader</a></li>
<li><a href="two.html">Queue</a></li>
<!-- <li><a href="">Flock</a></li> -->
</ul>
</aside>
<!-- Main -->
<main style="flex: 1">
<canvas id="renderCanvas"></canvas>
<div id="info">
Red sphere <span style="color:red"> PURSUE</span> green box avoiding white box.
<br>
Blue sphere <span style="color:rgb(78, 78, 243);">EVADE</span> red sphere avoiding white box.
<br>
Drag <span style="color:green;">green box</span> with the mouse.
</div>
</main>
</div>
<script>
var container = document.querySelector('.container');
var canvas = document.getElementById("renderCanvas");
var engine = null;
var scene = null;
var createDefaultEngine = function () {
return new BABYLON.Engine(canvas, true, {
preserveDrawingBuffer: true,
stencil: true
});
};
var createScene = function () {
var scene = new BABYLON.Scene(engine);
scene.gravity = new BABYLON.Vector3(0, -9.81, 0);
scene.collisionsEnabled = true;
// scene.clearColor = new BABYLON.Color3(0, 0, 0);
var camera = new BABYLON.FreeCamera("camera1", new BABYLON.Vector3(0, 700, -600), scene);
camera.setTarget(BABYLON.Vector3.Zero());
var stats = new Stats();
stats.domElement.style.position = 'absolute';
stats.domElement.style.top = '0px';
stats.domElement.style.left = '180px'
stats.domElement.style.zIndex = 100;
container.appendChild(stats.domElement);
// Light
/* var light = new BABYLON.PointLight("omni", new BABYLON.Vector3(10, 100, 10), scene);
light.intensity = 2; */
// var HemisphericLight = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
// HemisphericLight.intensity = 0.05;
var light = new BABYLON.DirectionalLight("dir01", new BABYLON.Vector3(-1, -2, -1.5), scene);
light.position = new BABYLON.Vector3(20, 60, 50);
light.intensity = 0.35;
var shadowGenerator = new BABYLON.ShadowGenerator(1024, light);
// Ground
var ground = BABYLON.Mesh.CreateGround("ground", 5000, 5000, 1, scene, false);
var groundMaterial = new BABYLON.StandardMaterial("ground", scene);
groundMaterial.specularColor = BABYLON.Color3.Black();
ground.material = groundMaterial;
ground.checkCollisions = true;
function createActor(color, cone = false, scene) {
let sphere = BABYLON.Mesh.CreateSphere("sphere", 32, 20, scene);
let targetBox = BABYLON.MeshBuilder.CreateBox("targetBox", {
height: 10,
width: 5,
depth: 10,
updatable: true,
sideOrientation: BABYLON.Mesh.DOUBLESIDE
});
targetBox.parent = sphere;
targetBox.position = new BABYLON.Vector3(0, 0, 10);
let redMat = new BABYLON.StandardMaterial("grodefaultund", scene);
redMat.diffuseColor = new BABYLON.Color3(0.4, 0.4, 0.4);
redMat.specularColor = new BABYLON.Color3(0.4, 0.4, 0.4);
redMat.emissiveColor = color ? color : BABYLON.Color3.Red();
sphere.color = color;
sphere.material = redMat;
targetBox.material = redMat;
sphere.position.y = 10;
sphere.position.z = Math.random() * 350;
sphere.checkCollisions = true;
targetBox.checkCollisions = true;
sphere.isPickable = true;
targetBox.isPickable = false;
// cone of view
if (cone) {
var disc = BABYLON.MeshBuilder.CreateDisc("disc", { radius: 160, arc: 0.33, tessellation: 12, sideOrientation: BABYLON.Mesh.DOUBLESIDE }, scene);
var coneOfViewMat = new BABYLON.StandardMaterial("myMaterial", scene);
coneOfViewMat.diffuseColor = new BABYLON.Color3(0, 1, 0);
coneOfViewMat.alpha = 0.35;
disc.parent = sphere;
disc.rotation.x = Math.PI / 2;
disc.rotation.y = -Math.PI / 6;
disc.isPickable = false;
disc.material = coneOfViewMat;
}
return sphere;
}
function createElement(color, dimension = 20, scene) {
var element = BABYLON.Mesh.CreateBox("element", dimension, scene);
var greenMat = new BABYLON.StandardMaterial("default", scene);
greenMat.diffuseColor = new BABYLON.Color3(0.4, 0.4, 0.4);
greenMat.specularColor = new BABYLON.Color3(0.4, 0.4, 0.4);
greenMat.emissiveColor = color ? color : BABYLON.Color3.White();
element.material = greenMat;
element.position.x = Math.random() * 250 * (Math.random()<.5? -1 : 1);
element.position.z = Math.random() * 250 * (Math.random()<.5? -1 : 1);
element.position.y = dimension / 2;
element.checkCollisions = true;
return element;
}
var redSphere = createActor(BABYLON.Color3.Red(), true, scene);
var yellowSphere = createActor(BABYLON.Color3.Yellow(), false, scene);
var blueSphere = createActor(BABYLON.Color3.Blue(), false, scene);
// var whiteBox = createElement(BABYLON.Color3.White(), 50, scene);
var greenBox = createElement(BABYLON.Color3.Green(), 20, scene);
var obstacleIstances = [];
for (var index = 0; index < 10; index++) {
var newInstance = createElement(BABYLON.Color3.White(), 40, scene);
shadowGenerator.addShadowCaster(newInstance);
obstacleIstances.push(new SteeringVehicle(newInstance, engine));
}
var canvas = engine.getRenderingCanvas();
var startingPoint;
var currentMesh;
// STEERING ACTORS
redSphere = new SteeringVehicle(redSphere, engine);
yellowSphere = new SteeringVehicle(yellowSphere, engine);
blueSphere = new SteeringVehicle(blueSphere, engine);
greenBox = new SteeringVehicle(greenBox, engine);
/* whiteBox = new SteeringVehicle(whiteBox, engine, {
mass: 10
}); */
shadowGenerator.addShadowCaster(redSphere.mesh);
shadowGenerator.addShadowCaster(yellowSphere.mesh);
shadowGenerator.addShadowCaster(blueSphere.mesh);
shadowGenerator.addShadowCaster(greenBox.mesh);
// shadowGenerator.addShadowCaster(whiteBox.mesh);
ground.receiveShadows = true;
var gui = new dat.GUI();
var redSphereGUI = gui.addFolder("Red Shere");
redSphereGUI.add(redSphere, 'maxSpeed', .1, 1).name('Max Speed').step(.1);
redSphereGUI.add(redSphere, 'maxForce', .1, 2).name('Max Force').step(.1);
redSphereGUI.open();
var getGroundPosition = function () {
// Use a predicate to get position on the ground
var pickinfo = scene.pick(scene.pointerX, scene.pointerY, function (mesh) {
return mesh == ground;
});
if (pickinfo.hit) {
return pickinfo.pickedPoint;
}
return null;
}
var onPointerDown = function (evt) {
if (evt.button !== 0) {
let pos = getGroundPosition(evt);
pos.y = 10;
greenBox.waypoints.push(pos);
}
// check if we are under a mesh
var pickInfo = scene.pick(scene.pointerX, scene.pointerY, function (mesh) {
return mesh !== ground;
});
if (pickInfo.hit) {
currentMesh = pickInfo.pickedMesh;
startingPoint = getGroundPosition(evt);
if (startingPoint) { // we need to disconnect camera from canvas
setTimeout(function () {
camera.detachControl(canvas);
}, 0);
}
}
}
var onPointerUp = function () {
if (startingPoint) {
camera.attachControl(canvas, true);
startingPoint = null;
return;
}
}
var onPointerMove = function (evt) {
if (!startingPoint) {
return;
}
var current = getGroundPosition(evt);
if (!current) {
return;
}
var diff = current.subtract(startingPoint);
currentMesh.position.addInPlace(diff);
startingPoint = current;
}
canvas.addEventListener("pointerdown", onPointerDown, false);
canvas.addEventListener("pointerup", onPointerUp, false);
canvas.addEventListener("pointermove", onPointerMove, false);
scene.onDispose = function () {
canvas.removeEventListener("pointerdown", onPointerDown);
canvas.removeEventListener("pointerup", onPointerUp);
canvas.removeEventListener("pointermove", onPointerMove);
}
scene.executeWhenReady(function () {
engine.runRenderLoop(function () {
redSphere
.seekWithArrive(greenBox, 50)
.hasInConeOfView([blueSphere, yellowSphere])
.avoid(obstacleIstances)
// .applyForce(new BABYLON.Vector3(1, 0, 0.75))
.lookWhereGoing(true);
blueSphere
.seek(greenBox, 50, { weigth: 1.7, priority: 1, probability: 0.6 })
.flee(redSphere, 160, { weigth: 0.5, priority: 5, probability: 0.6 })
.lookTarget(redSphere)
//.lookWhereGoing(true)
.avoid(obstacleIstances, { weigth: 1, weigth: 0.8, probability: 0.6 });
//.isInConeOfViewOf(redSphere);
yellowSphere
.hide(redSphere, obstacleIstances)
.avoid(obstacleIstances)
.lookWhereGoing(true);
redSphere.animate();
blueSphere.animate('blend'); // 'blend' 'priority' 'probability' 'truncated'
yellowSphere.animate();
greenBox.animate();
// whiteBox.animate();
obstacleIstances.forEach(e => {
e.animate();
});
stats.update();
scene.render();
});
});
return scene;
};
engine = createDefaultEngine();
if (!engine) throw 'engine should not be null.';
scene = createScene();
engine.runRenderLoop(function () {
if (scene) {
scene.render();
}
});
// Resize
window.addEventListener("resize", function () {
engine.resize();
});
</script>
</body>
</html>