test_js / index.html
broadfield-dev's picture
Update index.html
7fd47be verified
raw
history blame
6.55 kB
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Rubik's Cube</title>
<style>
body { margin: 0; overflow: hidden; }
canvas { width: 100%; height: 100%; }
</style>
</head>
<body>
<div id="controls">
<button onclick="rotate('U')">U</button>
<button onclick="rotate('U\'')">U'</button>
<button onclick="rotate('D')">D</button>
<button onclick="rotate('D\'')">D'</button>
<button onclick="rotate('L')">L</button>
<button onclick="rotate('L\'')">L'</button>
<button onclick="rotate('R')">R</button>
<button onclick="rotate('R\'')">R'</button>
<button onclick="rotate('F')">F</button>
<button onclick="rotate('F\'')">F'</button>
<button onclick="rotate('B')">B</button>
<button onclick="rotate('B\'')">B'</button>
<button onclick="scramble()">Scramble</button>
<button onclick="unscramble()">Unscramble</button>
</div>
<script type="module">
import * as THREE from 'https://cdn.skypack.dev/[email protected]';
import { OrbitControls } from 'https://cdn.skypack.dev/[email protected]/examples/jsm/controls/OrbitControls.js';
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const controls = new OrbitControls(camera, renderer.domElement);
camera.position.z = 5;
const cubeSize = 0.9;
const colors = {
'U': 0xFFFFFF, 'D': 0xFFFF00, 'L': 0xFFA500,
'R': 0x00FF00, 'F': 0x0000FF, 'B': 0xFF00FF
};
// Create cubies
const cubies = [];
for (let x = -1; x <= 1; x++) {
for (let y = -1; y <= 1; y++) {
for (let z = -1; z <= 1; z++) {
const geometry = new THREE.BoxGeometry(cubeSize, cubeSize, cubeSize);
const material = new THREE.MeshStandardMaterial({
color: 0x000000,
emissive: 0x000000
});
const cubie = new THREE.Mesh(geometry, material);
cubie.position.set(x * (cubeSize + 0.01), y * (cubeSize + 0.01), z * (cubeSize + 0.01));
// Paint faces
for (let face of ['U', 'D', 'L', 'R', 'F', 'B']) {
if ((face === 'U' && y === 1) || (face === 'D' && y === -1) ||
(face === 'L' && x === -1) || (face === 'R' && x === 1) ||
(face === 'F' && z === 1) || (face === 'B' && z === -1)) {
cubie.geometry.faces[getFaceIndex(face)].color.setHex(colors[face]);
}
}
cubie.geometry.colorsNeedUpdate = true;
cubies.push({ mesh: cubie, originalPosition: cubie.position.clone(), originalRotation: cubie.rotation.clone() });
scene.add(cubie);
}
}
}
// Light setup
const ambientLight = new THREE.AmbientLight(0x404040);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.5);
directionalLight.position.set(5, 5, 5);
scene.add(directionalLight);
// Cube rotation logic
const moveMap = {
'U': { axis: 'y', layer: 1, direction: 1, affectedCubies: cubies.filter(c => c.mesh.position.y === cubeSize) },
'U\'': { axis: 'y', layer: 1, direction: -1, affectedCubies: cubies.filter(c => c.mesh.position.y === cubeSize) },
// ... other moves similarly defined
};
let movesHistory = [];
function rotate(move) {
const { axis, layer, direction, affectedCubies } = moveMap[move];
const pivot = new THREE.Object3D();
scene.add(pivot);
for (let cubie of affectedCubies) {
pivot.attach(cubie.mesh);
}
const targetRotation = Math.PI / 2 * direction;
let currentRotation = 0;
function animate() {
if (currentRotation < targetRotation) {
currentRotation += 0.1;
pivot.rotation[axis] = currentRotation;
requestAnimationFrame(animate);
} else {
pivot.rotation[axis] = targetRotation;
for (let cubie of affectedCubies) {
cubie.mesh.applyMatrix4(pivot.matrix);
scene.attach(cubie.mesh);
}
scene.remove(pivot);
movesHistory.push(move);
}
}
animate();
}
function scramble() {
const moves = ['U', 'U\'', 'D', 'D\'', 'L', 'L\'', 'R', 'R\'', 'F', 'F\'', 'B', 'B\''];
for (let i = 0; i < 20; i++) {
rotate(moves[Math.floor(Math.random() * moves.length)]);
}
}
let unscrambling = false;
function unscramble() {
if (!unscrambling) {
unscrambling = true;
const interval = setInterval(() => {
if (movesHistory.length > 0) {
let lastMove = movesHistory.pop();
let inverse = lastMove.replace("'", "") + (lastMove.includes('\'') ? '' : '\'');
rotate(inverse);
} else {
clearInterval(interval);
unscrambling = false;
}
}, 500);
}
}
function animate() {
requestAnimationFrame(animate);
renderer.render(scene, camera);
}
animate();
function getFaceIndex(face) {
switch(face) {
case 'U': return 4; // top
case 'D': return 5; // bottom
case 'L': return 0; // left
case 'R': return 1; // right
case 'F': return 2; // front
case 'B': return 3; // back
}
}
</script>
</body>
</html>