Spaces:
Running
Running
| <html> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>3D Card Game with Physics</title> | |
| <style> | |
| body { margin: 0; } | |
| canvas { display: block; } | |
| </style> | |
| <script src="https://cdn.jsdelivr.net/npm/three@0.132.2/build/three.min.js"></script> | |
| <script src="https://cdnjs.cloudflare.com/ajax/libs/cannon.js/0.6.2/cannon.min.js"></script> | |
| </head> | |
| <body> | |
| <canvas id="gameCanvas"></canvas> | |
| <script> | |
| var scene = new THREE.Scene(); | |
| var camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000); | |
| camera.position.set(0, 30, 100); | |
| var renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('gameCanvas') }); | |
| renderer.setSize(window.innerWidth, window.innerHeight); | |
| // Physics world setup | |
| var world = new CANNON.World(); | |
| world.gravity.set(0, -9.82, 0); // Apply gravity in the negative y direction | |
| // Lighting | |
| var ambientLight = new THREE.AmbientLight(0x404040); // Soft white light | |
| scene.add(ambientLight); | |
| var directionalLight = new THREE.DirectionalLight(0xffffff, 0.5); | |
| directionalLight.position.set(0, 1, 1); | |
| scene.add(directionalLight); | |
| // Table surface with physics | |
| var tableGeometry = new THREE.BoxGeometry(100, 1, 100); | |
| var tableMaterial = new THREE.MeshLambertMaterial({ color: 0x8B4513 }); // Brown color for the table | |
| var table = new THREE.Mesh(tableGeometry, tableMaterial); | |
| table.position.set(0, -0.5, 0); // Adjust position to align with the physics body | |
| scene.add(table); | |
| // Create physics body for the table | |
| var tableShape = new CANNON.Box(new CANNON.Vec3(50, 0.5, 50)); // Half extents match the Three.js geometry | |
| var tableBody = new CANNON.Body({ | |
| mass: 0, // Mass of 0 makes the body static | |
| position: new CANNON.Vec3(0, -0.5, 0), // Match the position of the Three.js mesh | |
| shape: tableShape | |
| }); | |
| world.addBody(tableBody); | |
| // Card geometry and material | |
| var cardGeometry = new THREE.BoxGeometry(5, 0.1, 7); // Generic card size | |
| var cards = []; | |
| var cardBodies = []; // For physics bodies | |
| // Generate colors for cards | |
| var colors = []; | |
| for (let i = 0; i < 52; i++) { | |
| colors.push(Math.random() * 0xffffff); // Generate random color | |
| } | |
| // Shuffle colors | |
| function shuffleArray(array) { | |
| for (let i = array.length - 1; i > 0; i--) { | |
| const j = Math.floor(Math.random() * (i + 1)); | |
| [array[i], array[j]] = [array[j], array[i]]; // Swap | |
| } | |
| } | |
| shuffleArray(colors); // Shuffle the colors array to simulate shuffling cards | |
| // Card creation with physics and color based on shuffle | |
| function addCard(x, y, z, colorIndex) { | |
| var cardMaterial = new THREE.MeshLambertMaterial({ color: colors[colorIndex] }); | |
| var card = new THREE.Mesh(cardGeometry, cardMaterial); | |
| card.position.set(x, y, z); | |
| scene.add(card); | |
| cards.push(card); | |
| // Physics for card | |
| var cardShape = new CANNON.Box(new CANNON.Vec3(2.5, 0.05, 3.5)); | |
| var cardBody = new CANNON.Body({ mass: 0.1 }); | |
| cardBody.addShape(cardShape); | |
| cardBody.position.set(x, y, z); | |
| world.addBody(cardBody); | |
| cardBodies.push(cardBody); | |
| } | |
| // Create a stack of cards | |
| for (let i = 0; i < 52; i++) { | |
| addCard(0, i * 0.2 + 1, 0, i); // Position cards in a stack | |
| } | |
| function animate() { | |
| requestAnimationFrame(animate); | |
| // Update physics world | |
| world.step(1 / 60); | |
| // Sync Three.js objects with physics objects | |
| for (let i = 0; i < cardBodies.length; i++) { | |
| cards[i].position.copy(cardBodies[i].position); | |
| cards[i].quaternion.copy(cardBodies[i].quaternion); | |
| } | |
| renderer.render(scene, camera); | |
| } | |
| animate(); | |
| </script> | |
| </body> | |
| </html> | |