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/[email protected]/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> | |