Logica_Piezas_Artilleria.js
import Pieza from '../Pieza.js';
import { Eventos } from '../../Events.js';
import { EventBus } from '../../EventBus.js';
import Tablero from '../Tablero.js';
/**
* Clase que representa la pieza de Artillería en el juego.
* @class Artilleria
* @extends Pieza
* @memberof Logica
*/
class Artilleria extends Pieza {
/**
* Constructor de la pieza Artillería.
* @param {Tablero} tablero - tablero al que pertenece la pieza
* @param {number} fil - fila
* @param {number} col - columna
* @param {string} jugador - 'J1' o 'J2'
*/
constructor(tablero, fil, col, jugador) {
super(tablero, 'Artilleria', fil, col, jugador, 1, 0, -1);
this.cooldown = 4;
this.turnosTranscurridos = 0;
this.utilizable = true;
this.explosion = null;
this.pesoBase = 3;
EventBus.on(Eventos.CHANGE_TURN, (jugador) => { this.pasoTurno(jugador) });
}
/**
* Lanza un proyectil en una celda aleatoria dentro de un área de 3x3 centrada en (fil, col).
* @param {number} fil - fila
* @param {number} col - columna
* @param {Phaser.Scene} escena - escena actual
* @param {Tablero} tablero - tablero de juego
* @param {number} tamCasilla - tamaño de la casilla en píxeles
*/
lanzarProyectil(fil, col, escena, tablero, tamCasilla = 64) {
let randomCell = Phaser.Math.Between(0, 4);
const direcciones = [
{ df: 0, dc: 0 }, // centro
{ df: -1, dc: 0 }, // arriba
{ df: 1, dc: 0 }, // abajo
{ df: 0, dc: -1 }, // izquierda
{ df: 0, dc: 1 } // derecha
];
let filaProyectil = fil + direcciones[randomCell].df;
let colProyectil = col + direcciones[randomCell].dc;
while ((filaProyectil < 0 || filaProyectil > 7) || (colProyectil < 0 || colProyectil > 9)) {
randomCell = Phaser.Math.Between(0, 4);
filaProyectil = fil + direcciones[randomCell].df;
colProyectil = col + direcciones[randomCell].dc;
}
const x = colProyectil * tamCasilla + tamCasilla / 2;
const y = filaProyectil * tamCasilla + tamCasilla / 2;
if (!this.explosion) {
this.explosion = escena.add.sprite(x, y, 'explosion');
this.explosion.on('animationcomplete', () => {
this.explosion.visible = false;
});
this.explosion.setDepth(99);
}
this.explosion.visible = true;
this.explosion.setPosition(x, y);
this.explosion.play('explotar');
let celda = tablero.getCelda(filaProyectil, colProyectil);
if (!celda.estaVacia()) {
let pieza = celda.getPieza();
escena.eliminarPieza(pieza);
if (pieza.getTipo() == "Comandante") {
const atacanteJugador = this.jugador; // La artillería pertenece a alguien
const defensorJugador = pieza.getJugador();
let ganadorFinal;
let autoEliminacion = false;
// Si un jugador mata a SU PROPIO comandante, pierde
if (atacanteJugador === defensorJugador) {
autoEliminacion = true;
ganadorFinal = atacanteJugador === "J1" ? "J2" : "J1";
}
// Si mata al comandante enemigo, gana
else {
ganadorFinal = atacanteJugador;
}
EventBus.emit(Eventos.END_GAME, {
jugador: ganadorFinal,
tipo: "COMBATE",
autoEliminacion: autoEliminacion //info extra
});
}
celda.limpiar();
}
this.utilizable = false;
}
calculaPeso() {
let bestCelda = null;
let bestPeso = -Infinity;
for (let f = 0; f < this.tablero.filas - 1; f++) {
for (let c = this.col - 4; c < this.tablero.columnas - 1; c++) {
let celda = this.tablero.getCelda(f, c);
let pesoTmp = 0;
if (!celda.estaVacia() && celda.getPieza().getJugador() === 'J1') {
pesoTmp += this.detectaTipo(celda)
}
else if (!celda.estaVacia() && celda.getPieza().getJugador() === 'J2') {
pesoTmp -= this.detectaTipo(celda)
}
let vecinos = this.getVecinos(celda);
for (const vecino of vecinos) {
if (!vecino.estaVacia() && vecino.getPieza().getJugador() === 'J1') {
pesoTmp += this.detectaTipo(vecino)
}
else if (!vecino.estaVacia() && vecino.getPieza().getJugador() === 'J2') {
pesoTmp -= this.detectaTipo(vecino)
}
}
if (pesoTmp > bestPeso){
bestPeso = pesoTmp
bestCelda = celda
}
}
}
return {peso: (bestPeso + this.pesoBase), bestCelda: bestCelda};
}
/**
* Proceso de paso de turno para la pieza de artillería.
* Cuando es el turno del jugador de esta pieza, se incrementa el contador de turnos transcurridos.
* Si el contador alcanza el valor del cooldown, la pieza se vuelve utilizable nuevamente.
* @param {string} jugador - jugador actual 'J1' o 'J2'
*/
pasoTurno(jugador) {
if (!this.utilizable && jugador == this.jugador) {
this.turnosTranscurridos++;
if (this.turnosTranscurridos >= this.cooldown) {
this.utilizable = true;
this.turnosTranscurridos = 0;
}
}
}
/**
* Determina si la pieza de artillería puede disparar.
* @returns {boolean} - true si la pieza puede disparar, false en caso contrario
*/
puedeDisparar() {
return this.utilizable;
}
detectaTipo(celda) {
// Solo contabiliza piezas enemigas del jugador J1
if (!celda.estaVacia()) {
switch (celda.getPieza().getTipo()) {
case 'Soldado':
return 2;
case 'Caballeria':
return 3;
case 'Comandante':
return 5;
default:
return 0;
}
}
}
getVecinos(celda) {
const pos = celda.getPosicion();
const fila = pos.fila;
const col = pos.col;
const res = [];
// Arriba
if (fila > 0) {
let celdaArriba = this.tablero.getCelda(fila - 1, col);
res.push(celdaArriba);
}
// Izquierda
if (col > 0) {
let celdaIzquierda = this.tablero.getCelda(fila, col - 1);
res.push(celdaIzquierda);
}
// Abajo
if (fila < this.tablero.filas - 1) {
let celdaAbajo = this.tablero.getCelda(fila + 1, col);
res.push(celdaAbajo);
}
// Derecha
if (col < this.tablero.columnas - 1) {
let celdaDerecha = this.tablero.getCelda(fila, col + 1);
res.push(celdaDerecha);
}
return res;
}
}
export default Artilleria;