Jeu spatial d'intrication quantique
De Wikiprompt, l’encyclopédie libre de prompts
Jeu spatial d'intrication quantique Une invite pour créer un jeu Three.js en fichier unique où les joueurs associent des amas de particules 3D par orientation spatiale, avec des effets de fusion basés sur la physique.
Contenu du PromptEnregistrer
🌐
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Quantum Entanglement</title>
<style>
body {
margin: 0;
overflow: hidden;
background: #ffffff;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
#info {
position: absolute;
top: 20px;
left: 50%;
transform: translateX(-50%);
color: #333;
font-size: 14px;
background: rgba(255, 255, 255, 0.8);
padding: 10px 20px;
border-radius: 30px;
backdrop-filter: blur(10px);
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
z-index: 100;
pointer-events: none;
letter-spacing: 0.5px;
}
#status {
position: absolute;
bottom: 30px;
left: 50%;
transform: translateX(-50%);
color: #555;
font-size: 13px;
background: rgba(255, 255, 255, 0.7);
padding: 8px 16px;
border-radius: 20px;
backdrop-filter: blur(8px);
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.05);
z-index: 100;
pointer-events: none;
transition: all 0.3s ease;
}
#status.match {
color: #2e7d32;
background: rgba(232, 245, 233, 0.9);
}
#status.error {
color: #c62828;
background: rgba(255, 235, 238, 0.9);
}
canvas {
display: block;
}
.hint {
position: absolute;
top: 80px;
left: 50%;
transform: translateX(-50%);
color: #999;
font-size: 12px;
z-index: 100;
pointer-events: none;
font-style: italic;
}
</style>
</head>
<body>
<div id="info">Quantum Entanglement - Click to unfold, find matching pairs</div>
<div class="hint">Drag to rotate clusters | Click to unfold/fold</div>
<div id="status">Select a cluster to begin</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
<script>
// ============ CORE SETUP ============
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 0, 12);
camera.lookAt(0, 0, 0);
const renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
// ============ 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 backLight = new THREE.DirectionalLight(0x88ccff, 0.3);
backLight.position.set(-5, -3, -5);
scene.add(backLight);
// ============ GEOMETRY DEFINITIONS ============
// Define unique 3D geometric matrices (topologies)
const topologyDefinitions = [
// Tetrahedron
{
type: 'tetrahedron',
vertices: [
[0, 1, 0], [0.94, -0.33, 0], [-0.47, -0.33, 0.82], [-0.47, -0.33, -0.82]
],
edges: [[0,1],[0,2],[0,3],[1,2],[2,3],[3,1]]
},
// Cube
{
type: 'cube',
vertices: [
[-0.7,-0.7,-0.7], [0.7,-0.7,-0.7], [0.7,0.7,-0.7], [-0.7,0.7,-0.7],
[-0.7,-0.7,0.7], [0.7,-0.7,0.7], [0.7,0.7,0.7], [-0.7,0.7,0.7]
],
edges: [[0,1],[1,2],[2,3],[3,0],[4,5],[5,6],[6,7],[7,4],[0,4],[1,5],[2,6],[3,7]]
},
// Octahedron
{
type: 'octahedron',
vertices: [
[0, 1, 0], [0, -1, 0], [1, 0, 0], [-1, 0, 0], [0, 0, 1], [0, 0, -1]
],
edges: [[0,2],[0,3],[0,4],[0,5],[1,2],[1,3],[1,4],[1,5],[2,4],[4,3],[3,5],[5,2]]
},
// Icosahedron (simplified)
{
type: 'icosahedron',
vertices: [
[0, 1, 0.618], [0, -1, 0.618], [0, 1, -0.618], [0, -1, -0.618],
[1, 0.618, 0], [-1, 0.618, 0], [1, -0.618, 0], [-1, -0.618, 0],
[0.618, 0, 1], [-0.618, 0, 1], [0.618, 0, -1], [-0.618, 0, -1]
],
edges: [[0,1],[0,4],[0,5],[0,8],[0,9],[1,6],[1,7],[1,8],[1,9],[2,3],[2,4],[2,5],[2,10],[2,11],[3,6],[3,7],[3,10],[3,11],[4,8],[4,10],[5,9],[5,11],[6,8],[6,10],[7,9],[7,11]]
}
];
// ============ PARTICLE SYSTEM ============
class ParticleSystem {
constructor() {
this.particles = [];
this.geometry = new THREE.BufferGeometry();
this.material = new THREE.PointsMaterial({
color: 0x4488ff,
size: 0.08,
transparent: true,
opacity: 0.9,
blending: THREE.AdditiveBlending
});
this.points = new THREE.Points(this.geometry, this.material);
this.points.visible = false;
scene.add(this.points);
}
emit(position, color = 0x4488ff, count = 80) {
for (let i = 0; i < count; i++) {
this.particles.push({
pos: position.clone(),
vel: new THREE.Vector3(
(Math.random() - 0.5) * 0.3,
(Math.random() - 0.5) * 0.3,
(Math.random() - 0.5) * 0.3
),
life: 1.0,
decay: 0.005 + Math.random() * 0.01,
color: color
});
}
this.points.visible = true;
}
update() {
if (this.particles.length === 0) {
this.points.visible = false;
return;
}
const positions = [];
const colors = [];
for (let i = this.particles.length - 1; i >= 0; i--) {
const p = this.particles[i];
p.pos.add(p.vel);
p.vel.multiplyScalar(0.98);
p.life -= p.decay;
if (p.life <= 0) {
this.particles.splice(i, 1);
continue;
}
positions.push(p.pos.x, p.pos.y, p.pos.z);
const c = new THREE.Color(p.color);
colors.push(c.r * p.life, c.g * p.life, c.b * p.life);
}
this.geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3));
this.geometry.setAttribute('color', new THREE.Float32BufferAttribute(colors, 3));
this.points.material.vertexColors = true;
}
}
const particleSystem = new ParticleSystem();
// ============ CLUSTER CLASS ============
class Cluster {
constructor(position, topologyIndex, id) {
this.id = id;
this.topologyIndex = topologyIndex;
this.position = position.clone();
this.rotation = new THREE.Euler(
Math.random() * Math.PI * 2,
Math.random() * Math.PI * 2,
Math.random() * Math.PI * 2
);
this.quaternion = new THREE.Quaternion().setFromEuler(this.rotation);
this.isUnfolded = false;
this.isMatched = false;
this.isDragging = false;
// Create group
this.group = new THREE.Group();
this.group.position.copy(this.position);
this.group.quaternion.copy(this.quaternion);
// Create collapsed sphere (frosted glass)
const sphereGeo = new THREE.SphereGeometry(0.5, 32, 32);
const sphereMat = new THREE.MeshPhysicalMaterial({
color: 0xffffff,
transparent: true,
opacity: 0.3,
roughness: 0.1,
metalness: 0.1,
transmission: 0.9,
thickness: 0.5,
envMapIntensity: 1.0
});
this.sphere = new THREE.Mesh(sphereGeo, sphereMat);
this.sphere.castShadow = true;
this.group.add(this.sphere);
// Create unfolded geometry (hidden initially)
this.geometryGroup = new THREE.Group();
this.buildGeometry(topologyIndex);
this.geometryGroup.visible = false;
this.group.add(this.geometryGroup);
// Add glow ring
const ringGeo = new THREE.RingGeometry(0.6, 0.7, 32);
const ringMat = new THREE.MeshBasicMaterial({
color: 0x88ccff,
transparent: true,
opacity: 0.3,
side: THREE.DoubleSide
});
this.ring = new THREE.Mesh(ringGeo, ringMat);
this.ring.rotation.x = Math.PI / 2;
this.group.add(this.ring);
scene.add(this.group);
}
buildGeometry(topologyIndex) {
const def = topologyDefinitions[topologyIndex];
// Create vertices as small spheres
def.vertices.forEach((v, i) => {
const sphereGeo = new THREE.SphereGeometry(0.06, 8, 8);
const sphereMat = new THREE.MeshPhysicalMaterial({
color: 0x4488ff,
transparent: true,
opacity: 0.8,
roughness: 0.2,
metalness: 0.3,
transmission: 0.5
});
const mesh = new THREE.Mesh(sphereGeo, sphereMat);
mesh.position.set(v[0], v[1], v[2]);
this.geometryGroup.add(mesh);
});
// Create edges as lines
const lineMat = new THREE.LineBasicMaterial({
color: 0x4488ff,
transparent: true,
opacity: 0.6
});
def.edges.forEach(([a, b]) => {
const points = [
new THREE.Vector3(def.vertices[a][0], def.vertices[a][1], def.vertices[a][2]),
new THREE.Vector3(def.vertices[b][0], def.vertices[b][1], def.vertices[b][2])
];
const lineGeo = new THREE.BufferGeometry().setFromPoints(points);
const line = new THREE.Line(lineGeo, lineMat);
this.geometryGroup.add(line);
});
}
toggleUnfold() {
this.isUnfolded = !this.isUnfolded;
this.sphere.visible = !this.isUnfolded;
this.geometryGroup.visible = this.isUnfolded;
this.ring.visible = !this.isUnfolded;
if (this.isUnfolded) {
// Emit small particle burst
particleSystem.emit(this.position, 0x4488ff, 20);
}
}
update(delta) {
// Gentle floating animation
if (!this.isDragging && !this.isMatched) {
this.group.position.y += Math.sin(Date.now() * 0.001 + this.id) * 0.0005;
}
// Rotate ring
if (this.ring) {
this.ring.rotation.z += delta * 0.5;
}
}
dispose() {
scene.remove(this.group);
// Clean up geometries
this.group.traverse((child) => {
if (child.geometry) child.geometry.dispose();
if (child.material) {
if (Array.isArray(child.material)) {
child.material.forEach(m => m.dispose());
} else {
child.material.dispose();
}
}
});
}
}
// ============ CREATE CLUSTERS ============
const clusters = [];
const clusterPositions = [
new THREE.Vector3(-3, 1.5, 0),
new THREE.Vector3(3, 1.5, 0),
new THREE.Vector3(-3, -1.5, 0),
new THREE.Vector3(3, -1.5, 0),
new THREE.Vector3(0, 0, -2),
new THREE.Vector3(0, 0, 2)
];
// Create 6 clusters with 3 matching pairs
const topologyAssignments = [0, 0, 1, 1, 2, 2]; // 3 pairs
// Shuffle
for (let i = topologyAssignments.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[topologyAssignments[i], topologyAssignments[j]] = [topologyAssignments[j], topologyAssignments[i]];
}
clusterPositions.forEach((pos, i) => {
const cluster = new Cluster(pos, topologyAssignments[i], i);
clusters.push(cluster);
});
// ============ INTERACTION ============
let selectedCluster = null;
let isDragging = false;
let previousMouse = { x: 0, y: 0 };
let dragCluster = null;
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
function onMouseClick(event) {
if (isDragging) return;
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
// Check clusters
for (const cluster of clusters) {
if (cluster.isMatched) continue;
const intersects = raycaster.intersectObject(cluster.sphere, true);
if (intersects.length > 0) {
if (selectedCluster && selectedCluster !== cluster && selectedCluster.isUnfolded) {
// Check match
if (selectedCluster.topologyIndex === cluster.topologyIndex) {
// MATCH FOUND
handleMatch(selectedCluster, cluster);
} else {
// Wrong match
document.getElementById('status').textContent = 'No entanglement - try again';
document.getElementById('status').className = 'error';
setTimeout(() => {
document.getElementById('status').textContent = 'Select a cluster to begin';
document.getElementById('status').className = '';
}, 1500);
selectedCluster.toggleUnfold();
selectedCluster = null;
}
} else {
// Toggle unfold
if (selectedCluster && selectedCluster !== cluster) {
selectedCluster.toggleUnfold();
}
cluster.toggleUnfold();
selectedCluster = cluster;
document.getElementById('status').textContent = 'Cluster unfolded - find its match';
document.getElementById('status').className = '';
}
return;
}
}
// Click empty space - deselect
if (selectedCluster) {
selectedCluster.toggleUnfold();
selectedCluster = null;
document.getElementById('status').textContent = 'Select a cluster to begin';
document.getElementById('status').className = '';
}
}
function handleMatch(clusterA, clusterB) {
document.getElementById('status').textContent = 'ENTANGLED!';
document.getElementById('status').className = 'match';
// Mark as matched
clusterA.isMatched = true;
clusterB.isMatched = true;
// Calculate implosion vectors
const midpoint = new THREE.Vector3().addVectors(clusterA.position, clusterB.position).multiplyScalar(0.5);
// Emit particles at both clusters
particleSystem.emit(clusterA.position, 0x4488ff, 60);
particleSystem.emit(clusterB.position, 0x4488ff, 60);
// Animate implosion
const startTime = Date.now();
const duration = 1000;
function animateImplosion() {
const elapsed = Date.now() - startTime;
const progress = Math.min(elapsed / duration, 1);
// Move clusters toward midpoint
clusterA.group.position.lerp(midpoint, 0.05);
clusterB.group.position.lerp(midpoint, 0.05);
// Scale down
const scale = 1 - progress * 0.8;
clusterA.group.scale.setScalar(scale);
clusterB.group.scale.setScalar(scale);
// Emit particles along the way
if (Math.random() < 0.3) {
particleSystem.emit(clusterA.group.position, 0x88ccff, 5);
particleSystem.emit(clusterB.group.position, 0x88ccff, 5);
}
if (progress < 1) {
requestAnimationFrame(animateImplosion);
} else {
// Destroy clusters
clusterA.dispose();
clusterB.dispose();
// Big particle burst
particleSystem.emit(midpoint, 0x88ccff, 100);
particleSystem.emit(midpoint, 0x4488ff, 80);
document.getElementById('status').textContent = 'Clusters fused!';
setTimeout(() => {
document.getElementById('status').textContent = 'Select a cluster to begin';
document.getElementById('status').className = '';
}, 2000);
selectedCluster = null;
// Check win condition
const remaining = clusters.filter(c => !c.isMatched);
if (remaining.length === 0) {
document.getElementById('status').textContent = 'ALL CLUSTERS ENTANGLED!';
document.getElementById('status').className = 'match';
}
}
}
animateImplosion();
}
// ============ DRAG ROTATION ============
function onMouseDown(event) {
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
for (const cluster of clusters) {
if (cluster.isMatched) continue;
const intersects = raycaster.intersectObject(cluster.sphere, true);
if (intersects.length > 0) {
isDragging = true;
dragCluster = cluster;
cluster.isDragging = true;
previousMouse = { x: event.clientX, y: event.clientY };
break;
}
}
}
function onMouseMove(event) {
if (!isDragging || !dragCluster) return;
const deltaX = event.clientX - previousMouse.x;
const deltaY = event.clientY - previousMouse.y;
const rotationSpeed = 0.01;
const quaternion = new THREE.Quaternion()
.setFromEuler(new THREE.Euler(
deltaY * rotationSpeed,
deltaX * rotationSpeed,
0
));
dragCluster.group.quaternion.multiplyQuaternions(quaternion, dragCluster.group.quaternion);
previousMouse = { x: event.clientX, y: event.clientY };
}
function onMouseUp() {
isDragging = false;
if (dragCluster) {
dragCluster.isDragging = false;
dragCluster = null;
}
}
// ============ EVENT LISTENERS ============
renderer.domElement.addEventListener('click', onMouseClick);
renderer.domElement.addEventListener('mousedown', onMouseDown);
renderer.domElement.addEventListener('mousemove', onMouseMove);
renderer.domElement.addEventListener('mouseup', onMouseUp);
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// ============ ANIMATION LOOP ============
let lastTime = 0;
function animate(time) {
requestAnimationFrame(animate);
const delta = lastTime ? (time - lastTime) / 1000 : 0;
lastTime = time;
// Update clusters
clusters.forEach(cluster => {
if (!cluster.isMatched) {
cluster.update(delta);
}
});
// Update particle system
particleSystem.update();
renderer.render(scene, camera);
}
// Start animation
requestAnimationFrame(animate);
// Initial status
console.log('Quantum Entanglement game initialized');
</script>
</body>
</html>
Connectez-vous pour voir le prompt complet
Continuer avec:
En vous connectant, vous acceptez nos Conditions et Confidentialité
Utilisation
Ce prompt est conçu pour être utilisé avec coding. Copiez le contenu ci-dessus et collez-le dans votre outil d’IA préféré.
Pour de meilleurs résultats, personnalisez les espaces réservés (indiqués par des crochets ou des majuscules) selon vos besoins.
Discussion
0 commentaires