Cube Rush 3D
by AtomicBolt46514 lines11.3 KB🛠️ Three.js (3D graphics)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Cube Rush 3D</title>
<style>
* { box-sizing: border-box; }
body {
margin: 0;
overflow: hidden;
background: #080b20;
color: white;
font-family: Arial, sans-serif;
}
canvas { display: block; }
#hud {
position: absolute;
top: 15px;
left: 15px;
display: flex;
gap: 10px;
flex-wrap: wrap;
z-index: 2;
}
.stat {
background: #10152ddd;
border: 2px solid #00eaff;
border-radius: 10px;
padding: 10px 14px;
font-weight: bold;
}
#overlay {
position: absolute;
inset: 0;
background: #050817bb;
display: flex;
justify-content: center;
align-items: center;
z-index: 5;
text-align: center;
}
.panel {
width: min(90%, 430px);
padding: 28px;
border: 3px solid #00eaff;
border-radius: 20px;
background: #111a35;
box-shadow: 0 0 35px #00d9ff55;
}
h1 {
color: #00eaff;
font-size: 38px;
margin: 0 0 10px;
}
button {
background: #00eaff;
border: none;
color: #06101e;
padding: 14px 25px;
font-size: 18px;
font-weight: bold;
border-radius: 12px;
cursor: pointer;
margin-top: 12px;
}
button:hover { background: white; }
#jumpButton {
position: absolute;
bottom: 25px;
right: 25px;
z-index: 3;
width: 85px;
height: 85px;
border-radius: 50%;
font-size: 30px;
border: 3px solid white;
background: #00d9ffcc;
touch-action: none;
}
.hint {
color: #cbd5e1;
line-height: 1.6;
font-size: 14px;
}
</style>
</head>
<body>
<div id="hud">
<div class="stat">⭐ Score: <span id="score">0</span></div>
<div class="stat">💎 Orbs: <span id="orbs">0</span></div>
<div class="stat">⚡ Speed: <span id="speed">1.0x</span></div>
</div>
<div id="overlay">
<div class="panel">
<h1 id="heading">CUBE RUSH 3D</h1>
<p id="description">
Jump over spikes, dodge blocks and collect glowing orbs!
</p>
<p class="hint">
SPACE / UP ARROW / CLICK = JUMP<br>
On mobile, tap the jump button.<br>
Time your jumps carefully!
</p>
<button id="start">START GAME</button>
</div>
</div>
<button id="jumpButton">↑</button>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.160.0/build/three.module.js"
}
}
</script>
<script type="module">
import * as THREE from "three";
// ---------------- SCENE ----------------
const scene = new THREE.Scene();
scene.background = new THREE.Color(0x090d2b);
scene.fog = new THREE.Fog(0x090d2b, 25, 75);
const camera = new THREE.PerspectiveCamera(
60, innerWidth / innerHeight, 0.1, 150
);
camera.position.set(0, 7, 17);
camera.lookAt(0, 2, 0);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(innerWidth, innerHeight);
renderer.setPixelRatio(Math.min(devicePixelRatio, 2));
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
scene.add(new THREE.HemisphereLight(0xb8d9ff, 0x252044, 2));
const light = new THREE.DirectionalLight(0xffffff, 2);
light.position.set(-5, 12, 8);
light.castShadow = true;
scene.add(light);
// ---------------- MATERIALS ----------------
const mat = (color, emissive = 0x000000) =>
new THREE.MeshStandardMaterial({
color,
emissive,
roughness: 0.4,
metalness: 0.15
});
const floorMat = mat(0x171e42);
const cubeMat = mat(0x00eaff, 0x006c99);
const spikeMat = mat(0xff315d, 0x77001c);
const blockMat = mat(0xffa52f, 0x713400);
const orbMat = new THREE.MeshStandardMaterial({
color: 0xffe34d,
emissive: 0xffa500,
emissiveIntensity: 1.5,
metalness: 0.6,
roughness: 0.2
});
// ---------------- GROUND ----------------
const ground = new THREE.Mesh(
new THREE.BoxGeometry(200, 0.6, 12),
floorMat
);
ground.position.set(0, -0.35, 0);
ground.receiveShadow = true;
scene.add(ground);
const groundLine = new THREE.Mesh(
new THREE.BoxGeometry(200, 0.08, 12.1),
mat(0x00bfff, 0x0055ff)
);
groundLine.position.set(0, -0.02, 0);
scene.add(groundLine);
// Background grid
const grid = new THREE.GridHelper(100, 50, 0x174a85, 0x18264b);
grid.position.y = -0.02;
grid.position.z = -5;
scene.add(grid);
// Decorative glowing pillars
const decorations = [];
for (let i = 0; i < 35; i++) {
const h = 2 + Math.random() * 9;
const pillar = new THREE.Mesh(
new THREE.BoxGeometry(0.5, h, 0.5),
mat(0x202d67, 0x101c4b)
);
pillar.position.set(
-20 + i * 2.5,
h / 2 - 0.1,
-5 - Math.random() * 8
);
scene.add(pillar);
decorations.push(pillar);
}
// ---------------- PLAYER ----------------
const player = new THREE.Group();
scene.add(player);
const cube = new THREE.Mesh(
new THREE.BoxGeometry(1.25, 1.25, 1.25),
cubeMat
);
cube.castShadow = true;
player.add(cube);
// Bright front face decoration
const face = new THREE.Mesh(
new THREE.BoxGeometry(0.7, 0.7, 0.08),
mat(0xffffff, 0x0099aa)
);
face.position.set(0, 0, 0.66);
player.add(face);
const playerX = -5;
player.position.set(playerX, 0.65, 0);
// ---------------- GAME STATE ----------------
let playing = false;
let dead = false;
let score = 0;
let orbs = 0;
let speed = 13;
let gravity = 28;
let velocityY = 0;
let grounded = true;
let spawnTimer = 0;
let nextSpawn = 1.7;
let objects = [];
let elapsed = 0;
const scoreText = document.getElementById("score");
const orbText = document.getElementById("orbs");
const speedText = document.getElementById("speed");
const overlay = document.getElementById("overlay");
// ---------------- OBSTACLE CREATION ----------------
function addSpike(x) {
const geometry = new THREE.ConeGeometry(0.75, 1.6, 4);
const spike = new THREE.Mesh(geometry, spikeMat);
spike.rotation.y = Math.PI / 4;
spike.position.set(x, 0.8, 0);
spike.castShadow = true;
scene.add(spike);
objects.push({
mesh: spike,
type: "spike",
x,
collected: false
});
}
function addBlock(x) {
const block = new THREE.Mesh(
new THREE.BoxGeometry(1.35, 1.7, 1.5),
blockMat
);
block.position.set(x, 0.85, 0);
block.castShadow = true;
scene.add(block);
// Glowing top
const top = new THREE.Mesh(
new THREE.BoxGeometry(1.4, 0.12, 1.55),
mat(0xffe36e, 0xff8a00)
);
top.position.y = 0.91;
block.add(top);
objects.push({
mesh: block,
type: "block",
x,
collected: false
});
}
function addOrb(x, y = 2) {
const orb = new THREE.Mesh(
new THREE.OctahedronGeometry(0.38),
orbMat
);
orb.position.set(x, y, 0);
scene.add(orb);
objects.push({
mesh: orb,
type: "orb",
x,
baseY: y,
collected: false
});
}
function spawnPattern() {
const choice = Math.random();
if (choice < 0.42) {
addSpike(22);
if (Math.random() < 0.7) addOrb(22, 2.5);
} else if (choice < 0.72) {
addBlock(22);
addOrb(22, 3);
} else {
addSpike(22);
addSpike(23.4);
addOrb(22.7, 3.4);
}
}
// ---------------- JUMPING ----------------
function jump() {
if (!playing || dead || !grounded) return;
velocityY = 12;
grounded = false;
}
document.addEventListener("keydown", (event) => {
if (
event.code === "Space" ||
event.code === "ArrowUp" ||
event.code === "KeyW"
) {
event.preventDefault();
if (!event.repeat) jump();
}
});
renderer.domElement.addEventListener("pointerdown", jump);
const jumpButton = document.getElementById("jumpButton");
jumpButton.addEventListener("pointerdown", (e) => {
e.preventDefault();
jump();
});
// ---------------- GAME OVER ----------------
function gameOver() {
if (dead) return;
dead = true;
playing = false;
document.getElementById("heading").textContent = "GAME OVER!";
document.getElementById("description").innerHTML =
"⭐ Score: " + Math.floor(score) +
"<br>💎 Orbs collected: " + orbs +
"<br><br>Try again and beat your score!";
document.getElementById("start").textContent = "RESTART";
overlay.style.display = "flex";
}
// ---------------- START / RESTART ----------------
function startGame() {
objects.forEach(obj => scene.remove(obj.mesh));
objects = [];
score = 0;
orbs = 0;
speed = 13;
elapsed = 0;
spawnTimer = 0;
nextSpawn = 1.7;
velocityY = 0;
grounded = true;
dead = false;
playing = true;
player.position.set(playerX, 0.65, 0);
player.rotation.set(0, 0, 0);
document.getElementById("heading").textContent = "CUBE RUSH 3D";
document.getElementById("description").textContent =
"Jump over spikes, dodge blocks and collect glowing orbs!";
document.getElementById("start").textContent = "START GAME";
overlay.style.display = "none";
updateHUD();
}
document.getElementById("start").addEventListener("click", startGame);
function updateHUD() {
scoreText.textContent = Math.floor(score);
orbText.textContent = orbs;
speedText.textContent = (speed / 13).toFixed(1) + "x";
}
// ---------------- MAIN LOOP ----------------
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const dt = Math.min(clock.getDelta(), 0.04);
if (playing) {
elapsed += dt;
// Increase difficulty gradually
speed = Math.min(26, 13 + elapsed * 0.22);
score += dt * speed * 2;
// Jump physics
velocityY -= gravity * dt;
player.position.y += velocityY * dt;
if (player.position.y <= 0.65) {
player.position.y = 0.65;
velocityY = 0;
grounded = true;
}
// Rotate the cube while in the air
if (!grounded) {
cube.rotation.z -= dt * 5;
} else {
cube.rotation.z = Math.round(
cube.rotation.z / (Math.PI / 2)
) * (Math.PI / 2);
}
// Spawn obstacles
spawnTimer += dt;
if (spawnTimer >= nextSpawn) {
spawnTimer = 0;
nextSpawn = Math.max(1.05, 1.8 - elapsed * 0.006);
spawnPattern();
}
// Move obstacles and collect orbs
for (let i = objects.length - 1; i >= 0; i--) {
const obj = objects[i];
obj.x -= speed * dt;
obj.mesh.position.x = obj.x;
if (obj.type === "orb") {
obj.mesh.rotation.y += dt * 3;
obj.mesh.rotation.x += dt * 2;
obj.mesh.position.y = obj.baseY + Math.sin(elapsed * 4 + i) * 0.15;
const closeX = Math.abs(obj.x - playerX) < 1.05;
const closeY = Math.abs(obj.mesh.position.y - player.position.y) < 1.6;
if (closeX && closeY && !obj.collected) {
obj.collected = true;
orbs++;
score += 50;
scene.remove(obj.mesh);
objects.splice(i, 1);
continue;
}
} else {
const closeX = Math.abs(obj.x - playerX) < 0.95;
const playerBottom = player.position.y - 0.625;
if (closeX && playerBottom < 1.45) {
gameOver();
}
}
// Remove things behind the player
if (obj.x < -13) {
scene.remove(obj.mesh);
objects.splice(i, 1);
}
}
// Move background decorations
for (const pillar of decorations) {
pillar.position.x -= speed * dt * 0.35;
if (pillar.position.x < -25) {
pillar.position.x += 87.5;
}
}
updateHUD();
}
// Camera movement
camera.position.y = 7 + (player.position.y - 0.65) * 0.15;
camera.lookAt(0, 2, 0);
renderer.render(scene, camera);
}
animate();
// ---------------- RESIZE ----------------
window.addEventListener("resize", () => {
camera.aspect = innerWidth / innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(innerWidth, innerHeight);
});
</script>
</body>
</html>Game Source: Cube Rush 3D
Creator: AtomicBolt46
Libraries: three
Complexity: complex (514 lines, 11.3 KB)
The full source code is displayed above on this page.
Remix Instructions
To remix this game, copy the source code above and modify it. Add a ARCADELAB header at the top with "remix_of: cube-rush-3d-atomicbolt46" to link back to the original. Then publish at arcadelab.ai/publish.