Juego 3D de Angry Birds con Three.js
De Wikiprompt, la enciclopedia libre de prompts
Juego 3D de Angry Birds con Three.js Una solicitud de desarrollo de juego de un solo prompt para crear un juego 3D estilo Angry Birds usando three.js o HTML, con un fondo blanco para claridad.
Medios relacionados
Contenido del PromptGuardar
🌐
I'll create a complete Angry Birds-style physics game using Three.js with a clean white background. This will be a single HTML file with everything included.
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Angry Birds Style Game - Three.js</title>
<style>
body {
margin: 0;
overflow: hidden;
font-family: Arial, sans-serif;
background-color: #ffffff;
}
#info {
position: absolute;
top: 10px;
left: 50%;
transform: translateX(-50%);
color: #333;
font-size: 18px;
background: rgba(255,255,255,0.9);
padding: 10px 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
z-index: 100;
text-align: center;
}
#score {
position: absolute;
top: 10px;
right: 20px;
color: #333;
font-size: 20px;
font-weight: bold;
background: rgba(255,255,255,0.9);
padding: 10px 20px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
z-index: 100;
}
#controls {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
color: #555;
font-size: 14px;
background: rgba(255,255,255,0.9);
padding: 8px 16px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
z-index: 100;
text-align: center;
}
#restart {
position: absolute;
top: 10px;
left: 20px;
color: #fff;
font-size: 16px;
background: #e74c3c;
padding: 10px 20px;
border-radius: 8px;
border: none;
cursor: pointer;
z-index: 100;
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
}
#restart:hover {
background: #c0392b;
}
canvas {
display: block;
}
</style>
</head>
<body>
<div id="info">🎯 Drag to aim and release to launch!</div>
<div id="score">Score: <span id="scoreValue">0</span></div>
<button id="restart">🔄 Restart</button>
<div id="controls">Mouse: Drag from bird to aim | Release to launch</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 src="https://cdn.jsdelivr.net/npm/cannon@0.6.2/dist/cannon.min.js"></script>
<script>
// ====== GAME SETUP ======
const scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff); // White background
const camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.set(0, 8, 15);
camera.lookAt(0, 2, 0);
const renderer = new THREE.WebGLRenderer({ antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
document.body.appendChild(renderer.domElement);
// ====== PHYSICS WORLD ======
const world = new CANNON.World();
world.gravity.set(0, -9.82, 0);
world.broadphase = new CANNON.NaiveBroadphase();
world.defaultContactMaterial.friction = 0.5;
world.defaultContactMaterial.restitution = 0.3;
// ====== LIGHTING ======
const ambientLight = new THREE.AmbientLight(0x404040, 0.6);
scene.add(ambientLight);
const directionalLight = new THREE.DirectionalLight(0xffffff, 1);
directionalLight.position.set(5, 10, 7);
directionalLight.castShadow = true;
directionalLight.shadow.mapSize.width = 1024;
directionalLight.shadow.mapSize.height = 1024;
scene.add(directionalLight);
const fillLight = new THREE.DirectionalLight(0xffffff, 0.3);
fillLight.position.set(-5, 3, -5);
scene.add(fillLight);
// ====== GROUND ======
const groundGeo = new THREE.PlaneGeometry(30, 30);
const groundMat = new THREE.MeshStandardMaterial({
color: 0xcccccc,
roughness: 0.8
});
const groundMesh = new THREE.Mesh(groundGeo, groundMat);
groundMesh.rotation.x = -Math.PI / 2;
groundMesh.position.y = 0;
groundMesh.receiveShadow = true;
scene.add(groundMesh);
// Physics ground
const groundBody = new CANNON.Body({
mass: 0,
shape: new CANNON.Plane()
});
groundBody.quaternion.setFromAxisAngle(new CANNON.Vec3(1, 0, 0), -Math.PI / 2);
world.addBody(groundBody);
// ====== GAME OBJECTS ======
const objects = [];
const physicsBodies = [];
// Helper to create physics-linked objects
function createPhysicsObject(geometry, material, position, mass = 1, isStatic = false) {
const mesh = new THREE.Mesh(geometry, material);
mesh.castShadow = true;
mesh.receiveShadow = true;
mesh.position.copy(position);
scene.add(mesh);
// Create physics body
let shape;
if (geometry.type === 'BoxGeometry') {
shape = new CANNON.Box(new CANNON.Vec3(
geometry.parameters.width / 2,
geometry.parameters.height / 2,
geometry.parameters.depth / 2
));
} else if (geometry.type === 'SphereGeometry') {
shape = new CANNON.Sphere(geometry.parameters.radius);
} else if (geometry.type === 'CylinderGeometry') {
shape = new CANNON.Cylinder(
geometry.parameters.radiusTop,
geometry.parameters.radiusBottom,
geometry.parameters.height,
8
);
}
const body = new CANNON.Body({
mass: isStatic ? 0 : mass,
shape: shape,
position: new CANNON.Vec3(position.x, position.y, position.z)
});
world.addBody(body);
objects.push({ mesh, body });
physicsBodies.push(body);
return { mesh, body };
}
// ====== CREATE LEVEL ======
function createLevel() {
// Clear existing objects
objects.forEach(obj => {
scene.remove(obj.mesh);
world.removeBody(obj.body);
});
objects.length = 0;
physicsBodies.length = 0;
// Create ground blocks (static)
const blockMat = new THREE.MeshStandardMaterial({
color: 0x8B4513,
roughness: 0.7
});
const woodMat = new THREE.MeshStandardMaterial({
color: 0xDEB887,
roughness: 0.6
});
const glassMat = new THREE.MeshStandardMaterial({
color: 0x87CEEB,
roughness: 0.1,
transparent: true,
opacity: 0.8
});
const stoneMat = new THREE.MeshStandardMaterial({
color: 0x808080,
roughness: 0.9
});
// Base platform
createPhysicsObject(
new THREE.BoxGeometry(6, 0.5, 1),
blockMat,
new THREE.Vector3(6, 0.25, 0),
0, true
);
// Vertical blocks
createPhysicsObject(
new THREE.BoxGeometry(0.5, 2, 1),
woodMat,
new THREE.Vector3(4.5, 1, 0),
2
);
createPhysicsObject(
new THREE.BoxGeometry(0.5, 2, 1),
woodMat,
new THREE.Vector3(7.5, 1, 0),
2
);
// Horizontal block on top
createPhysicsObject(
new THREE.BoxGeometry(3.5, 0.5, 1),
woodMat,
new THREE.Vector3(6, 2.25, 0),
1.5
);
// Second level
createPhysicsObject(
new THREE.BoxGeometry(0.5, 1.5, 1),
glassMat,
new THREE.Vector3(5, 3, 0),
1
);
createPhysicsObject(
new THREE.BoxGeometry(0.5, 1.5, 1),
glassMat,
new THREE.Vector3(7, 3, 0),
1
);
// Top block
createPhysicsObject(
new THREE.BoxGeometry(2.5, 0.5, 1),
stoneMat,
new THREE.Vector3(6, 3.75, 0),
3
);
// Pigs (targets)
const pigMat = new THREE.MeshStandardMaterial({
color: 0x2ECC71,
roughness: 0.3
});
// Pig 1 - behind structure
createPhysicsObject(
new THREE.SphereGeometry(0.4, 16, 16),
pigMat,
new THREE.Vector3(6, 0.4, 0.5),
1
);
// Pig 2 - on top
createPhysicsObject(
new THREE.SphereGeometry(0.35, 16, 16),
pigMat,
new THREE.Vector3(6, 4.2, 0),
0.8
);
// Pig 3 - behind
createPhysicsObject(
new THREE.SphereGeometry(0.3, 16, 16),
pigMat,
new THREE.Vector3(8, 0.3, 0.3),
0.6
);
}
// ====== BIRD ======
let birdMesh, birdBody;
let isDragging = false;
let dragStart = new THREE.Vector3();
let dragEnd = new THREE.Vector3();
let birdLaunched = false;
let score = 0;
let birdsRemaining = 3;
function createBird() {
// Remove old bird if exists
if (birdMesh) {
scene.remove(birdMesh);
world.removeBody(birdBody);
}
const birdGeo = new THREE.SphereGeometry(0.4, 16, 16);
const birdMat = new THREE.MeshStandardMaterial({
color: 0xFF0000,
roughness: 0.4
});
birdMesh = new THREE.Mesh(birdGeo, birdMat);
birdMesh.castShadow = true;
birdMesh.position.set(0, 1, 0);
scene.add(birdMesh);
// Add eyes
const eyeMat = new THREE.MeshStandardMaterial({ color: 0xFFFFFF });
const pupilMat = new THREE.MeshStandardMaterial({ color: 0x000000 });
const eyeGeo = new THREE.SphereGeometry(0.08, 8, 8);
const pupilGeo = new THREE.SphereGeometry(0.04, 8, 8);
const leftEye = new THREE.Mesh(eyeGeo, eyeMat);
leftEye.position.set(-0.15, 0.15, 0.35);
birdMesh.add(leftEye);
const rightEye = new THREE.Mesh(eyeGeo, eyeMat);
rightEye.position.set(0.15, 0.15, 0.35);
birdMesh.add(rightEye);
const leftPupil = new THREE.Mesh(pupilGeo, pupilMat);
leftPupil.position.set(-0.15, 0.15, 0.43);
birdMesh.add(leftPupil);
const rightPupil = new THREE.Mesh(pupilGeo, pupilMat);
rightPupil.position.set(0.15, 0.15, 0.43);
birdMesh.add(rightPupil);
// Physics body
birdBody = new CANNON.Body({
mass: 2,
shape: new CANNON.Sphere(0.4),
position: new CANNON.Vec3(0, 1, 0)
});
world.addBody(birdBody);
birdLaunched = false;
}
// ====== TRAJECTORY LINE ======
const trajectoryPoints = [];
const trajectoryLine = new THREE.Line(
new THREE.BufferGeometry(),
new THREE.LineBasicMaterial({ color: 0x333333, linewidth: 2 })
);
scene.add(trajectoryLine);
function updateTrajectory() {
if (!isDragging || birdLaunched) {
trajectoryLine.visible = false;
return;
}
trajectoryLine.visible = true;
const start = birdMesh.position.clone();
const force = dragStart.clone().sub(dragEnd);
const velocity = force.multiplyScalar(5);
const points = [];
const gravity = new THREE.Vector3(0, -9.82, 0);
for (let i = 0; i < 30; i++) {
const t = i * 0.05;
const point = start.clone().add(velocity.clone().multiplyScalar(t));
point.y += 0.5 * gravity.y * t * t;
points.push(point);
}
trajectoryLine.geometry.setFromPoints(points);
}
// ====== MOUSE CONTROLS ======
const raycaster = new THREE.Raycaster();
const mouse = new THREE.Vector2();
const plane = new THREE.Plane(new THREE.Vector3(0, 1, 0), 0);
const intersection = new THREE.Vector3();
function onMouseDown(event) {
if (birdLaunched || birdsRemaining <= 0) return;
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
if (raycaster.ray.intersectObject(birdMesh).length > 0) {
isDragging = true;
dragStart.copy(birdMesh.position);
raycaster.ray.intersectPlane(plane, intersection);
dragEnd.copy(intersection);
}
}
function onMouseMove(event) {
if (!isDragging) return;
mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(mouse, camera);
raycaster.ray.intersectPlane(plane, intersection);
dragEnd.copy(intersection);
updateTrajectory();
}
function onMouseUp(event) {
if (!isDragging) return;
isDragging = false;
const force = dragStart.clone().sub(dragEnd);
const power = force.length();
if (power > 0.5) {
// Launch the bird
const launchForce = force.multiplyScalar(5);
birdBody.velocity.set(launchForce.x, launchForce.y, launchForce.z);
birdLaunched = true;
trajectoryLine.visible = false;
birdsRemaining--;
updateScore();
}
}
// ====== SCORE & UI ======
function updateScore() {
document.getElementById('scoreValue').textContent = score;
}
function checkPigs() {
objects.forEach(obj => {
if (obj.mesh.material.color.getHex() === 0x2ECC71) {
// Check if pig is destroyed (fell or hit hard)
if (obj.body.position.y < -1 || obj.body.velocity.length() > 5) {
scene.remove(obj.mesh);
world.removeBody(obj.body);
score += 100;
updateScore();
}
}
});
}
// ====== RESTART ======
function restartGame() {
score = 0;
birdsRemaining = 3;
updateScore();
createLevel();
createBird();
}
document.getElementById('restart').addEventListener('click', restartGame);
// ====== EVENT LISTENERS ======
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 ======
function animate() {
requestAnimationFrame(animate);
// Step physics
world.step(1/60);
// Update mesh positions from physics
objects.forEach(obj => {
obj.mesh.position.copy(obj.body.position);
obj.mesh.quaternion.copy(obj.body.quaternion);
});
if (birdMesh && birdBody) {
birdMesh.position.copy(birdBody.position);
birdMesh.quaternion.copy(birdBody.quaternion);
}
// Check if bird is out of bounds
if (birdLaunched && birdBody.position.x > 15) {
if (birdsRemaining > 0) {
createBird();
}
}
// Check pig destruction
checkPigs();
// Update trajectory
updateTrajectory();
renderer.render(scene, camera);
}
// ====== INITIALIZE ======
createLevel();
createBird();
animate();
</script>
</body>
</html>
```
This game features:
1. **White background** - clearly shows all objects
2. **Physics engine** (Cannon.js) - realistic gravity, collisions, and destruction
3. **Drag-to-launch mechanic** - click and drag from the bird to aim, release to launch
4. **Trajectory preview** - dotted line showing predicted path
5. **Destructible structures** - wooden, glass, and stone blocks with different properties
6. **Pigs to destroy** - green targets worth 100 points each
7. **Score system** - tracks your points
8. **Restart button** - reset the game
9. **3 birds per round** - limited attempts
10. **3D graphics** - with shadows, lighting, and detailed models
**How to play:**
- Click and drag on the red bird to aim
- Release to launch
- Try to knock down the structures and hit the green pigs
- Score points for each pig destroyed
- Restart anytime with the red button
The game uses Three.js for 3D rendering and Cannon.js for physics simulation, creating a satisfying Angry Birds experience in the browser.
Iniciá sesión para ver el prompt completo
Continuar con:
Al iniciar sesión, aceptás nuestros Términos de uso y Política de privacidad
Uso
Este prompt está diseñado para usarse con coding. Copiá el contenido de arriba y pegalo en tu herramienta de IA preferida.
Para mejores resultados, personalizá los marcadores (indicados con corchetes o mayúsculas) con tus requisitos específicos.
Referencias
- Categoría: Prompts de coding
- Fuente: https://x.com/TimJayas/status/2088206050940113201
Discusión
0 comentarios