231 lines
11 KiB
JavaScript
231 lines
11 KiB
JavaScript
const BOX_SIZE = 1
|
|
const BOX_DEPTH = 4
|
|
const GROUND_SIZE = 50
|
|
const colors = {
|
|
seaFoam: BABYLON.Color3.FromHexString("#16a085"),
|
|
green: BABYLON.Color3.FromHexString("#27ae60"),
|
|
blue: BABYLON.Color3.FromHexString("#2980b9"),
|
|
purple: BABYLON.Color3.FromHexString("#8e44ad"),
|
|
navy: BABYLON.Color3.FromHexString("#2c3e50"),
|
|
yellow: BABYLON.Color3.FromHexString("#f39c12"),
|
|
orange: BABYLON.Color3.FromHexString("#d35400"),
|
|
red: BABYLON.Color3.FromHexString("#c0392b"),
|
|
white: BABYLON.Color3.FromHexString("#bdc3c7"),
|
|
gray: BABYLON.Color3.FromHexString("#7f8c8d")
|
|
}
|
|
|
|
const SHAPES = ["I", "O", "S", "T", "L"]
|
|
var BODIES = { "I": {}, "O": {}, "S": {}, "T": {}, "L": {} }
|
|
|
|
var canvas = document.getElementById("renderCanvas");
|
|
var engine = null;
|
|
var scene = null;
|
|
var sceneToRender = null;
|
|
var createDefaultEngine = ()=>{
|
|
return new BABYLON.Engine(canvas, true, { preserveDrawingBuffer: true, stencil:true}); };
|
|
|
|
var createScene = async ()=> {
|
|
var scene = new BABYLON.Scene(engine);
|
|
scene.clearColor = colors.navy;
|
|
scene.enablePhysics(null, new BABYLON.AmmoJSPlugin());
|
|
//CAMERA
|
|
var camera = new BABYLON.ArcRotateCamera("Camera", Math.PI / 2, Math.PI / 2.5, 25, BABYLON.Vector3.Zero(), scene);
|
|
camera.attachControl(canvas, true);
|
|
camera.setPosition(new BABYLON.Vector3(GROUND_SIZE / 2, GROUND_SIZE / 2, GROUND_SIZE / 2))
|
|
//LIGHT
|
|
var light = new BABYLON.DirectionalLight("dir02", new BABYLON.Vector3(0.2, -1, 0), scene);
|
|
light.position = new BABYLON.Vector3(0, GROUND_SIZE, 0);
|
|
light.intensity = 0.9
|
|
shadowGenerator = new BABYLON.ShadowGenerator(2048, light);
|
|
|
|
//MATERIAL
|
|
BODIES["O"].material = createMat(scene, colors.purple)
|
|
BODIES["I"].material = createMat(scene, colors.red)
|
|
BODIES["L"].material = createMat(scene, colors.yellow)
|
|
BODIES["T"].material = createMat(scene, colors.green)
|
|
BODIES["S"].material = createMat(scene, colors.orange)
|
|
|
|
var grass = new BABYLON.StandardMaterial("grass", scene);
|
|
grass.diffuseTexture = new BABYLON.Texture("https://images.pexels.com/photos/3038740/pexels-photo-3038740.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500");
|
|
grass.diffuseTexture.uScale = 5;
|
|
grass.diffuseTexture.vScale = 5;
|
|
|
|
var ground = BABYLON.MeshBuilder.CreateBox("ground", { width: GROUND_SIZE, depth: GROUND_SIZE, height: 1 }, scene);
|
|
ground.material = grass;
|
|
ground.receiveShadows = true;
|
|
ground.physicsImpostor = new BABYLON.PhysicsImpostor(ground, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 0, friction: 0.5, restitution: 0 }, scene);
|
|
|
|
var ticker = 0;
|
|
|
|
scene.registerBeforeRender(function() {
|
|
if((ticker++ % 60)) return;
|
|
for (var ii = 0; ii < 10; ii++) {
|
|
let nextChar = SHAPES[randomInteger(0, SHAPES.length)]
|
|
getBody(nextChar, scene, new BABYLON.Vector3(randomInteger(-GROUND_SIZE/2,GROUND_SIZE/2),
|
|
GROUND_SIZE/2,
|
|
randomInteger(-GROUND_SIZE/2,GROUND_SIZE/2)))
|
|
}
|
|
});
|
|
scene.registerBeforeRender( ()=> {
|
|
scene.meshes.forEach( (m)=> {
|
|
if (m.name=="s" && m.position.y < -10) {
|
|
m.dispose();
|
|
}
|
|
})
|
|
});
|
|
|
|
|
|
scene.onKeyboardObservable.add((kbInfo) => {
|
|
switch (kbInfo.type) {
|
|
case BABYLON.KeyboardEventTypes.KEYDOWN:
|
|
switch (kbInfo.event.keyCode) {
|
|
case 65: //A
|
|
// nextShape.position.z -= 0.1;
|
|
break
|
|
case 68: //D
|
|
// nextShape.position.z += 0.1;
|
|
break
|
|
case 87://"W":
|
|
// nextShape.position.y += 0.1;
|
|
break
|
|
case 83: // "S":
|
|
// nextShape.position.y -= 0.1;
|
|
break
|
|
case 32: // "SPACE":
|
|
let nextChar = SHAPES[randomInteger(0, SHAPES.length)]
|
|
let nextShape = getBody(nextChar, scene, new BABYLON.Vector3(randomInteger(-GROUND_SIZE/4,GROUND_SIZE/4),
|
|
50, randomInteger(-GROUND_SIZE/4,GROUND_SIZE/4)))
|
|
// nextShape.rotation.x += Math.PI / 2;
|
|
break
|
|
}
|
|
break;
|
|
}
|
|
});
|
|
|
|
return scene;
|
|
};
|
|
|
|
var getBody = (nextChar, scene, position = new BABYLON.Vector3(0, 50, 0)) => {
|
|
|
|
let body
|
|
if (BODIES[nextChar].mesh) {
|
|
body = BODIES[nextChar].mesh.clone("s")
|
|
} else {
|
|
let shape = getShape(nextChar, scene)
|
|
BODIES[nextChar].mesh = shape
|
|
body = BODIES[nextChar].mesh.clone("s")
|
|
body.isVisible = true
|
|
}
|
|
|
|
body.position = position
|
|
shadowGenerator.addShadowCaster(body);
|
|
return body
|
|
}
|
|
|
|
var getShape = (shape, scene) => {
|
|
|
|
switch (shape) {
|
|
case "O":
|
|
var boxO = BABYLON.MeshBuilder.CreateBox("boxO", { height: BOX_DEPTH/2, width: BOX_SIZE, depth: BOX_DEPTH/2 }, scene);
|
|
boxO.physicsImpostor = new BABYLON.PhysicsImpostor(boxO, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 1 }, scene);
|
|
boxO.material = BODIES[shape].material
|
|
return boxO
|
|
|
|
case "I":
|
|
var boxI = BABYLON.MeshBuilder.CreateBox("boxI", { height: BOX_DEPTH, width: BOX_SIZE, depth: BOX_SIZE }, scene);
|
|
boxI.physicsImpostor = new BABYLON.PhysicsImpostor(boxI, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 1 }, scene);
|
|
boxI.material = BODIES[shape].material
|
|
|
|
return boxI
|
|
|
|
case "L":
|
|
|
|
var boxL = BABYLON.MeshBuilder.CreateBox("boxL", { height: BOX_SIZE, width: BOX_SIZE, depth: BOX_DEPTH }, scene);
|
|
var boxLTop = BABYLON.MeshBuilder.CreateBox("boxLTop", { height: BOX_SIZE, width: BOX_SIZE, depth: BOX_SIZE }, scene);
|
|
boxLTop.position.y = BOX_SIZE
|
|
boxLTop.position.z = BOX_SIZE * 2
|
|
boxLTop.parent = boxL
|
|
|
|
boxLTop.physicsImpostor = new BABYLON.PhysicsImpostor(boxLTop, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 1 }, scene);
|
|
boxL.physicsImpostor = new BABYLON.PhysicsImpostor(boxL, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 1 }, scene);
|
|
boxL.material = BODIES[shape].material
|
|
boxLTop.material = BODIES[shape].material
|
|
|
|
return boxL
|
|
/**
|
|
return BABYLON.Mesh.MergeMeshes([boxL, boxLTop])
|
|
*/
|
|
|
|
var subCSG = BABYLON.CSG.FromMesh(boxL).subtract(BABYLON.CSG.FromMesh(boxLTop));
|
|
var newMesh = subCSG.toMesh("csg", materials[shape], scene);
|
|
newMesh.position = new BABYLON.Vector3(10, 0, 0);
|
|
return newMesh
|
|
|
|
case "T":
|
|
var boxT = BABYLON.MeshBuilder.CreateBox("boxT", { height: BOX_SIZE, width: BOX_SIZE, depth: BOX_DEPTH }, scene);
|
|
var boxTBottom = BABYLON.MeshBuilder.CreateBox("box", { height: BOX_SIZE, width: BOX_SIZE, depth: BOX_SIZE }, scene);
|
|
boxTBottom.position.y = -BOX_SIZE
|
|
boxTBottom.parent = boxT
|
|
|
|
boxT.physicsImpostor = new BABYLON.PhysicsImpostor(boxT, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 1 }, scene);
|
|
boxTBottom.physicsImpostor = new BABYLON.PhysicsImpostor(boxTBottom, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 1 }, scene);
|
|
|
|
boxT.material = BODIES[shape].material
|
|
boxTBottom.material = BODIES[shape].material
|
|
return boxT //BABYLON.Mesh.MergeMeshes([boxT, boxTBottom])
|
|
|
|
case "S":
|
|
var boxS = BABYLON.MeshBuilder.CreateBox("boxS", { height: BOX_SIZE, width: BOX_SIZE, depth: BOX_DEPTH / 2 }, scene);
|
|
var boxSTop = BABYLON.MeshBuilder.CreateBox("boxS", { height: BOX_SIZE, width: BOX_SIZE, depth: BOX_DEPTH / 2 }, scene);
|
|
boxSTop.position.y = BOX_SIZE
|
|
boxSTop.position.z = BOX_SIZE
|
|
boxSTop.parent = boxS
|
|
|
|
boxS.physicsImpostor = new BABYLON.PhysicsImpostor(boxS, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 1 }, scene);
|
|
boxSTop.physicsImpostor = new BABYLON.PhysicsImpostor(boxSTop, BABYLON.PhysicsImpostor.BoxImpostor, { mass: 1 }, scene);
|
|
|
|
boxS.material = BODIES[shape].material
|
|
boxSTop.material = BODIES[shape].material
|
|
return boxS
|
|
|
|
//return BABYLON.Mesh.MergeMeshes([boxS, boxSTop])
|
|
}
|
|
}
|
|
|
|
randomInteger=(min, max)=> {
|
|
return Math.floor(Math.random() * (max-min)) + min
|
|
}
|
|
|
|
var createMat = (scene, color) => {
|
|
var mat = new BABYLON.StandardMaterial("", scene);
|
|
mat.diffuseColor = color;
|
|
mat.specularColor = BABYLON.Color3.FromHexString("#555555");
|
|
mat.specularPower = 1;
|
|
mat.emissiveColor = color // color.clone().scale(0.7);
|
|
mat.backFaceCulling = false;
|
|
return mat;
|
|
}
|
|
|
|
|
|
var engine;
|
|
try {
|
|
engine = createDefaultEngine();
|
|
} catch(e) {
|
|
console.log("the available createEngine function failed. Creating the default engine instead");
|
|
engine = createDefaultEngine();
|
|
}
|
|
if (!engine) throw 'engine should not be null.';
|
|
scene = createScene();;
|
|
scene.then(returnedScene => { sceneToRender = returnedScene; });
|
|
|
|
|
|
engine.runRenderLoop(function () {
|
|
if (sceneToRender && sceneToRender.activeCamera) {
|
|
sceneToRender.render();
|
|
}
|
|
});
|
|
|
|
// Resize
|
|
window.addEventListener("resize", function () {
|
|
engine.resize();
|
|
}); |