top of page
Buscar

Shadow Fight: Gatos vs Perros 3D




<!DOCTYPE html>

<html lang="es">

<head>

<meta charset="UTF-8">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Shadow Fight: Gatos vs Perros</title>

<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&family=Roboto:wght@300;400;700&display=swap" rel="stylesheet">

<style>

* {

margin: 0;

padding: 0;

box-sizing: border-box;

}


body {

font-family: 'Orbitron', monospace;

background: linear-gradient(135deg, #1a1a2e, #16213e, #0f3460);

overflow: hidden;

color: white;

}


position: relative;

width: 100vw;

height: 100vh;

}


display: block;

}


#ui {

position: absolute;

top: 0;

left: 0;

width: 100%;

height: 100%;

pointer-events: none;

z-index: 100;

}


.health-bar-container {

position: absolute;

top: 20px;

width: 300px;

height: 30px;

border: 3px solid #fff;

border-radius: 15px;

background: rgba(0, 0, 0, 0.7);

overflow: hidden;

}


left: 20px;

}


right: 20px;

}


.health-bar {

width: 100%;

height: 100%;

border-radius: 12px;

transition: width 0.3s ease;

}


.health-cat {

background: linear-gradient(90deg, #ff6b35, #f7931e);

}


.health-dog {

background: linear-gradient(90deg, #4facfe, #00f2fe);

}


.player-name {

position: absolute;

bottom: -25px;

width: 100%;

text-align: center;

font-size: 14px;

font-weight: bold;

}


#round-counter {

position: absolute;

top: 20px;

left: 50%;

transform: translateX(-50%);

background: rgba(0, 0, 0, 0.8);

padding: 10px 20px;

border-radius: 20px;

border: 2px solid #ffd700;

font-size: 18px;

font-weight: bold;

color: #ffd700;

}


position: absolute;

bottom: 20px;

left: 20px;

background: rgba(0, 0, 0, 0.8);

padding: 15px;

border-radius: 10px;

font-size: 12px;

line-height: 1.5;

pointer-events: auto;

}


#avatar-selector {

position: absolute;

top: 50%;

left: 50%;

transform: translate(-50%, -50%);

background: rgba(0, 0, 0, 0.9);

padding: 30px;

border-radius: 20px;

border: 3px solid #ffd700;

text-align: center;

pointer-events: auto;

}


.avatar-grid {

display: grid;

grid-template-columns: repeat(2, 1fr);

gap: 20px;

margin: 20px 0;

}


.avatar-option {

padding: 20px;

border: 2px solid #333;

border-radius: 15px;

cursor: pointer;

transition: all 0.3s ease;

background: rgba(255, 255, 255, 0.1);

}


.avatar-option:hover {

border-color: #ffd700;

background: rgba(255, 215, 0, 0.2);

transform: scale(1.05);

}


.avatar-option.selected {

border-color: #ffd700;

background: rgba(255, 215, 0, 0.3);

}


.start-btn {

background: linear-gradient(45deg, #ff6b35, #f7931e);

border: none;

padding: 15px 30px;

border-radius: 25px;

color: white;

font-family: 'Orbitron', monospace;

font-weight: bold;

font-size: 16px;

cursor: pointer;

transition: all 0.3s ease;

margin-top: 20px;

}


.start-btn:hover {

transform: scale(1.1);

box-shadow: 0 0 20px rgba(255, 107, 53, 0.5);

}


.combo-display {

position: absolute;

top: 50%;

left: 50%;

transform: translate(-50%, -50%);

font-size: 48px;

font-weight: 900;

color: #ffd700;

text-shadow: 0 0 20px rgba(255, 215, 0, 0.8);

opacity: 0;

transition: all 0.5s ease;

pointer-events: none;

}


.combo-display.show {

opacity: 1;

transform: translate(-50%, -50%) scale(1.2);

}


.power-indicator {

position: absolute;

bottom: 80px;

width: 200px;

height: 20px;

border: 2px solid #fff;

border-radius: 10px;

background: rgba(0, 0, 0, 0.7);

overflow: hidden;

}


left: 20px;

}


right: 20px;

}


.power-bar {

height: 100%;

background: linear-gradient(90deg, #9b59b6, #e74c3c);

border-radius: 8px;

transition: width 0.3s ease;

width: 0%;

}


position: absolute;

top: 50%;

left: 50%;

transform: translate(-50%, -50%);

background: rgba(0, 0, 0, 0.95);

padding: 40px;

border-radius: 20px;

border: 3px solid #ffd700;

text-align: center;

font-size: 24px;

display: none;

pointer-events: auto;

}


.hidden {

display: none !important;

}

</style>

</head>

<body>

<div id="gameContainer">

<canvas id="gameCanvas"></canvas>

<div id="ui">

<!-- Barras de vida -->

<div id="player1Health" class="health-bar-container">

<div class="health-bar health-cat" id="p1HealthBar"></div>

<div class="player-name">GATO SOMBRA</div>

</div>

<div id="player2Health" class="health-bar-container">

<div class="health-bar health-dog" id="p2HealthBar"></div>

<div class="player-name">PERRO LUCHA</div>

</div>


<!-- Contador de rondas -->

<div id="round-counter">RONDA 1</div>


<!-- Indicadores de poder -->

<div id="player1Power" class="power-indicator">

<div class="power-bar" id="p1PowerBar"></div>

</div>

<div id="player2Power" class="power-indicator">

<div class="power-bar" id="p2PowerBar"></div>

</div>


<!-- Display de combos -->

<div id="comboDisplay" class="combo-display"></div>


<!-- Controles -->

<div id="controls">

<strong>CONTROLES:</strong><br>

<strong>Jugador 1 (Gato):</strong><br>

WASD - Mover | Q - Puño | E - Patada<br>

R - Rayo | T - Super Combo | F - Espada<br><br>

<strong>Jugador 2 (Perro):</strong><br>

↑↓←→ - Mover | P - Puño | O - Patada<br>

I - Rayo | U - Super Combo | L - Espada

</div>


<!-- Selector de avatar -->

<div id="avatar-selector">

<h2 style="color: #ffd700; margin-bottom: 20px;">¡ELIGE TU LUCHADOR!</h2>

<div class="avatar-grid">

<div class="avatar-option" data-type="cat" data-color="orange">

<h3>🐱 GATO NARANJA</h3>

<p>Velocidad: ⭐⭐⭐⭐⭐<br>Poder: ⭐⭐⭐</p>

</div>

<div class="avatar-option" data-type="cat" data-color="black">

<h3>🐱 GATO NEGRO</h3>

<p>Velocidad: ⭐⭐⭐<br>Poder: ⭐⭐⭐⭐⭐</p>

</div>

<div class="avatar-option" data-type="dog" data-color="brown">

<h3>🐶 PERRO CAFÉ</h3>

<p>Velocidad: ⭐⭐⭐<br>Poder: ⭐⭐⭐⭐</p>

</div>

<div class="avatar-option" data-type="dog" data-color="white">

<h3>🐶 PERRO BLANCO</h3>

<p>Velocidad: ⭐⭐⭐⭐<br>Poder: ⭐⭐⭐⭐</p>

</div>

</div>

<button class="start-btn" onclick="startGame()">¡COMENZAR BATALLA!</button>

</div>


<!-- Game Over -->

<div id="gameOver">

<h2 id="winnerText"></h2>

<button class="start-btn" onclick="resetGame()">NUEVA BATALLA</button>

</div>

</div>

</div>


<script>

// Variables globales del juego

let scene, camera, renderer, clock;

let player1, player2;

let gameState = 'menu'; // menu, playing, gameOver

let selectedAvatar = { type: 'cat', color: 'orange' };

let round = 1;

let wins = { player1: 0, player2: 0 };


// Estados de los jugadores

let gameData = {

player1: {

health: 100,

power: 0,

position: { x: -3, y: 0, z: 0 },

isAttacking: false,

isBlocking: false,

combo: 0,

lastAttack: 0

},

player2: {

health: 100,

power: 0,

position: { x: 3, y: 0, z: 0 },

isAttacking: false,

isBlocking: false,

combo: 0,

lastAttack: 0

}

};


// Controles

const keys = {};

const keyMap = {

// Jugador 1 (Gato)

'KeyW': 'p1up',

'KeyS': 'p1down',

'KeyA': 'p1left',

'KeyD': 'p1right',

'KeyQ': 'p1punch',

'KeyE': 'p1kick',

'KeyR': 'p1lightning',

'KeyT': 'p1super',

'KeyF': 'p1sword',

// Jugador 2 (Perro)

'ArrowUp': 'p2up',

'ArrowDown': 'p2down',

'ArrowLeft': 'p2left',

'ArrowRight': 'p2right',

'KeyP': 'p2punch',

'KeyO': 'p2kick',

'KeyI': 'p2lightning',

'KeyU': 'p2super',

'KeyL': 'p2sword'

};


// Inicialización

function init() {

// Configurar Three.js

scene = new THREE.Scene();

camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);

renderer = new THREE.WebGLRenderer({ canvas: document.getElementById('gameCanvas'), antialias: true });

renderer.setSize(window.innerWidth, window.innerHeight);

renderer.shadowMap.enabled = true;

renderer.shadowMap.type = THREE.PCFSoftShadowMap;

renderer.setClearColor(0x0a0a0a);

clock = new THREE.Clock();


// Configurar escena

setupScene();

setupLights();

// Event listeners

document.addEventListener('keydown', onKeyDown);

document.addEventListener('keyup', onKeyUp);

window.addEventListener('resize', onWindowResize);


// Configurar selector de avatar

setupAvatarSelector();


// Iniciar loop de renderizado

animate();

}


function setupScene() {

// Suelo de arena

const floorGeometry = new THREE.PlaneGeometry(20, 20);

const floorMaterial = new THREE.MeshLambertMaterial({

color: 0x8B4513,

transparent: true,

opacity: 0.8

});

const floor = new THREE.Mesh(floorGeometry, floorMaterial);

floor.rotation.x = -Math.PI / 2;

floor.receiveShadow = true;

scene.add(floor);


// Fondo épico

const bgGeometry = new THREE.SphereGeometry(50, 32, 16);

const bgMaterial = new THREE.MeshBasicMaterial({

color: 0x1a1a2e,

side: THREE.BackSide,

transparent: true,

opacity: 0.7

});

const background = new THREE.Mesh(bgGeometry, bgMaterial);

scene.add(background);


// Posicionar cámara

camera.position.set(0, 3, 8);

camera.lookAt(0, 1, 0);

}


function setupLights() {

// Luz ambiental

const ambientLight = new THREE.AmbientLight(0x404040, 0.4);

scene.add(ambientLight);


// Luz direccional principal

const directionalLight = new THREE.DirectionalLight(0xffffff, 1);

directionalLight.position.set(5, 10, 5);

directionalLight.castShadow = true;

directionalLight.shadow.mapSize.width = 2048;

directionalLight.shadow.mapSize.height = 2048;

scene.add(directionalLight);


// Luces de ambiente dramático

const light1 = new THREE.PointLight(0xff6b35, 0.8, 10);

light1.position.set(-5, 3, 2);

scene.add(light1);


const light2 = new THREE.PointLight(0x4facfe, 0.8, 10);

light2.position.set(5, 3, 2);

scene.add(light2);

}


function createCharacter(type, color, position) {

const group = new THREE.Group();


// Cuerpo principal

const bodyGeometry = new THREE.BoxGeometry(0.8, 1.2, 0.4);

let bodyColor;

if (type === 'cat') {

bodyColor = color === 'orange' ? 0xff6b35 : 0x2c2c2c;

} else {

bodyColor = color === 'brown' ? 0x8B4513 : 0xffffff;

}

const bodyMaterial = new THREE.MeshLambertMaterial({ color: bodyColor });

const body = new THREE.Mesh(bodyGeometry, bodyMaterial);

body.position.y = 1;

body.castShadow = true;

group.add(body);


// Cabeza

const headGeometry = new THREE.SphereGeometry(0.4, 16, 16);

const head = new THREE.Mesh(headGeometry, bodyMaterial);

head.position.y = 1.8;

head.castShadow = true;

group.add(head);


// Orejas distintivas

if (type === 'cat') {

// Orejas puntiagudas de gato

const earGeometry = new THREE.ConeGeometry(0.1, 0.3, 8);

const leftEar = new THREE.Mesh(earGeometry, bodyMaterial);

leftEar.position.set(-0.2, 2.1, 0);

leftEar.castShadow = true;

group.add(leftEar);


const rightEar = new THREE.Mesh(earGeometry, bodyMaterial);

rightEar.position.set(0.2, 2.1, 0);

rightEar.castShadow = true;

group.add(rightEar);


// Cola de gato

const tailGeometry = new THREE.CylinderGeometry(0.05, 0.1, 1);

const tail = new THREE.Mesh(tailGeometry, bodyMaterial);

tail.position.set(0, 0.5, -0.5);

tail.rotation.x = Math.PI / 4;

tail.castShadow = true;

group.add(tail);

} else {

// Orejas caídas de perro

const earGeometry = new THREE.SphereGeometry(0.15, 8, 8);

const leftEar = new THREE.Mesh(earGeometry, bodyMaterial);

leftEar.position.set(-0.3, 1.9, 0);

leftEar.scale.y = 0.5;

leftEar.castShadow = true;

group.add(leftEar);


const rightEar = new THREE.Mesh(earGeometry, bodyMaterial);

rightEar.position.set(0.3, 1.9, 0);

rightEar.scale.y = 0.5;

rightEar.castShadow = true;

group.add(rightEar);


// Cola de perro

const tailGeometry = new THREE.CylinderGeometry(0.08, 0.05, 0.8);

const tail = new THREE.Mesh(tailGeometry, bodyMaterial);

tail.position.set(0, 0.8, -0.4);

tail.rotation.x = -Math.PI / 6;

tail.castShadow = true;

group.add(tail);

}


// Brazos

const armGeometry = new THREE.CylinderGeometry(0.1, 0.15, 0.8);

const leftArm = new THREE.Mesh(armGeometry, bodyMaterial);

leftArm.position.set(-0.5, 1, 0);

leftArm.castShadow = true;

group.add(leftArm);


const rightArm = new THREE.Mesh(armGeometry, bodyMaterial);

rightArm.position.set(0.5, 1, 0);

rightArm.castShadow = true;

group.add(rightArm);


// Piernas

const legGeometry = new THREE.CylinderGeometry(0.12, 0.15, 0.8);

const leftLeg = new THREE.Mesh(legGeometry, bodyMaterial);

leftLeg.position.set(-0.2, 0.4, 0);

leftLeg.castShadow = true;

group.add(leftLeg);


const rightLeg = new THREE.Mesh(legGeometry, bodyMaterial);

rightLeg.position.set(0.2, 0.4, 0);

rightLeg.castShadow = true;

group.add(rightLeg);


// Posicionar el grupo

group.position.set(position.x, position.y, position.z);

// Agregar propiedades personalizadas

group.userData = {

type: type,

color: color,

isAnimating: false,

animationTime: 0,

originalPosition: {...position}

};


return group;

}


function setupAvatarSelector() {

const options = document.querySelectorAll('.avatar-option');

options.forEach(option => {

option.addEventListener('click', () => {

options.forEach(opt => opt.classList.remove('selected'));

option.classList.add('selected');

selectedAvatar = {

type: option.dataset.type,

color: option.dataset.color

};

});

});


// Seleccionar primera opción por defecto

options[0].classList.add('selected');

}


function startGame() {

gameState = 'playing';

document.getElementById('avatar-selector').classList.add('hidden');

// Crear personajes

if (player1) scene.remove(player1);

if (player2) scene.remove(player2);


player1 = createCharacter(selectedAvatar.type, selectedAvatar.color, gameData.player1.position);

player2 = createCharacter(

selectedAvatar.type === 'cat' ? 'dog' : 'cat',

selectedAvatar.type === 'cat' ? 'brown' : 'orange',

gameData.player2.position

);


scene.add(player1);

scene.add(player2);


// Resetear estado del juego

resetGameData();

updateUI();

}


function resetGameData() {

gameData.player1.health = 100;

gameData.player1.power = 0;

gameData.player1.combo = 0;

gameData.player2.health = 100;

gameData.player2.power = 0;

gameData.player2.combo = 0;

}


function onKeyDown(event) {

const action = keyMap[event.code];

if (action && gameState === 'playing') {

keys[action] = true;

handleAction(action);

}

}


function onKeyUp(event) {

const action = keyMap[event.code];

if (action) {

keys[action] = false;

}

}


function handleAction(action) {

const player = action.startsWith('p1') ? 'player1' : 'player2';

const character = action.startsWith('p1') ? player1 : player2;

const opponent = action.startsWith('p1') ? 'player2' : 'player1';

const opponentChar = action.startsWith('p1') ? player2 : player1;


if (action.includes('punch')) {

performAttack(player, opponent, character, opponentChar, 'punch', 15);

} else if (action.includes('kick')) {

performAttack(player, opponent, character, opponentChar, 'kick', 20);

} else if (action.includes('lightning')) {

if (gameData[player].power >= 50) {

performSpecialAttack(player, opponent, character, opponentChar, 'lightning', 35);

gameData[player].power -= 50;

}

} else if (action.includes('super')) {

if (gameData[player].power >= 100) {

performSpecialAttack(player, opponent, character, opponentChar, 'super', 50);

gameData[player].power = 0;

}

} else if (action.includes('sword')) {

if (gameData[player].power >= 30) {

performSpecialAttack(player, opponent, character, opponentChar, 'sword', 25);

gameData[player].power -= 30;

}

}

}


function performAttack(attackerKey, defenderKey, attackerChar, defenderChar, type, damage) {

if (gameData[attackerKey].isAttacking) return;


gameData[attackerKey].isAttacking = true;

setTimeout(() => gameData[attackerKey].isAttacking = false, 500);


// Animación de ataque

animateAttack(attackerChar, type);


// Verificar distancia

const distance = Math.abs(attackerChar.position.x - defenderChar.position.x);

if (distance < 2) {

// Golpe exitoso

gameData[defenderKey].health -= damage;

gameData[attackerKey].power = Math.min(100, gameData[attackerKey].power + 10);

gameData[attackerKey].combo++;


// Mostrar combo

if (gameData[attackerKey].combo > 1) {

showCombo(gameData[attackerKey].combo);

}


// Animación de impacto

animateHit(defenderChar);


// Partículas de impacto

createImpactEffect(defenderChar.position);

}


updateUI();

checkGameOver();

}


function performSpecialAttack(attackerKey, defenderKey, attackerChar, defenderChar, type, damage) {

if (gameData[attackerKey].isAttacking) return;


gameData[attackerKey].isAttacking = true;

setTimeout(() => gameData[attackerKey].isAttacking = false, 1000);


// Animación especial

animateSpecialAttack(attackerChar, type);


// Efecto siempre golpea en ataques especiales

gameData[defenderKey].health -= damage;

gameData[attackerKey].combo += 2;


showCombo(`${type.toUpperCase()}!`);

animateHit(defenderChar);

createSpecialEffect(attackerChar.position, type);


updateUI();

checkGameOver();

}


function animateAttack(character, type) {

if (!character || character.userData.isAnimating) return;

character.userData.isAnimating = true;

const originalX = character.position.x;

// Movimiento hacia adelante

const direction = character.position.x < 0 ? 1 : -1;

character.position.x += direction * 0.5;

// Rotación de ataque

const targetRotation = type === 'kick' ? Math.PI / 4 : Math.PI / 6;

character.rotation.y = direction * targetRotation;

setTimeout(() => {

character.position.x = originalX;

character.rotation.y = 0;

character.userData.isAnimating = false;

}, 300);

}


function animateSpecialAttack(character, type) {

if (!character || character.userData.isAnimating) return;

character.userData.isAnimating = true;

const originalY = character.position.y;

if (type === 'lightning') {

// Salto con rayo

character.position.y += 1;

character.rotation.z = Math.PI * 2;

} else if (type === 'super') {

// Giro épico

character.rotation.y = Math.PI * 4;

character.scale.set(1.2, 1.2, 1.2);

} else if (type === 'sword') {

// Dash con espada

const direction = character.position.x < 0 ? 1 : -1;

character.position.x += direction * 1.5;

character.rotation.x = Math.PI / 3;

}

setTimeout(() => {

character.position.y = originalY;

character.rotation.set(0, 0, 0);

character.scale.set(1, 1, 1);

if (type === 'sword') {

character.position.x = character.userData.originalPosition.x;

}

character.userData.isAnimating = false;

}, 800);

}


function animateHit(character) {

if (!character) return;

const originalX = character.position.x;

const direction = character.position.x < 0 ? -1 : 1;

character.position.x += direction * 0.3;

setTimeout(() => {

character.position.x = originalX;

}, 200);

}


function createImpactEffect(position) {

const particleCount = 10;

for (let i = 0; i < particleCount; i++) {

const geometry = new THREE.SphereGeometry(0.05, 8, 8);

const material = new THREE.MeshBasicMaterial({

color: Math.random() > 0.5 ? 0xff6b35 : 0xffd700,

transparent: true,

opacity: 0.8

});

const particle = new THREE.Mesh(geometry, material);

particle.position.copy(position);

particle.position.x += (Math.random() - 0.5) * 2;

particle.position.y += Math.random() + 0.5;

particle.position.z += (Math.random() - 0.5) * 2;

scene.add(particle);

// Animar partícula

const velocity = {

x: (Math.random() - 0.5) * 0.2,

y: Math.random() * 0.3 + 0.1,

z: (Math.random() - 0.5) * 0.2

};

let opacity = 0.8;

const animateParticle = () => {

particle.position.x += velocity.x;

particle.position.y += velocity.y;

particle.position.z += velocity.z;

velocity.y -= 0.01; // Gravedad

opacity -= 0.02;

particle.material.opacity = opacity;

if (opacity > 0) {

requestAnimationFrame(animateParticle);

} else {

scene.remove(particle);

}

};

animateParticle();

}

}


function createSpecialEffect(position, type) {

if (type === 'lightning') {

// Efecto de rayo

for (let i = 0; i < 20; i++) {

const geometry = new THREE.CylinderGeometry(0.02, 0.02, Math.random() * 2 + 1);

const material = new THREE.MeshBasicMaterial({

color: 0x00ffff,

transparent: true,

opacity: 0.9

});

const bolt = new THREE.Mesh(geometry, material);

bolt.position.copy(position);

bolt.position.y += Math.random() * 3;

bolt.rotation.z = Math.random() * Math.PI;

scene.add(bolt);

setTimeout(() => scene.remove(bolt), 500);

}

} else if (type === 'super') {

// Efecto de super combo - explosión de energía

const ringGeometry = new THREE.RingGeometry(0.5, 2, 16);

const ringMaterial = new THREE.MeshBasicMaterial({

color: 0xff0080,

transparent: true,

opacity: 0.7,

side: THREE.DoubleSide

});

const ring = new THREE.Mesh(ringGeometry, ringMaterial);

ring.position.copy(position);

ring.rotation.x = -Math.PI / 2;

scene.add(ring);

let scale = 0.1;

const animateRing = () => {

scale += 0.1;

ring.scale.set(scale, scale, scale);

ring.material.opacity = Math.max(0, 0.7 - scale * 0.1);

if (ring.material.opacity > 0) {

requestAnimationFrame(animateRing);

} else {

scene.remove(ring);

}

};

animateRing();

} else if (type === 'sword') {

// Efecto de espada - línea de corte

const lineGeometry = new THREE.PlaneGeometry(3, 0.1);

const lineMaterial = new THREE.MeshBasicMaterial({

color: 0xffffff,

transparent: true,

opacity: 0.9

});

const slash = new THREE.Mesh(lineGeometry, lineMaterial);

slash.position.copy(position);

slash.position.y += 1;

scene.add(slash);

let opacity = 0.9;

const animateSlash = () => {

opacity -= 0.05;

slash.material.opacity = opacity;

slash.rotation.z += 0.1;

if (opacity > 0) {

requestAnimationFrame(animateSlash);

} else {

scene.remove(slash);

}

};

animateSlash();

}

}


function showCombo(text) {

const comboDisplay = document.getElementById('comboDisplay');

comboDisplay.textContent = text;

comboDisplay.classList.add('show');

setTimeout(() => {

comboDisplay.classList.remove('show');

}, 1000);

}


function updateMovement() {

if (gameState !== 'playing') return;


// Movimiento Jugador 1

if (keys.p1left && player1.position.x > -8) {

player1.position.x -= 0.1;

player1.rotation.y = Math.PI / 6;

} else if (keys.p1right && player1.position.x < 8) {

player1.position.x += 0.1;

player1.rotation.y = -Math.PI / 6;

} else {

player1.rotation.y = 0;

}


if (keys.p1up && player1.position.z > -8) {

player1.position.z -= 0.1;

}

if (keys.p1down && player1.position.z < 8) {

player1.position.z += 0.1;

}


// Movimiento Jugador 2

if (keys.p2left && player2.position.x > -8) {

player2.position.x -= 0.1;

player2.rotation.y = Math.PI / 6;

} else if (keys.p2right && player2.position.x < 8) {

player2.position.x += 0.1;

player2.rotation.y = -Math.PI / 6;

} else {

player2.rotation.y = 0;

}


if (keys.p2up && player2.position.z > -8) {

player2.position.z -= 0.1;

}

if (keys.p2down && player2.position.z < 8) {

player2.position.z += 0.1;

}


// Actualizar posiciones en gameData

gameData.player1.position = { ...player1.position };

gameData.player2.position = { ...player2.position };

}


function updateUI() {

// Actualizar barras de vida

const p1Health = Math.max(0, gameData.player1.health);

const p2Health = Math.max(0, gameData.player2.health);

document.getElementById('p1HealthBar').style.width = p1Health + '%';

document.getElementById('p2HealthBar').style.width = p2Health + '%';


// Actualizar barras de poder

document.getElementById('p1PowerBar').style.width = gameData.player1.power + '%';

document.getElementById('p2PowerBar').style.width = gameData.player2.power + '%';


// Actualizar contador de rondas

document.getElementById('round-counter').textContent = `RONDA ${round}`;

}


function checkGameOver() {

if (gameData.player1.health <= 0) {

endRound('player2');

} else if (gameData.player2.health <= 0) {

endRound('player1');

}

}


function endRound(winner) {

wins[winner]++;

if (wins[winner] >= 2) {

// Fin del juego

gameState = 'gameOver';

const winnerText = winner === 'player1' ?

`¡${selectedAvatar.type === 'cat' ? 'GATO' : 'PERRO'} SOMBRA GANA!` :

`¡${selectedAvatar.type === 'cat' ? 'PERRO' : 'GATO'} LUCHA GANA!`;

document.getElementById('winnerText').textContent = winnerText;

document.getElementById('gameOver').style.display = 'block';

} else {

// Siguiente ronda

round++;

resetGameData();

// Resetear posiciones

player1.position.set(-3, 0, 0);

player2.position.set(3, 0, 0);

updateUI();

// Mostrar mensaje de ronda

showCombo(`RONDA ${round}`);

}

}


function resetGame() {

gameState = 'menu';

round = 1;

wins = { player1: 0, player2: 0 };

document.getElementById('gameOver').style.display = 'none';

document.getElementById('avatar-selector').classList.remove('hidden');

// Limpiar escena

if (player1) {

scene.remove(player1);

player1 = null;

}

if (player2) {

scene.remove(player2);

player2 = null;

}

resetGameData();

updateUI();

}


function animate() {

requestAnimationFrame(animate);

const deltaTime = clock.getDelta();

// Actualizar movimiento

updateMovement();

// Animaciones de idle para los personajes

if (player1 && !player1.userData.isAnimating) {

player1.position.y = Math.sin(Date.now() * 0.005) * 0.1;

player1.rotation.z = Math.sin(Date.now() * 0.003) * 0.05;

}

if (player2 && !player2.userData.isAnimating) {

player2.position.y = Math.sin(Date.now() * 0.005 + Math.PI) * 0.1;

player2.rotation.z = Math.sin(Date.now() * 0.003 + Math.PI) * 0.05;

}

// Efectos de luces dinámicas

const time = Date.now() * 0.001;

if (scene.children.length > 0) {

scene.children.forEach(child => {

if (child.type === 'PointLight') {

child.intensity = 0.8 + Math.sin(time * 2) * 0.3;

}

});

}

// Renderizar

renderer.render(scene, camera);

}


function onWindowResize() {

camera.aspect = window.innerWidth / window.innerHeight;

camera.updateProjectionMatrix();

renderer.setSize(window.innerWidth, window.innerHeight);

}


// Inicializar el juego

init();

</script>

</body>

</html>

ree

 
 
 

Comentarios


bottom of page