3Dルービックキューブアプリ
フリーのプロンプト百科事典 Wikiprompt より
3Dルービックキューブアプリ Three.jsを用いてインタラクティブな3Dルービックキューブを作成するための包括的なプロンプト。コントロール、UI、スムーズなアニメーションを備えています。
プロンプト内容保存
🌐
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D Rubik's Cube</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
background: #1a1a2e;
overflow: hidden;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
#canvas {
display: block;
}
.hud {
position: fixed;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 20px;
align-items: center;
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
padding: 15px 25px;
border-radius: 50px;
border: 1px solid rgba(255, 255, 255, 0.2);
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3);
z-index: 100;
}
.btn {
padding: 10px 25px;
border: none;
border-radius: 25px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: all 0.3s ease;
color: white;
letter-spacing: 0.5px;
}
.btn-scramble {
background: linear-gradient(135deg, #667eea, #764ba2);
box-shadow: 0 4px 15px rgba(102, 126, 234, 0.4);
}
.btn-scramble:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(102, 126, 234, 0.6);
}
.btn-solve {
background: linear-gradient(135deg, #f093fb, #f5576c);
box-shadow: 0 4px 15px rgba(245, 87, 108, 0.4);
}
.btn-solve:hover {
transform: translateY(-2px);
box-shadow: 0 6px 20px rgba(245, 87, 108, 0.6);
}
.move-counter {
color: white;
font-size: 16px;
font-weight: 500;
padding: 10px 20px;
background: rgba(255, 255, 255, 0.1);
border-radius: 25px;
border: 1px solid rgba(255, 255, 255, 0.2);
min-width: 80px;
text-align: center;
}
.title {
position: fixed;
top: 30px;
left: 50%;
transform: translateX(-50%);
color: white;
font-size: 24px;
font-weight: 700;
text-shadow: 0 2px 10px rgba(0, 0, 0, 0.5);
z-index: 100;
letter-spacing: 1px;
}
.hint {
position: fixed;
bottom: 100px;
left: 50%;
transform: translateX(-50%);
color: rgba(255, 255, 255, 0.6);
font-size: 14px;
z-index: 100;
text-align: center;
background: rgba(0, 0, 0, 0.3);
padding: 8px 16px;
border-radius: 20px;
backdrop-filter: blur(5px);
}
@media (max-width: 768px) {
.hud {
bottom: 20px;
padding: 10px 15px;
gap: 10px;
}
.btn {
padding: 8px 15px;
font-size: 14px;
}
.move-counter {
padding: 8px 12px;
font-size: 14px;
min-width: 60px;
}
.title {
font-size: 18px;
top: 20px;
}
.hint {
bottom: 80px;
font-size: 12px;
}
}
</style>
</head>
<body>
<div class="title">🎲 Rubik's Cube</div>
<div class="hint">Drag to rotate • Scroll to zoom • Press R to scramble, S to solve</div>
<div class="hud">
<button class="btn btn-scramble" onclick="scrambleCube()">Scramble</button>
<div class="move-counter" id="moveCounter">0 moves</div>
<button class="btn btn-solve" onclick="solveCube()">Solve</button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script>
<script>
// Scene setup
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(5, 5, 5);
camera.lookAt(0, 0, 0);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
// Controls
const controls = new THREE.OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.dampingFactor = 0.25;
controls.rotateSpeed = 0.8;
controls.zoomSpeed = 1.2;
controls.minDistance = 4;
controls.maxDistance = 15;
// Lighting
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
directionalLight.position.set(5, 10, 7);
directionalLight.castShadow = true;
scene.add(directionalLight);
const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.3);
directionalLight2.position.set(-5, -3, -5);
scene.add(directionalLight2);
// Cube colors
const colors = {
white: 0xffffff,
yellow: 0xffd500,
red: 0xff0000,
orange: 0xff8c00,
blue: 0x0000ff,
green: 0x00ff00
};
// Create cube
const cubeGroup = new THREE.Group();
const cubies = [];
const gap = 0.05;
const size = 0.9;
// Face colors for each cubie position
const faceColors = {
right: colors.red,
left: colors.orange,
up: colors.white,
down: colors.yellow,
front: colors.green,
back: colors.blue
};
// Create materials for each face
function createCubie(x, y, z) {
const materials = [];
// Right (+x) - Red
materials.push(new THREE.MeshPhongMaterial({
color: x === 1 ? faceColors.right : 0x333333,
shininess: 30
}));
// Left (-x) - Orange
materials.push(new THREE.MeshPhongMaterial({
color: x === -1 ? faceColors.left : 0x333333,
shininess: 30
}));
// Up (+y) - White
materials.push(new THREE.MeshPhongMaterial({
color: y === 1 ? faceColors.up : 0x333333,
shininess: 30
}));
// Down (-y) - Yellow
materials.push(new THREE.MeshPhongMaterial({
color: y === -1 ? faceColors.down : 0x333333,
shininess: 30
}));
// Front (+z) - Green
materials.push(new THREE.MeshPhongMaterial({
color: z === 1 ? faceColors.front : 0x333333,
shininess: 30
}));
// Back (-z) - Blue
materials.push(new THREE.MeshPhongMaterial({
color: z === -1 ? faceColors.back : 0x333333,
shininess: 30
}));
const geometry = new THREE.BoxGeometry(size, size, size);
const cubie = new THREE.Mesh(geometry, materials);
cubie.position.set(x * (size + gap), y * (size + gap), z * (size + gap));
cubie.castShadow = true;
cubie.receiveShadow = true;
// Store original position for solving
cubie.userData = { x, y, z };
return cubie;
}
// Create all 27 cubies
for (let x = -1; x <= 1; x++) {
for (let y = -1; y <= 1; y++) {
for (let z = -1; z <= 1; z++) {
const cubie = createCubie(x, y, z);
cubeGroup.add(cubie);
cubies.push(cubie);
}
}
}
scene.add(cubeGroup);
// Animation state
let isAnimating = false;
let moveQueue = [];
let moveCount = 0;
let scrambleMoves = [];
// Move definitions
const moves = {
'R': { axis: 'x', layer: 1, angle: -Math.PI / 2 },
'R\'': { axis: 'x', layer: 1, angle: Math.PI / 2 },
'L': { axis: 'x', layer: -1, angle: Math.PI / 2 },
'L\'': { axis: 'x', layer: -1, angle: -Math.PI / 2 },
'U': { axis: 'y', layer: 1, angle: -Math.PI / 2 },
'U\'': { axis: 'y', layer: 1, angle: Math.PI / 2 },
'D': { axis: 'y', layer: -1, angle: Math.PI / 2 },
'D\'': { axis: 'y', layer: -1, angle: -Math.PI / 2 },
'F': { axis: 'z', layer: 1, angle: -Math.PI / 2 },
'F\'': { axis: 'z', layer: 1, angle: Math.PI / 2 },
'B': { axis: 'z', layer: -1, angle: Math.PI / 2 },
'B\'': { axis: 'z', layer: -1, angle: -Math.PI / 2 }
};
// Get cubies in a layer
function getCubiesInLayer(axis, layer) {
return cubies.filter(cubie => {
const pos = cubie.position;
return Math.round(pos[axis]) === layer * (size + gap);
});
}
// Perform a move
function performMove(moveName) {
const move = moves[moveName];
if (!move) return;
const layerCubies = getCubiesInLayer(move.axis, move.layer);
const pivot = new THREE.Group();
// Add cubies to pivot
layerCubies.forEach(cubie => {
cubeGroup.remove(cubie);
pivot.add(cubie);
});
cubeGroup.add(pivot);
// Animate rotation
const targetRotation = move.angle;
let currentRotation = 0;
const duration = 300; // ms
const startTime = Date.now();
function animateMove() {
const elapsed = Date.now() - startTime;
const progress = Math.min(elapsed / duration, 1);
const easedProgress = 1 - Math.pow(1 - progress, 3); // easeOutCubic
const rotation = targetRotation * easedProgress;
const delta = rotation - currentRotation;
if (move.axis === 'x') pivot.rotation.x += delta;
else if (move.axis === 'y') pivot.rotation.y += delta;
else if (move.axis === 'z') pivot.rotation.z += delta;
currentRotation = rotation;
if (progress < 1) {
requestAnimationFrame(animateMove);
} else {
// Snap to exact rotation
if (move.axis === 'x') pivot.rotation.x = targetRotation;
else if (move.axis === 'y') pivot.rotation.y = targetRotation;
else if (move.axis === 'z') pivot.rotation.z = targetRotation;
// Remove pivot and add cubies back
pivot.updateMatrixWorld();
layerCubies.forEach(cubie => {
const worldPos = new THREE.Vector3();
cubie.getWorldPosition(worldPos);
const worldQuat = new THREE.Quaternion();
cubie.getWorldQuaternion(worldQuat);
pivot.remove(cubie);
cubeGroup.add(cubie);
cubie.position.copy(worldPos);
cubie.quaternion.copy(worldQuat);
// Round positions to avoid floating point errors
cubie.position.x = Math.round(cubie.position.x * 10) / 10;
cubie.position.y = Math.round(cubie.position.y * 10) / 10;
cubie.position.z = Math.round(cubie.position.z * 10) / 10;
});
cubeGroup.remove(pivot);
// Process next move
moveCount++;
document.getElementById('moveCounter').textContent = moveCount + ' moves';
if (moveQueue.length > 0) {
const nextMove = moveQueue.shift();
setTimeout(() => performMove(nextMove), 50);
} else {
isAnimating = false;
}
}
}
animateMove();
}
// Queue a move
function queueMove(moveName) {
moveQueue.push(moveName);
if (!isAnimating) {
isAnimating = true;
const nextMove = moveQueue.shift();
setTimeout(() => performMove(nextMove), 50);
}
}
// Scramble function
function scrambleCube() {
if (isAnimating) return;
// Clear any pending moves
moveQueue = [];
scrambleMoves = [];
const moveNames = Object.keys(moves);
const numMoves = Math.floor(Math.random() * 6) + 15; // 15-20 moves
let lastMove = '';
for (let i = 0; i < numMoves; i++) {
let move;
do {
move = moveNames[Math.floor(Math.random() * moveNames.length)];
} while (move.replace("'", "") === lastMove.replace("'", ""));
lastMove = move;
scrambleMoves.push(move);
queueMove(move);
}
}
// Solve function
function solveCube() {
if (isAnimating) return;
// Clear any pending moves
moveQueue = [];
// Reverse the scramble moves
const reverseMoves = scrambleMoves.slice().reverse().map(move => {
return move.includes("'") ? move.replace("'", "") : move + "'";
});
scrambleMoves = [];
reverseMoves.forEach(move => queueMove(move));
}
// Keyboard shortcuts
document.addEventListener('keydown', (e) => {
if (e.key.toLowerCase() === 'r') {
scrambleCube();
} else if (e.key.toLowerCase() === 's') {
solveCube();
}
});
// Window resize
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// Animation loop
function animate() {
requestAnimationFrame(animate);
controls.update();
renderer.render(scene, camera);
}
animate();
// Initial scramble for visual interest
setTimeout(() => {
scrambleCube();
}, 500);
</script>
</body>
</html>
ログインして完全なプロンプトを表示
次で続行:
ログインすると、次に同意したことになります: 利用規約 と プライバシーポリシー
使い方
このプロンプトは coding 向けに設計されています。上の内容をコピーして、お好みの AI ツールに貼り付けてください。
最良の結果を得るには、プレースホルダー(角括弧や大文字で示された部分)を具体的な要件に置き換えてください。
ノート
0 件のコメント