import Barco from './barco.js'; import Oceano from './oceano.js'; class MapaBase { constructor(canvas, size, scale, sprites) { this.canvas = canvas; this.canvas.width = size; this.canvas.height = size; this.width = size / scale; this.height = size / scale; this.ctx = this.canvas.getContext('2d'); this.scale = scale; this.ctx.scale(this.scale, this.scale); this.sprites = sprites; this.oceano = new Oceano(this.width, this.height, 32, sprites['OCEANO']); this.casillaSize = 64; this.numFilas = 10; this.numColumnas = 10; } draw() { this.ctx.clearRect(0, 0, this.width, this.height); this.oceano.draw(this.ctx); } } class MapaVisor extends MapaBase { celdas = []; barcos = []; constructor(canvas, size, scale, sprites, barcos, celdas) { super(canvas, size, scale, sprites); this.celdas = celdas; //this.inicializarCeldas(); this.setBarcos(barcos); } inicializarCeldas() { for (let i = 0; i < this.numFilas; i++) { this.celdas[i] = new Array(this.numColumnas).fill(0); } } setBarcos(barcos) { const barcosArray = Array.isArray(barcos) ? barcos : [barcos]; for (const barco of barcosArray) { this.barcos.push( new Barco( barco.x, barco.y, barco.longitud, barco.orientacion, this.sprites[barco.tipoNave], barco.tipoNave, ), ); } } draw() { super.draw(); this.barcos.forEach((barco) => { barco.draw(this.ctx); }); this.ctx.beginPath(); for (let i = 1; i < this.numFilas; i++) { const y = i * this.casillaSize; this.ctx.moveTo(5, y); this.ctx.lineTo(this.casillaSize * this.numColumnas - 5, y); } for (let i = 1; i < this.numColumnas; i++) { const x = i * this.casillaSize; this.ctx.moveTo(x, 5); this.ctx.lineTo(x, this.casillaSize * this.numFilas - 5); } this.ctx.strokeStyle = 'rgba(0, 255, 0, 0.6)'; this.ctx.stroke(); this.ctx.fillStyle = 'red'; this.ctx.font = 'bold 24px Arial'; for (let fila = 0; fila < this.numFilas; fila++) { for (let columna = 0; columna < this.numColumnas; columna++) { const valor = this.celdas[fila][columna]; const posX = columna * this.casillaSize + this.casillaSize / 2.3; const posY = fila * this.casillaSize + this.casillaSize / 1.5; this.ctx.fillText(valor, posX, posY); } } } } class MapaAtaque extends MapaVisor { constructor(canvas, size, scale, sprites, barcos, celdas) { super(canvas, size, scale, sprites, barcos, celdas); canvas.addEventListener('click', this.getPosClick); } calcularCoordenadas(event) { const rect = this.canvas.getBoundingClientRect(); const x = Math.floor( (event.clientX - rect.left) / (this.casillaSize * this.scale), ); const y = Math.floor( (event.clientY - rect.top) / (this.casillaSize * this.scale), ); return { x, y }; } getPosClick = (event) => { const { x, y } = this.calcularCoordenadas(event); console.log(x, y); }; draw() { super.draw(); } } class MapaEditor extends MapaVisor { barcoSeleccionado; constructor(canvas, size, scale, sprites, barcos, celdas) { super(canvas, size, scale, sprites, barcos, celdas); canvas.addEventListener('click', this.getPosClick); canvas.addEventListener('contextmenu', this.giraBarcoSeleccionado); canvas.addEventListener('mousemove', this.mueveBarcoSeleccionado); document.addEventListener('keydown', this.handleKeyDown); } fijaBarco(barco) { barco.seleccionado = false; const incFila = barco.orientacion === 'VERTICAL' ? 1 : 0; const incColumna = barco.orientacion === 'HORIZONTAL' ? 1 : 0; for (let i = 0; i < barco.longitud; i++) { const fila = barco.y + i * incFila; const columna = barco.x + i * incColumna; this.celdas[fila][columna] = barco.longitud; } this.barcos.push(barco); } calcularCoordenadas(event) { const rect = this.canvas.getBoundingClientRect(); const x = Math.floor( (event.clientX - rect.left) / (this.casillaSize * this.scale), ); const y = Math.floor( (event.clientY - rect.top) / (this.casillaSize * this.scale), ); return { x, y }; } //Acuerdate!!!! funcion de flecha en los callBack para no tener problemas con el contexto this handleKeyDown = (event) => { const canvasFocused = document.activeElement === this.canvas; if (canvasFocused && event.key === 'Escape' && this.barcoSeleccionado) { this.barcoSeleccionado.restoreIniPos(); this.posicionaBarcoSeleccionado(); } }; //Acuerdate!!!! funcion de flecha en los callBack para no tener problemas con el contexto this giraBarcoSeleccionado = (event) => { event.preventDefault(); if (this.barcoSeleccionado) { if ( this.barcoSeleccionado.x + this.barcoSeleccionado.longitud <= this.numColumnas && this.barcoSeleccionado.y + this.barcoSeleccionado.longitud <= this.numFilas ) { this.barcoSeleccionado.giraBarco(); this.barcoSeleccionado.posIncorrecta = this.sePuedeColocar(); } } }; //Acuerdate!!!! funcion de flecha en los callBack para no tener problemas con el contexto this getPosClick = (event) => { const { x, y } = this.calcularCoordenadas(event); if (!this.barcoSeleccionado) { const index = this.barcos.findIndex((barco) => barco.clickado(x, y)); if (index != -1) this.seleccionaBarco(index); } else { this.posicionaBarcoSeleccionado(); } }; seleccionaBarco(index_barco) { this.barcoSeleccionado = this.barcos[index_barco]; this.barcoSeleccionado.seleccionado = true; this.barcoSeleccionado.saveIniPos(); this.barcos.splice(index_barco, 1); const incFila = this.barcoSeleccionado.orientacion === 'VERTICAL' ? 1 : 0; const incColumna = this.barcoSeleccionado.orientacion === 'HORIZONTAL' ? 1 : 0; for (let i = 0; i < this.barcoSeleccionado.longitud; i++) { const fila = this.barcoSeleccionado.y + i * incFila; const columna = this.barcoSeleccionado.x + i * incColumna; this.celdas[fila][columna] = 0; } } //Acuerdate!!!! funcion de flecha en los callBack para no tener problemas con el contexto this mueveBarcoSeleccionado = (event) => { if (this.barcoSeleccionado) { const { x, y } = this.calcularCoordenadas(event); if (!this.colisionBorde(x, y)) this.barcoSeleccionado.setXY(x, y); this.barcoSeleccionado.posIncorrecta = this.sePuedeColocar(); } }; posicionaBarcoSeleccionado() { if (!this.barcoSeleccionado.posIncorrecta) { this.fijaBarco(this.barcoSeleccionado); this.barcoSeleccionado = null; } } colisionBorde(x, y) { const barco = this.barcoSeleccionado; const longitud = barco.longitud; const orientacion = barco.orientacion; return orientacion === 'VERTICAL' ? x < 0 || x >= this.numColumnas || y < 0 || y + longitud > this.numFilas : x < 0 || x + longitud > this.numColumnas || y < 0 || y > this.numFilas; } sePuedeColocar() { const x = this.barcoSeleccionado.x; const y = this.barcoSeleccionado.y; const longitud = this.barcoSeleccionado.longitud; const orientacion = this.barcoSeleccionado.orientacion; let suma = 0; if (orientacion === 'VERTICAL') { for (let f = -1; f <= longitud; f++) { for (let c = -1; c < 2; c++) { const fila = y + f; const columna = x + c; if ( fila >= 0 && fila < this.celdas.length && columna >= 0 && columna < this.celdas[0].length ) { suma += this.celdas[fila][columna]; } } } } else { for (let f = -1; f < 2; f++) { for (let c = -1; c <= longitud; c++) { const fila = y + f; const columna = x + c; if ( fila >= 0 && fila < this.celdas.length && columna >= 0 && columna < this.celdas[0].length ) { suma += this.celdas[fila][columna]; } } } } return suma; } esFlotaValida() { return true; } draw() { super.draw(); if (this.barcoSeleccionado) this.barcoSeleccionado.draw(this.ctx); } } export { MapaBase, MapaVisor, MapaAtaque, MapaEditor };