Skip to content

Commit 55df3d4

Browse files
authored
3d marlbe game test
1 parent 2ff68d7 commit 55df3d4

File tree

4 files changed

+209
-0
lines changed

4 files changed

+209
-0
lines changed

babylon_basic/ball8.png

1.78 KB
Loading

babylon_basic/game.js

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
// Wait until the entire HTML document is loaded and parsed
2+
window.addEventListener('DOMContentLoaded', () => {
3+
4+
const canvas = document.getElementById("renderCanvas");
5+
const engine = new BABYLON.Engine(canvas, true);
6+
const debugInfo = document.getElementById("debugInfo");
7+
const inputMap = {};
8+
9+
const createScene = () => {
10+
const scene = new BABYLON.Scene(engine);
11+
12+
const camera = new BABYLON.ArcRotateCamera("camera", Math.PI / 4, Math.PI / 4, 30, BABYLON.Vector3.Zero(), scene);
13+
camera.attachControl(canvas, true);
14+
camera.upperBetaLimit = Math.PI / 2.2;
15+
camera.lowerRadiusLimit = 10;
16+
camera.upperRadiusLimit = 50;
17+
18+
const light = new BABYLON.HemisphericLight("light", new BABYLON.Vector3(0, 1, 0), scene);
19+
light.intensity = 0.8;
20+
const gravityVector = new BABYLON.Vector3(0, -9.81, 0);
21+
const physicsPlugin = new BABYLON.CannonJSPlugin();
22+
scene.enablePhysics(gravityVector, physicsPlugin);
23+
24+
const floorMaterial = new BABYLON.StandardMaterial("floorMat", scene);
25+
floorMaterial.diffuseTexture = new BABYLON.Texture("checkerboard.jpg", scene);
26+
floorMaterial.specularColor = BABYLON.Color3.Black();
27+
28+
const wallMaterial = new BABYLON.StandardMaterial("wallMat", scene);
29+
wallMaterial.diffuseTexture = new BABYLON.Texture("wood.jpg", scene);
30+
wallMaterial.specularColor = BABYLON.Color3.Black();
31+
32+
const goalMaterial = new BABYLON.StandardMaterial("goalMat", scene);
33+
goalMaterial.diffuseColor = new BABYLON.Color3.Green();
34+
goalMaterial.emissiveColor = new BABYLON.Color3(0.2, 0.7, 0.2);
35+
36+
const levelMap = ["WWWWWWWWWW","WS-------W","W-WWWW-O-W","W-W----O-W","W-W-WWWW-W","W-O-W----W","W-O-WW-W-W","W---G--W-W","WWWWWWWWWW"];
37+
const tileSize = 2, wallHeight = 2;
38+
let startPosition = BABYLON.Vector3.Zero(), goalMesh = null;
39+
40+
const createLevelFromMap = (map) => {
41+
const levelWidth = map[0].length, levelHeight = map.length;
42+
const offsetX = -(levelWidth * tileSize) / 2 + tileSize / 2, offsetZ = (levelHeight * tileSize) / 2 - tileSize / 2;
43+
for (let row = 0; row < map.length; row++) for (let col = 0; col < map[row].length; col++) {
44+
const char = map[row][col], x = col * tileSize + offsetX, z = -(row * tileSize - offsetZ);
45+
if (char === '-' || char === 'S' || char === 'G') {
46+
const tile = BABYLON.MeshBuilder.CreateBox(`f_${row}_${col}`,{width:tileSize,height:0.1,depth:tileSize},scene);
47+
tile.position = new BABYLON.Vector3(x,0,z); tile.material = floorMaterial;
48+
// <-- FIX: Using full property names for physics
49+
tile.physicsImpostor = new BABYLON.PhysicsImpostor(tile,BABYLON.PhysicsImpostor.BoxImpostor,{mass:0,restitution:0.5,friction:0.5},scene);
50+
if (char === 'S') startPosition = new BABYLON.Vector3(x, 1, z);
51+
if (char === 'G') { tile.material = goalMaterial; goalMesh = tile; }
52+
} else if (char === 'W') {
53+
const wall = BABYLON.MeshBuilder.CreateBox(`w_${row}_${col}`,{width:tileSize,height:wallHeight,depth:tileSize},scene);
54+
wall.position = new BABYLON.Vector3(x, wallHeight / 2, z); wall.material = wallMaterial;
55+
// <-- FIX: Using full property names for physics
56+
wall.physicsImpostor = new BABYLON.PhysicsImpostor(wall,BABYLON.PhysicsImpostor.BoxImpostor,{mass:0,restitution:0.5,friction:0.5},scene);
57+
}
58+
}
59+
};
60+
createLevelFromMap(levelMap);
61+
62+
const ball = BABYLON.MeshBuilder.CreateSphere("ball", { diameter: 1 }, scene);
63+
const ballMaterial = new BABYLON.StandardMaterial("ballMat", scene);
64+
ballMaterial.diffuseTexture = new BABYLON.Texture("ball8.png", scene);
65+
ballMaterial.specularColor = BABYLON.Color3.Black();
66+
ball.material = ballMaterial;
67+
// <-- FIX: Using full property names for physics
68+
ball.physicsImpostor = new BABYLON.PhysicsImpostor(ball,BABYLON.PhysicsImpostor.SphereImpostor,{mass:1,restitution:0.5,friction:0.1,damping:0.1});
69+
const resetBall = () => { ball.physicsImpostor.setLinearVelocity(BABYLON.Vector3.Zero()); ball.physicsImpostor.setAngularVelocity(BABYLON.Vector3.Zero()); ball.position = startPosition; };
70+
resetBall();
71+
72+
scene.actionManager = new BABYLON.ActionManager(scene);
73+
if (goalMesh) {
74+
goalMesh.actionManager = new BABYLON.ActionManager(scene);
75+
goalMesh.actionManager.registerAction(new BABYLON.ExecuteCodeAction({trigger:BABYLON.ActionManager.OnIntersectionEnterTrigger,parameter:ball}, () => { alert("You Win!"); resetBall(); }));
76+
}
77+
scene.actionManager.registerAction(new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnKeyDownTrigger, (evt) => { inputMap[evt.sourceEvent.key.toLowerCase()] = true; }));
78+
scene.actionManager.registerAction(new BABYLON.ExecuteCodeAction(BABYLON.ActionManager.OnKeyUpTrigger, (evt) => { inputMap[evt.sourceEvent.key.toLowerCase()] = false; }));
79+
80+
scene.onBeforeRenderObservable.add(() => {
81+
if (ball.position.y < -5) { alert("You fell! Try again."); resetBall(); }
82+
83+
const moveForce = 15;
84+
const forceDirection = new BABYLON.Vector3.Zero();
85+
const cameraForward = camera.getDirection(BABYLON.Vector3.Forward());
86+
const forward = new BABYLON.Vector3(cameraForward.x, 0, cameraForward.z).normalize();
87+
const right = BABYLON.Vector3.Cross(BABYLON.Vector3.Up(), forward).normalize();
88+
89+
if (inputMap["w"]) { forceDirection.addInPlace(forward); }
90+
if (inputMap["s"]) { forceDirection.subtractInPlace(forward); }
91+
if (inputMap["d"]) { forceDirection.addInPlace(right); }
92+
if (inputMap["a"]) { forceDirection.subtractInPlace(right); }
93+
94+
if (forceDirection.length() > 0.01) {
95+
forceDirection.normalize().scaleInPlace(moveForce);
96+
ball.physicsImpostor.applyForce(forceDirection, ball.getAbsolutePosition());
97+
}
98+
99+
if (debugInfo) {
100+
const alphaDeg = BABYLON.Tools.ToDegrees(camera.alpha).toFixed(2);
101+
const betaDeg = BABYLON.Tools.ToDegrees(camera.beta).toFixed(2);
102+
const radius = camera.radius.toFixed(2);
103+
debugInfo.innerHTML = `Alpha (Y-rot): ${alphaDeg}°<br>Beta (X-rot): ${betaDeg}°<br>Radius (Zoom): ${radius}`;
104+
}
105+
});
106+
107+
return scene;
108+
};
109+
110+
const setupButtonControls = (buttonId, key) => {
111+
const button = document.getElementById(buttonId);
112+
if (!button) return;
113+
const pressEvent = (e) => { e.preventDefault(); inputMap[key] = true; };
114+
const releaseEvent = (e) => { e.preventDefault(); inputMap[key] = false; };
115+
button.addEventListener("mousedown", pressEvent);
116+
button.addEventListener("mouseup", releaseEvent);
117+
button.addEventListener("mouseleave", releaseEvent);
118+
button.addEventListener("touchstart", pressEvent, { passive: false });
119+
button.addEventListener("touchend", releaseEvent);
120+
button.addEventListener("touchcancel", releaseEvent);
121+
};
122+
setupButtonControls("btn-up", "w");
123+
setupButtonControls("btn-down", "s");
124+
setupButtonControls("btn-left", "a");
125+
setupButtonControls("btn-right", "d");
126+
127+
const scene = createScene();
128+
engine.runRenderLoop(() => { scene.render(); });
129+
window.addEventListener("resize", () => { engine.resize(); });
130+
131+
});

babylon_basic/index.html

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>Babylon.js Ball Roller</title>
6+
<style>
7+
html, body {
8+
overflow: hidden;
9+
width: 100%;
10+
height: 100%;
11+
margin: 0;
12+
padding: 0;
13+
}
14+
#renderCanvas {
15+
width: 100%;
16+
height: 100%;
17+
touch-action: none;
18+
}
19+
/* --- CSS FOR ON-SCREEN CONTROLS (BIGGER) --- */
20+
#controls {
21+
position: fixed;
22+
bottom: 30px; /* Increased spacing from edge */
23+
left: 30px;
24+
width: 240px; /* <-- DOUBLED in size */
25+
height: 240px; /* <-- DOUBLED in size */
26+
display: grid;
27+
grid-template-columns: 1fr 1fr 1fr;
28+
grid-template-rows: 1fr 1fr 1fr;
29+
z-index: 10;
30+
}
31+
#controls button {
32+
background-color: rgba(50, 50, 50, 0.7);
33+
color: white;
34+
border: 3px solid rgba(255, 255, 255, 0.8); /* Thicker border */
35+
border-radius: 16px; /* Larger radius */
36+
font-size: 36px; /* Larger font */
37+
font-weight: bold;
38+
cursor: pointer;
39+
user-select: none;
40+
}
41+
#controls button:active {
42+
background-color: rgba(255, 255, 255, 0.7);
43+
color: black;
44+
}
45+
#btn-up { grid-area: 1 / 2 / 2 / 3; }
46+
#btn-left { grid-area: 2 / 1 / 3 / 2; }
47+
#btn-right { grid-area: 2 / 3 / 3 / 4; }
48+
#btn-down { grid-area: 3 / 2 / 4 / 3; }
49+
50+
/* --- CSS FOR DEBUG INFO --- */
51+
#debugInfo {
52+
position: fixed;
53+
top: 10px;
54+
right: 10px;
55+
background-color: rgba(0, 0, 0, 0.5);
56+
color: white;
57+
padding: 10px;
58+
border-radius: 5px;
59+
font-family: monospace;
60+
font-size: 14px;
61+
z-index: 10;
62+
}
63+
</style>
64+
<script src="https://cdn.babylonjs.com/babylon.js"></script>
65+
<script src="https://cdn.babylonjs.com/cannon.js"></script>
66+
</head>
67+
<body>
68+
<canvas id="renderCanvas"></canvas>
69+
<div id="debugInfo"></div>
70+
<div id="controls">
71+
<button id="btn-up"></button>
72+
<button id="btn-left"></button>
73+
<button id="btn-right"></button>
74+
<button id="btn-down"></button>
75+
</div>
76+
<script src="game.js"></script>
77+
</body>
78+
</html>

babylon_basic/wood.jpg

44 KB
Loading

0 commit comments

Comments
 (0)