Not gonna lie to you, but it’s really really hard for me to make my game project into the plaground, i’ve already tried that before posting this and it was so complicated (at least for me), that’s why i linked a Github repository and made demo videos, all i can for now is showing you the two main file of my project :
index.html :
<html>
<head>
<title>Calamity Car</title>
<meta charset="UTF-8">
<style>
html, body {
overflow: hidden;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#renderCanvas {
width: 100%;
height: 100%;
touch-action: none;
}
</style>
<link rel="stylesheet" href="css/default.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/dat-gui/0.6.2/dat.gui.min.js"></script>
<script src="https://assets.babylonjs.com/generated/Assets.js"></script>
<script src="https://preview.babylonjs.com/ammo.js"></script>
<script src="https://preview.babylonjs.com/cannon.js"></script>
<script src="https://preview.babylonjs.com/Oimo.js"></script>
<script src="https://preview.babylonjs.com/earcut.min.js"></script>
<script src="https://preview.babylonjs.com/babylon.js"></script>
<script src="https://preview.babylonjs.com/materialsLibrary/babylonjs.materials.min.js"></script>
<script src="https://preview.babylonjs.com/proceduralTexturesLibrary/babylonjs.proceduralTextures.min.js"></script>
<script src="https://preview.babylonjs.com/postProcessesLibrary/babylonjs.postProcess.min.js"></script>
<script src="https://preview.babylonjs.com/loaders/babylonjs.loaders.js"></script>
<script src="https://preview.babylonjs.com/serializers/babylonjs.serializers.min.js"></script>
<script src="https://preview.babylonjs.com/gui/babylon.gui.min.js"></script>
<script src="https://preview.babylonjs.com/inspector/babylon.inspector.bundle.js"></script>
<script src="js/main.js"></script>
</head>
<body>
<canvas id="renderCanvas" touch-action="none"></canvas>
<script>
modifySettings();
const canvas = document.getElementById("renderCanvas");
const engine = new BABYLON.Engine(canvas, true);
const createScene = function () {
const scene = new BABYLON.Scene(engine);
var physicsPlugin = new BABYLON.CannonJSPlugin();
scene.collisionsEnabled = true;
scene.enablePhysics(physicsPlugin);
SceneLoader(scene);
light = new BABYLON.HemisphericLight("Light", new BABYLON.Vector3(0, -1, 0), scene);
camera = new BABYLON.FreeCamera("Camera", new BABYLON.Vector3(0,0,100), scene);
camera.inputs.clear();
camera.attachControl(canvas, true);
return scene;
};
const scene = createScene();
engine.runRenderLoop(function () {
if(fullyLoaded(scene) && once){
//CreateGizmo(scene);
CreateSkyBox(scene);
CreateCar(scene);
CreateGUI(scene);
camera.target = Car.position;
camera.parent = Car;
once = false;
}
else if (start) {
Car.move();
if (OK) {
SpawnMeteor(scene);
OK = false;
}
}
scene.render();
});
window.addEventListener("resize", function () {
engine.resize();
});
</script>
</body>
</html>
and my main.js :
let once = true;
let Car;
let camera;
let inputStates = {};
let world;
let start = false;
let OK = true;
let angle = 0.01;
let angle2 = 0.04;
let gizmoManager;
let light;
let json = {"name":"CPU particle system","id":"default system","capacity":10000,"emitter":[0,0,0],"particleEmitterType":{"type":"ConeParticleEmitter","radius":0.1,"angle":0.7853981633974483,"directionRandomizer":0,"radiusRange":1,"heightRange":1,"emitFromSpawnPointOnly":false},"textureName":"https://www.babylonjs.com/assets/Flare.png","invertY":true,"isLocal":false,"animations":[],"beginAnimationOnStart":false,"beginAnimationFrom":0,"beginAnimationTo":60,"beginAnimationLoop":false,"startDelay":0,"renderingGroupId":0,"isBillboardBased":true,"billboardMode":7,"minAngularSpeed":0,"maxAngularSpeed":0,"minSize":0.1,"maxSize":0.2,"minScaleX":1,"maxScaleX":1,"minScaleY":1,"maxScaleY":1,"minEmitPower":2,"maxEmitPower":2,"minLifeTime":1,"maxLifeTime":2,"emitRate":150,"gravity":[0,0,0],"noiseStrength":[10,10,10],"color1":[1,1,1,1],"color2":[0.7647058823529411,0.07450980392156863,0.07450980392156863,1],"colorDead":[0,0,0,0],"updateSpeed":0.016666666666666666,"targetStopDuration":0,"blendMode":0,"preWarmCycles":0,"preWarmStepOffset":1,"minInitialRotation":0,"maxInitialRotation":0,"startSpriteCellID":0,"endSpriteCellID":0,"spriteCellChangeSpeed":1,"spriteCellWidth":0,"spriteCellHeight":0,"spriteRandomStartCell":false,"isAnimationSheetEnabled":false,"textureMask":[1,1,1,1],"customShader":null,"preventAutoStart":false};
function CreateGizmo(scene){
gizmoManager = new BABYLON.GizmoManager(scene);
gizmoManager.positionGizmoEnabled = true;
gizmoManager.rotationGizmoEnabled = true;
gizmoManager.scaleGizmoEnabled = true;
gizmoManager.boundingBoxGizmoEnabled = true;
}
function SpawnMeteor(scene){
var meteor = BABYLON.MeshBuilder.CreateSphere("meteor", {diameter: 5, segments: 32}, scene);
var meteorMaterial = new BABYLON.StandardMaterial("meteorM", scene);
meteorMaterial.diffuseTexture = new BABYLON.Texture("/textures/meteor.jpg", scene);
meteorMaterial.alpha = 1;
meteor.material = meteorMaterial;
meteor.physicsImpostor = new BABYLON.PhysicsImpostor(meteor, BABYLON.PhysicsImpostor.SphereImpostor, {mass: 0});
meteor.position = new BABYLON.Vector3(getRandomArbitrary(),getRandomArbitrary(),getRandomArbitrary());
var solutions = FindLineSphereIntersections(meteor.position);
const particleSystem = new BABYLON.ParticleSystem("particles", 500);
particleSystem.particleTexture = new BABYLON.Texture(json.textureName);
particleSystem.updateSpeed = json.updateSpeed;
particleSystem.emitRate = 150;
particleSystem.emitter = meteor;
particleSystem.start();
BABYLON.Animation.CreateAndStartAnimation("anim", meteor, "position", 30, 60, meteor.position, solutions[0], BABYLON.Animation.ANIMATIONLOOPMODE_CONSTANT);
setTimeout(SpawnMeteor, 2000);
}
function CreateGUI(scene) {
var advancedTexture = BABYLON.GUI.AdvancedDynamicTexture.CreateFullscreenUI(scene);
var button1 = BABYLON.GUI.Button.CreateSimpleButton("but1", "START");
button1.width = "150px"
button1.height = "75px";
button1.color = "white";
button1.cornerRadius = 20;
button1.background = "green";
button1.top = "200px"
button1.onPointerUpObservable.add(function() {
start = true;
button1._doNotRender = true;
});
advancedTexture.addControl(button1);
}
function CreateWorld(world) {
world.physicsImpostor = new BABYLON.PhysicsImpostor(world, BABYLON.PhysicsImpostor.MeshImpostor, {mass: 0});
world.checkCollisions = true;
}
function CreateCar(scene){
let pivot = new BABYLON.Mesh("pivot", scene);
pivot.parent = Car;
const pivotAt = new BABYLON.Vector3(0, 0, 0);
const relativePosition = pivotAt.subtract(Car.position);
Car.setPivotPoint(relativePosition);
Car.move = () => {
Car.rotate(new BABYLON.Vector3(1, 0, 0), angle, BABYLON.Space.LOCAL);
if(inputStates.left) {
Car.rotate(new BABYLON.Vector3(0, 0, -1), angle2, BABYLON.Space.LOCAL);
}
if(inputStates.right) {
Car.rotate(new BABYLON.Vector3(0, 0, 1), angle2, BABYLON.Space.LOCAL);
}
};
}
function CreateSkyBox(scene){
var skybox = BABYLON.MeshBuilder.CreateBox("skyBox", {size:500.0}, scene);
var skyboxMaterial = new BABYLON.StandardMaterial("skyBox", scene);
skyboxMaterial.backFaceCulling = false;
var files = [
"textures/bg_left.jpg",
"textures/bg_up.jpg",
"textures/bg_front.jpg",
"textures/bg_right.jpg",
"textures/bg_down.jpg",
"textures/bg_back.jpg",
];
skyboxMaterial.reflectionTexture = new BABYLON.CubeTexture.CreateFromImages(files, scene);
skyboxMaterial.reflectionTexture.coordinatesMode = BABYLON.Texture.SKYBOX_MODE;
skyboxMaterial.diffuseColor = new BABYLON.Color3(0, 0, 0);
skyboxMaterial.specularColor = new BABYLON.Color3(0, 0, 0);
skybox.material = skyboxMaterial;
}
function fullyLoaded(scene) {
if(scene.getMeshByName("__root__") != null && scene.getMeshByName("planet_3") != null)
{
Car = scene.getMeshByName("__root__");
world = scene.getMeshByName("planet_3");
return true;
}
else
return false;
}
function SceneLoader(scene) {
BABYLON.SceneLoader.Append("scene/car/", "scene.gltf", scene, function (scene) {
});
BABYLON.SceneLoader.Append("scene/World/", "world.gltf", scene,function (scene) {
});
}
function modifySettings() {
/*scene.onPointerDown = () => {
if(!scene.alreadyLocked) {
console.log("requesting pointer lock");
canvas.requestPointerLock();
} else {
console.log("Pointer already locked");
}
}
document.addEventListener("pointerlockchange", () => {
let element = document.pointerLockElement || null;
if(element) {
scene.alreadyLocked = true;
} else {
scene.alreadyLocked = false;
}
})
*/
inputStates.left = false;
inputStates.right = false;
inputStates.up = false;
inputStates.down = false;
inputStates.space = false;
window.addEventListener('keydown', (event) => {
if ((event.key === "ArrowLeft") || (event.key === "q")|| (event.key === "Q")) {
inputStates.left = true;
} else if ((event.key === "ArrowUp") || (event.key === "z")|| (event.key === "Z")){
inputStates.up = true;
} else if ((event.key === "ArrowRight") || (event.key === "d")|| (event.key === "D")){
inputStates.right = true;
} else if ((event.key === "ArrowDown")|| (event.key === "s")|| (event.key === "S")) {
inputStates.down = true;
} else if (event.key === " ") {
inputStates.space = true;
}
}, false);
window.addEventListener('keyup', (event) => {
if ((event.key === "ArrowLeft") || (event.key === "q")|| (event.key === "Q")) {
inputStates.left = false;
} else if ((event.key === "ArrowUp") || (event.key === "z")|| (event.key === "Z")){
inputStates.up = false;
} else if ((event.key === "ArrowRight") || (event.key === "d")|| (event.key === "D")){
inputStates.right = false;
} else if ((event.key === "ArrowDown")|| (event.key === "s")|| (event.key === "S")) {
inputStates.down = false;
} else if (event.key === " ") {
inputStates.space = false;
}
}, false);
}
function getRandomArbitrary() {
var sign = Math.random() < 0.5 ? -1 : 1;
var coord = Math.floor(Math.random() * 100) + 50
return sign * coord;
}
function FindLineSphereIntersections(meteorPosition)
{
let solutions;
var circleRadius = 35;
var cx = 0;
var cy = 0;
var cz = 0;
var px = cx;
var py = cy;
var pz = cz;
var vx = meteorPosition.x;
var vy = meteorPosition.y;
var vz = meteorPosition.z;
var A = vx * vx + vy * vy + vz * vz;
var B = 2.0 * (px * vx + py * vy + pz * vz - vx * cx - vy * cy - vz * cz);
var C = px * px - 2 * px * cx + cx * cx + py * py - 2 * py * cy + cy * cy +
pz * pz - 2 * pz * cz + cz * cz - circleRadius * circleRadius;
// discriminant
var D = B * B - 4 * A * C;
if ( D < 0 )
{
return new BABYLON.Vector3.Zero();
}
var t1 = ( -B - Math.sqrt(D) ) / (2.0 *A);
var solution1 = new BABYLON.Vector3( cx * ( 1 - t1 ) + t1 * meteorPosition.x,
cy * ( 1 - t1 ) + t1 * meteorPosition.y,
cz * ( 1 - t1 ) + t1 * meteorPosition.z );
if ( D == 0 )
{
solutions = [solution1];
return solutions;
}
var t2 = ( -B + Math.sqrt(D) ) / ( 2.0 * A );
var solution2 = new BABYLON.Vector3( cx * ( 1 - t2 ) + t2 * meteorPosition.x,
cy * ( 1 - t2 ) + t2 * meteorPosition.y,
cz * ( 1 - t2 ) + t2 * meteorPosition.z );
// prefer a solution that's on the line segment itself
if ( Math.abs( t1 - 0.5 ) < Math.abs( t2 - 0.5 ) )
{
solutions = [solution1, solution2];
return solutions;
}
solutions = [solution2, solution1];
return solutions;
}
everything else is just textures and scenes (wich you can find on my github repository set on public.
Sorry for the inconvenience and my incompetence
.