const CELL_WIDTH = 47; const CELL_HEIGHT = 47; const CASILLAS = 9; class ChessGoal extends Juego { constructor(jugador, url) { super(jugador, url); this.portero = {}; // { 'blancas', 'negras' } this.chess_figures; this.chess_figures_9 = [ { name: "bK", data: "negras", id: "blackKing", x: 4, y: 1 }, { name: "bP", data: "negras", id: "blackPawn1", x: 3, y: 2 }, { name: "bP", data: "negras", id: "blackPawn2", x: 4, y: 2 }, { name: "bP", data: "negras", id: "blackPawn3", x: 5, y: 2 }, { name: "bB", data: "negras", id: "blackBishop1", x: 2, y: 2 }, { name: "bB", data: "negras", id: "blackBishop2", x: 6, y: 2 }, { name: "bR", data: "negras", id: "blackRook1", x: 0, y: 2 }, { name: "bR", data: "negras", id: "blackRook2", x: 8, y: 2 }, { name: "bN", data: "negras", id: "blackKnight1", x: 1, y: 2 }, { name: "bN", data: "negras", id: "blackKnight2", x: 7, y: 2 }, { name: "bQ", data: "negras", id: "blackQueen", x: 4, y: 3 }, { name: "wK", data: "blancas", id: "whiteKing", x: 4, y: 9 }, { name: "wP", data: "blancas", id: "whitePawn1", x: 3, y: 8 }, { name: "wP", data: "blancas", id: "whitePawn2", x: 4, y: 8 }, { name: "wP", data: "blancas", id: "whitePawn3", x: 5, y: 8 }, { name: "wB", data: "blancas", id: "whiteBishop1", x: 2, y: 8 }, { name: "wB", data: "blancas", id: "whiteBishop2", x: 6, y: 8 }, { name: "wR", data: "blancas", id: "whiteRook1", x: 0, y: 8 }, { name: "wR", data: "blancas", id: "whiteRook2", x: 8, y: 8 }, { name: "wN", data: "blancas", id: "whiteKnight1", x: 1, y: 8 }, { name: "wN", data: "blancas", id: "whiteKnight2", x: 7, y: 8 }, { name: "wQ", data: "blancas", id: "whiteQueen", x: 4, y: 7 }, { name: "pelota", data: null, id: "pelota", x: 4, y: 5 } ]; this.redes = [ { name: "red", data: '', id: "red1", x: 3, y: 0 }, { name: "red", data: '', id: "red2", x: 4, y: 0 }, { name: "red", data: '', id: "red3", x: 5, y: 0 }, { name: "red", data: 'invertida_v', id: "red4", x: 3, y: 10 }, { name: "red", data: 'invertida_v', id: "red5", x: 4, y: 10 }, { name: "red", data: 'invertida_v', id: "red6", x: 5, y: 10 }, ]; this.sala.mostrar_sonido(); } // @Override pintar_tablero() { // Mostramos el tablero $('#juego').removeClass('hidden'); var board = $("#chess_board"); // De 0 a 98 // Necesitamos que la fila de las porterías esté dentro de chess_board para poder depositar la pelota en ellas for (var i = 0; i < (CASILLAS * (CASILLAS + 2)); i++) { let fila = parseInt(i / CASILLAS); let columna = parseInt(i % CASILLAS); // Las casillas a los lados de las porterías no tienen fondo let clase = 'chess_cell ' + (i % 2 ? 'bg0' : 'bg1'); if (fila == 0 || fila == CASILLAS + 1) { if (columna < 3 || columna > 5) { clase += " invisible"; } else { clase += " semitransparente"; } } var html = '
'; board.append(html); } // Esquinas de la red $(".chess_cell")[3].id = 'red1'; $(".chess_cell")[5].id = 'red3'; $(".chess_cell")[93].id = 'fondo_red4'; $(".chess_cell")[95].id = 'fondo_red6'; } vaciar_tablero() { // Borramos los relojes $("#capa_tiempo").children(":not(#chess_board)").remove(); // Borramos todo menos las líneas del campo $("#chess_board").find("*:not(object)").remove(); // Vaciamos el chat $('#chat').empty(); $('#texto').val(''); } // @Override pintar_figuras() { // Figuras // Las tengo que clonar para que las piezas se coloquen en su posición al iniciar un nuevo partido this.chess_figures = JSON.parse(JSON.stringify(this.chess_figures_9)); for (let i = 0; i < this.chess_figures.length; i++) { if (this.chess_figures[i].name == 'pelota') { var figureHTML = '
'; } else { var figureHTML = '
'; } this.chess_figures[i].figureHTML = $(figureHTML); $("#chess_board").append($(this.chess_figures[i].figureHTML)); if (this.chess_figures[i].name == 'bK' || this.chess_figures[i].name == 'wK') { this.poner_guantes(this.chess_figures[i]); } } // Redes for (let i = 0; i < this.redes.length; i++) { var figureHTML = '
'; $("#chess_board").append(figureHTML); } // Letras y nºs for (let i = 0; i < CASILLAS; i++) { let num = this.color == 'blancas' ? CASILLAS - i : i + 1; let letra = String.fromCharCode('J'.charCodeAt(0) - num); let color = i >= 3 && i<= 5 ? 'black' : 'white'; $("#chess_board").append( '
' + letra + '
' ); $("#chess_board").append( '
' + letra + '
' ); $("#chess_board").append( '
' + num + '
' ); $("#chess_board").append( '
' + num + '
' ); } // Rival $("#nombre_rival").html(this.rival.mostrar_jugador()); $("#capa_tiempo").append(`
timer
`); // Jugador $("#nombre_jugador").html(this.jugador.mostrar_jugador()); $("#capa_tiempo").append(`
timer
`); } coordenada_x(x) { return this.color == 'blancas' ? x : CASILLAS - 1 - x; } coordenada_y(y) { return this.color == 'blancas' ? y : CASILLAS + 1 - y; } casilla_over(casilla) { if ($('.seleccion').length > 0) { $(casilla).addClass('sombra'); } } casilla_out(casilla) { if ($('.seleccion').length > 0) { $(casilla).removeClass('sombra'); } } // La pelota será siempre la última de las figuras getPelota() { return this.chess_figures[this.chess_figures.length - 1]; } getFigure(id) { for (var i = 0; i < this.chess_figures.length; ++i) { if (this.chess_figures[i].id == id) { return this.chess_figures[i]; }; } return; } getFigureInCell(x, y) { var figura; for (var i = 0; i < this.chess_figures.length; ++i) { if (x == this.chess_figures[i].x && y == this.chess_figures[i].y) { // Damos prioridad a las piezas sobre la pelota if (!figura || !figura.data) { figura = this.chess_figures[i]; } }; } return figura; } checkValidMove(figura, newX, newY) { var invalid = false; if (this.estado < 2) { // Sin iniciar if (!figura.data) { // La pelota no puede moverse invalid = true; } else { // Comprobamos que las fichas no pasen de su campo if (figura.data == 'negras' && newY >= (CASILLAS + 1) / 2) { invalid = true; } else if (figura.data == 'blancas' && (newY < (CASILLAS + 1) / 2 || newY == (CASILLAS + 1) / 2 && newX != (CASILLAS - 1) / 2)) { invalid = true; } } } else if (this.estado == 2) { //console.log('checkValidMove'); if (figura.data) { // Comprobar si es una figura blanca invalid |= figura.data != 'blancas'; // La figura que saca no puede moverse hasta que saque if (figura.x == (CASILLAS - 1) / 2 && figura.y == (CASILLAS + 1) / 2 && this.getPelota().x == (CASILLAS - 1) / 2 && this.getPelota().y == (CASILLAS + 1) / 2) { invalid = true; } } //check figure can move invalid |= !this.movimiento_correcto(figura, newX, newY); } else if (this.turno == this.color) { if (figura.data) { // Comprobar si es su turno invalid |= this.turno != figura.data; } else { // Comprobar fuera de juego const figura_con_pelota = this.getFigureInCell(figura.x, figura.y); invalid |= this.comprobar_fuera_de_juego(figura_con_pelota, newY); } //check figure can move invalid |= !this.movimiento_correcto(figura, newX, newY); } else { invalid = true; } // Líneas de gol invalid |= (newY == 0 || newY == CASILLAS + 1) && (newX < (CASILLAS + 1) / 2 - 2 || newX > (CASILLAS + 1) / 2); // Si movemos una pieza sobre otra... var figureInCell = this.getFigureInCell(newX, newY); if (figureInCell && figureInCell.data && figura.data) { // No permitimos mover una pieza sobre otra del mismo color invalid |= figura.data == figureInCell.data; // Ni sobre una figura rival ya movida invalid |= $(figureInCell.figureHTML).find('img:first').hasClass('figura_movida'); // Ni sobre una rival, siendo torre, si no se puede empujar invalid |= this.comprobar_empujon(figura, figureInCell); } // Ni sobre si misma (ni siquiera la pelota) invalid |= figura.x == newX && figura.y == newY; return invalid; } comprobar_empujon(torre, rival) { if (torre.name == 'bR' || torre.name == 'wR') { // Las torres empujan al rival hacia atrás const newX = rival.x * 2 - torre.x; const newY = rival.y * 2 - torre.y; // Comprobamos que sea dentro del tablero if (newX >= 0 && newX <= CASILLAS && newY >= 0 && newY <= CASILLAS + 2) { if (!$($('.chess_cell')[newX + newY * CASILLAS]).hasClass('invisible')) { // Y que la casilla esté vacía if (!this.getFigureInCell(newX, newY)) { return false; } } } return true; } return false; } comprobar_fuera_de_juego(figura, newY) { // 1. Comprobamos si se pasa la pelota detrás de la defensa var defensas_detras = 0; var ys = []; for (var i = 0; i < this.chess_figures.length; ++i) { if (this.chess_figures[i].data == this.cambiar_color(this.color)) { ys.push(this.chess_figures[i].y); if (this.color == 'blancas' && this.chess_figures[i].y <= newY || this.color == 'negras' && this.chess_figures[i].y >= newY) { defensas_detras++; } } } if (defensas_detras <= 1) { // 2. Vemos si hay algún jugador en fuera de juego ys.sort(); // El límite será la menor altura entre la posición del 2º jugador rival y la altura de la pelota const limite = this.color == 'blancas' ? Math.min(ys[1], figura.y) : Math.max(ys[ys.length - 2], figura.y); for (var i = 0; i < this.chess_figures.length; i++) { if (this.chess_figures[i].id != figura.id && this.chess_figures[i].data == this.color && (this.color == 'blancas' && this.chess_figures[i].y < limite || this.color == 'negras' && this.chess_figures[i].y > limite)) { return true; } } } return false; } piezas_entre(figura, x, y) { const incrX = Math.sign(figura.x - x);//4-2 const incrY = Math.sign(figura.y - y);//5-7 x += incrX; y += incrY; while (figura.x != x || figura.y != y) { if (this.getFigureInCell(x, y)) { return true; } x += incrX; y += incrY; } return false; } movimiento_correcto(figura, newX, newY) { if (figura.name == 'pelota') { // La pelota solo se puede mover si la tiene una pieza del jugador que tiene el turno const figura_con_pelota = this.getFigureInCell(figura.x, figura.y); if (!figura_con_pelota || this.estado != 2 && figura_con_pelota.data != this.turno) { return false; } else { switch (figura_con_pelota.name) { case 'bK': case 'wK': // Si la diferencia en valor absoluto de la casilla destino y la origen es mayor que 1 -> error if (Math.abs(newX - figura_con_pelota.x) > 1 || Math.abs(newY - figura_con_pelota.y) > 1) { return false; } else { return true; } case "wB": case "bB": // Si no está en la diagonal if (Math.abs(figura_con_pelota.x - newX) != Math.abs(figura_con_pelota.y - newY)) { return false; } if (this.piezas_entre(figura_con_pelota, newX, newY)) { return false; } else { return true; } case 'bR': case 'wR': // Si no está en la vertical u horizontal if (newX != figura_con_pelota.x && newY != figura_con_pelota.y) { return false; } if (this.piezas_entre(figura_con_pelota, newX, newY)) { return false; } else { return true; } case 'bQ': case 'wQ': // Si está en la diagonal if (Math.abs(figura_con_pelota.x - newX) == Math.abs(figura_con_pelota.y - newY) // Si está en la vertical u horizontal || (newX == figura_con_pelota.x || newY == figura_con_pelota.y)) { if (this.piezas_entre(figura_con_pelota, newX, newY)) { return false; } else { return true; } } case 'bP': case 'wP': // Las blancas mueven hacia arriba y las negras hacia abajo if (newY == figura_con_pelota.y + (this.color == 'blancas' ? -1 : 1) && Math.abs(newX - figura_con_pelota.x) <= 1) { return true; } else { return false; } case 'bN': case 'wN': const difY = Math.abs(newY - figura_con_pelota.y); const difX = Math.abs(newX - figura_con_pelota.x); if (difY == 2 && difX == 1 || difY == 1 && difX == 2) { return true; } else { return false; } } } } else { // Si la diferencia en valor absoluto de la casilla destino y la origen es mayor que 1 -> error if (Math.abs(newX - figura.x) > 1 || Math.abs(newY - figura.y) > 1) { return false; } else { return true; } } } // Limpio el tablero de figuras movidas, seleccionadas, sombras... limpiar_tablero() { // Borro las piezas movidas del rival $('.chess_figure, .chess_figure img').removeClass('figura_rival_movida'); // Cambio las movidas del jugador $('.chess_figure img.figura_movida, .chess_figure.figura_movida').removeClass('figura_movida').addClass('figura_rival_movida'); $('.chess_figure.pelota_movida').removeClass('pelota_movida').addClass('figura_rival_movida'); $('.chess_figure img').removeClass('seleccion'); $('.chess_cell').removeClass('sombra'); } habilitar_color(habilitar) { if (this.soy_observador()) { habilitar = false; } // Habilito las fichas del color del turno for (var i = 0; i < this.chess_figures.length; ++i) { $(this.chess_figures[i].figureHTML).draggable(habilitar && this.color && (this.chess_figures[i].data == null || this.chess_figures[i].data == this.color) ? "enable" : "disable"); } } // Acción de mover del usuario mover(figura, newX, newY) { $('.chess_figure img').removeClass('seleccion'); $('.chess_cell').removeClass('sombra'); if (juego.checkValidMove(figura, newX, newY)) { return false; } else { // Saque inicial if (this.estado == 2 && figura.name == 'pelota') { this.estado = 4; juego.turno = juego.color; } // ¿Parada del portero? const figureInCell = juego.getFigureInCell(newX, newY); const parada = juego.comprobar_parada(figura, newX, newY, juego.portero[juego.cambiar_color(juego.color)]); if (parada) { newX = parada.x; newY = parada.y; juego.hacer_parada(newX, juego.cambiar_color(juego.color), 250); } juego.movimientos.push({id: figura.id, x: newX, y: newY }); juego.hacer_movimiento(figura, newX, newY, 250, null); if (this.sala.sonido()) { if (figura.id == 'pelota') { $('#audio_pase')[0].play(); } else if (figureInCell && figureInCell.id != 'pelota') { if (figura.name == 'bR' || figura.name == 'wR') { $('#audio_empujon')[0].play(); } else { $('#audio_regate')[0].play(); } } else { $('#audio_movimiento')[0].play(); } } // Si la partida ya ha comenzado... if (juego.estado >= 2) { if (figura.data || figura.figureHTML.hasClass("pelota_movida")) { // Las piezas solo se pueden mover una vez por jugada if (figura.data) { figura.figureHTML.find('img:first').removeClass("figura_rival_movida").addClass("figura_movida"); } else { figura.figureHTML.removeClass("pelota_movida").addClass("figura_movida"); } figura.figureHTML.draggable("disable"); if (figureInCell && figureInCell.data) { // Solo dejamos que se muevan una vez las figuras rivales figureInCell.figureHTML.find('img:first').removeClass("figura_rival_movida").addClass("figura_movida"); } } else { // Excepto la pelota figura.figureHTML.removeClass("figura_rival_movida").addClass("pelota_movida"); } if (!figura.data) { // Si movemos la pelota, deshabilitamos a la figura que la recibe const figura_con_pelota = juego.getFigureInCell(newX, newY); if (figura_con_pelota && figura_con_pelota.data) { figura_con_pelota.figureHTML.find('img:first').removeClass("figura_rival_movida").addClass("figura_movida"); figura_con_pelota.figureHTML.draggable("disable"); } } } return true; } } // ignorar_tamanyo: si estamos pintando únicamente, no queremos que se produzcan transiciones con el tamaño de la pelota mover_figura(figura, x, y, duration, callback, ignorar_tamanyo) { let figura_destino = this.getFigureInCell(x, y); const pelota = this.getPelota(); const tiene_pelota = pelota.x == figura.x && pelota.y == figura.y; figura.x = x; figura.y = y; // Solo aplicamos las clases si la figura no está ya en el destino if (!ignorar_tamanyo && (!figura_destino || figura.name != figura_destino.name)) { if (figura.name == 'pelota') { if (figura_destino) { $(figura.figureHTML).find('img').addClass('pequenya', duration); } else { $(figura.figureHTML).find('img').removeClass('pequenya', duration); } $(figura.figureHTML).animate({ "margin-top": figura_destino ? "28px" : "0", "margin-left": figura_destino ? "-2px" : "0" }, { duration: 100, queue: false }); } else if (figura_destino && figura_destino.name == 'pelota') { $(figura_destino.figureHTML).find('img').addClass('pequenya', duration); $(figura_destino.figureHTML).animate({ "margin-top": "28px", "margin-left": "-2px" }, { duration: 100, queue: false }); } else if (this.turno == null && tiene_pelota) { // La partida no ha empezado, se coloca una figura en el centro y luego se quita $(pelota.figureHTML).find('img').removeClass('pequenya', duration); $(pelota.figureHTML).animate({ "margin-top": "0", "margin-left": "0" }, { duration: 100, queue: false }); } } figura.figureHTML.animate({ top: this.coordenada_y(y) * CELL_HEIGHT, left: this.coordenada_x(x) * CELL_WIDTH }, duration, null, callback); } // Aplica las consecuencias de hacer el movimiento (intercambios, empujones...) hacer_movimiento(figura, x, y, duration, callback) { // Si hay una figura en el destino y ninguna de las dos es la pelota... var figureInCell = this.getFigureInCell(x, y); if (figura.data && figureInCell && figureInCell.data) { // Si es una torre... if (figura.name == 'bR' || figura.name == 'wR') { // La empujamos const newX = figureInCell.x * 2 - figura.x; const newY = figureInCell.y * 2 - figura.y; setTimeout(() => { this.mover_figura(figureInCell, newX, newY, duration, null, false); }, duration / 2); } else { // Si no, las intercambiamos this.mover_figura(figureInCell, figura.x, figura.y, duration, null, false); } } // Si no es la pelota if (figura.data) { // Si el juego ha comenzado y la figura tiene la pelota, la movemos con ella const pelota = this.getPelota(); if (this.turno && pelota.x == figura.x && pelota.y == figura.y) { this.mover_figura(pelota, x, y, duration, null, true); } } this.mover_figura(figura, x, y, duration, callback, false); } empezar(c, duracion) { super.empezar(c, duracion); this.duracion = duracion; this.tiempo['blancas'] = duracion * 60; this.tiempo['negras'] = duracion * 60; this.estado = 0; // sin iniciar // Establecemos el color this.color = c; // Pintamos el tablero this.pintar_ui(); this.actualizar_turno(null, false); this.pintar_tiempos(); this.escribir_servidor(null, '???msg.chooseTactic???'); showToast.show('???msg.chooseTactic???'); $('#boton_nuevo').prop('disabled', false); $('#boton_nuevo').hide(); // Ya podemos ir haciendo la táctica this.habilitar_color(true); if (this.sala.sonido()) { $('#audio_partido')[0].play(); } } // Lo separo para que el observador pueda ver el tablero con las piezas sin que le afecte lo demás pintar_ui() { this.vaciar_tablero(); this.pintar_tablero(); this.pintar_figuras(); $('.chess_figure').draggable({ containment: "parent", zIndex: 1, revert: true, refreshPositions: true }); $('.chess_figure').click(function() { juego.figura_click(this); }); $('.chess_cell').droppable({ accept: ".chess_figure", tolerance: 'intersect', classes: { "ui-droppable-hover" : "sombra" }, drop: function(event, ui) { // Utilizo "juego" en lugar de "this" porque "this" tiene que apuntar a la figura que se ha movido var figura = juego.getFigure($(ui.draggable).attr('data-figureId')); var newX = parseInt($(this).attr('data-x')); var newY = parseInt($(this).attr('data-y')); if (juego.mover(figura, newX, newY)) { if (juego.estado != null && juego.estado >= 2) { // Informo al rival y observadores del movimiento juego.sala.conexion.enviar('hacer_movimiento', juego.getUltimoMovimiento()); } return $(ui.draggable).draggable('option', 'revert', false); } else { return $(ui.draggable).draggable('option', 'revert', true); } } }); } manda_tactica(movs) { this.estado = 2; this.limpiar_tablero(); this.actualizar_turno('blancas', true); this.iniciar_cronometros(); this.escribir_servidor(null, '???msg.gameStarts???'); this.pintar_movimientos(movs, 0, 800, () => { this.habilitar_color(this.color == 'blancas'); if (this.sala.sonido()) { $('#audio_inicio')[0].play(); } }); } getMovimientos() { return JSON.stringify(this.movimientos); } // Devuielve el último movimiento y lo elimina getUltimoMovimiento() { return JSON.stringify(this.movimientos.pop()); } // Solo pinta los movimientos // Si me acaba de mandar la táctica, sí que movemos las figuras con suavidad pintar_movimientos(movs, i, duration, funcion) { if (movs.length > i) { var figura = this.getFigure(movs[i].id); // Pintamos la figura if (movs[i].estado == 'MOVIDA_DOS_VECES') { figura.figureHTML.addClass('pelota_movida'); } else if (movs[i].estado == 'MOVIDA') { if (figura.data) { figura.figureHTML.find('img:first').addClass('figura_movida'); } else { figura.figureHTML.addClass('figura_movida'); } figura.figureHTML.draggable("disable"); } else if (movs[i].estado == 'MOVIDA_RIVAL') { if (figura.data) { figura.figureHTML.find('img:first').addClass('figura_rival_movida'); } else { figura.figureHTML.addClass('figura_rival_movida'); } } // Llamada recursiva hasta que se acaben los movimientos this.mover_figura(figura, movs[i].x, movs[i].y, duration, () => { this.pintar_movimientos(movs, i + 1, duration, funcion); }, false); } else { if (funcion) { funcion(); } } } // Pinta los movimientos del rival y aplica las consecuencias (intercambios, empujones...) hacer_movimientos(movs, i, funcion) { if (movs.length > i) { var figura = this.getFigure(movs[i].id); // ¿Parada del portero? const parada = this.comprobar_parada(figura, movs[i].x, movs[i].y, this.portero[this.cambiar_color(this.turno)]); if (parada) { movs[i].x = parada.x; movs[i].y = parada.y; setTimeout(() => { this.hacer_parada(movs[i].x, this.color, 250); }, 750); } // Pintamos la figura if (figura.data) { figura.figureHTML.find('img:first').removeClass('figura_rival_movida').addClass('figura_movida'); } else if (figura.figureHTML.hasClass('pelota_movida')) { // 2º movimiento pelota figura.figureHTML.removeClass('pelota_movida').addClass('figura_movida'); } else { // 1er movimiento pelota figura.figureHTML.removeClass('figura_rival_movida').addClass('pelota_movida'); } // Si ha habido intercambio o empujón (excluyo la pelota), tb pinto la mía let figura_destino = this.getFigureInCell(movs[i].x, movs[i].y); if (figura_destino && figura_destino.data) { figura_destino.figureHTML.find('img:first').removeClass('figura_rival_movida').addClass('figura_movida'); } // Llamada recursiva hasta que se acaben los movimientos this.hacer_movimiento(figura, movs[i].x, movs[i].y, 1000, () => { this.hacer_movimientos(movs, i + 1, funcion); }); } else { if (funcion) { funcion(); } } } movimientos_turno_rival(tiempo_blancas, tiempo_negras, estado, movs) { this.estado = parseInt(estado); this.actualizar_tiempos(tiempo_blancas, tiempo_negras); this.pintar_movimientos(movs, 0, this.rival_bot() ? 800 : 0, () => { if (!this.soy_observador()) { // Los observadores no tienen color pero sí tienen turno this.actualizar_turno(this.cambiar_color(this.turno), false); this.habilitar_color(true); } else { this.actualizar_turno(this.color, this.estado != null); } this.limpiar_tablero(); if (this.sala.sonido()) { $('#audio_turno')[0].play(); } }); } movimientos_turno_bot(tiempo_blancas, tiempo_negras, estado, movs) { this.estado = parseInt(estado); this.actualizar_tiempos(tiempo_blancas, tiempo_negras); this.hacer_movimientos(movs, 0, () => { if (!this.soy_observador()) { // Los observadores no tienen color pero sí tienen turno this.actualizar_turno(this.cambiar_color(this.turno), false); this.habilitar_color(true); } else { this.actualizar_turno(this.color, this.estado != null); } this.limpiar_tablero(); if (this.sala.sonido()) { $('#audio_turno')[0].play(); } }); } movimiento_rival(mov) { this.hacer_movimientos([mov], 0, null); } poner_guantes(quien) { this.portero[quien.data] = quien; quien.figureHTML.append(''); quien.figureHTML.append(''); } // Comprueba si la pelota ha entrado en la portería, y de ser así, si el portero la ha podido parar // En caso de parada, devuelve las coordenadas donde ha ocurrido // NOTA: tb consideramos parada la pelota si cae al lado del portero. De esta forma evitamos mandar al servidor el movimiento de que la pelota ha entrado en la portería comprobar_parada(figura, newX, newY, port) { // Parada del portero? if (figura.name == 'pelota') { if (newY == 0 || newY == CASILLAS + 1) { // Posición de la pelota antes de entrar en la portería var x = newX - Math.sign(newX - figura.x); var y = newY - Math.sign(newY - figura.y); } else if (newY == 1 || newY == CASILLAS) { var x = newX; var y = newY } else { return null; } // Si el que remata es un caballo, es imparable const figura_con_pelota = this.getFigureInCell(figura.x, figura.y); if (figura_con_pelota.name != 'bN' && figura_con_pelota.name != 'wN') { // Si no hay nadie en la celda... if (!this.getFigureInCell(x, y)) { // y el portero está cerca... if (Math.abs(x - port.x) == 1 && y == port.y) { return { 'x' : x, 'y' : y }; } } } } return null; } encoger_guantes(duracion) { $('.chess_figure').find('.guante:not(.invertida_h)').animate({width: "20px", right: '40px', top: '13px'}, duracion); $('.chess_figure').find('.guante.invertida_h').animate({width: "20px", left: '40px', top: '13px'}, duracion); } hacer_parada(newX, quien, duracion) { if (newX < this.portero[quien].x) { this.portero[quien].figureHTML.find('.guante:not(.invertida_h)').animate({width: CELL_WIDTH + "px", transformOrigin: "right", top: "-5px"}, duracion); } else { this.portero[quien].figureHTML.find('.guante.invertida_h').animate({width: CELL_WIDTH + "px", transformOrigin: "left", top: "-5px"}, duracion); } setTimeout(() => { this.encoger_guantes(duracion); }, duracion * 2); } actualizar_texto_turno() { switch (this.estado) { case 0: // Sin iniciar $('#finalizar').show(); $('#boton_otro').hide(); $('#boton_otro_cancelar').hide(); $('#finalizar').text('???msg.sendTactic???'); $('#finalizar').prop('disabled', this.soy_observador()); break; case 1: // Táctica mandada $('#finalizar').html('
???msg.waitingTactic???'); $('#finalizar').prop('disabled', true); break; case 2: // Esperando saque inicial case 3: // partido iniciado, turno blancas case 4: // partido iniciado, turno negras if (this.soy_observador()) { $('#finalizar').hide(); } else { if (this.turno == this.color || this.turno == null && this.color == 'blancas') { $('#finalizar').text('???msg.endTurn???'); $('#finalizar').prop('disabled', false); } else { $('#finalizar').html('
???msg.opponentTurn???'); $('#finalizar').prop('disabled', true); } } break; default: // Fin partido $('#boton_otro').text('???game.playAgain???'); $('#boton_otro').show(); $('#finalizar').hide(); if (this.soy_observador()) { $('#boton_otro').prop('disabled', true); $('#boton_otro_cancelar').hide(); } else { $('#boton_otro').prop('disabled', false); $('#boton_otro_cancelar').show(); } } } partido_finalizado(tiempo_blancas, tiempo_negras, ganador, puntos_blancas, puntos_negras) { this.estado = null; this.actualizar_turno(null, false); this.actualizar_tiempos(tiempo_blancas, tiempo_negras); this.pintar_tiempos(); setTimeout(() => { if (tiempo_blancas <= 0 || tiempo_negras <= 0) { showToast.show("???msg.timeOut???"); if (this.sala.sonido()) { $('#audio_timeout')[0].play(); } } else { showToast.show("???msg.goal???"); if (this.sala.sonido()) { $('#audio_gol')[0].play(); } } if (this.soy_observador()) { this.escribir_servidor(null, '???msg.endOfGame???'.replace('{0}', ganador == 'blancas' ? this.jugador.nombre : this.rival.nombre)); } else { this.escribir_servidor(null, ganador == this.color ? '???msg.youWin???' : '???msg.youLose???'); } let puntos_rival = this.color == 'negras' ? puntos_blancas : puntos_negras; let puntos_jugador = this.color == 'negras' ? puntos_negras : puntos_blancas; if ((this.jugador.puntos || '') != (puntos_jugador || '')) { var mensaje1 = this.jugador.mostrar_jugador(); this.jugador.puntos = puntos_jugador; mensaje1 += ' pasa a ' + this.jugador.mostrar_jugador(); this.escribir_servidor(null, mensaje1); } if ((this.rival.puntos || '') != (puntos_rival || '')) { var mensaje2 = this.rival.mostrar_jugador(); this.rival.puntos = puntos_rival; mensaje2 += ' pasa a ' + this.rival.mostrar_jugador(); this.escribir_servidor(null, mensaje2); } // Borrar partido this.sala.borrar_partido('partido_' + this.jugador.nombre + '-' + this.rival.nombre); // Actualizar usuarios this.sala.borrar_usuario(this.jugador.nombre); this.sala.borrar_usuario(this.rival.nombre); this.sala.crear_usuario(this.jugador); this.sala.crear_usuario(this.rival); }, 500); clearInterval(this.timer); this.timer = null; } //////////// // EVENTOS //////////// figura_click(figura) { const seleccion = juego.getFigure($('.seleccion').closest('.chess_figure').attr('data-figureid')); const destino = juego.getFigure($(figura).attr('data-figureid')); if (seleccion) { // Si ya hay una figura seleccionada this.mover(seleccion, parseInt(destino.x), parseInt(destino.y)); } else { // Si no, si es nuestra, la seleccionamos if (!$(figura).draggable("option", "disabled")) { $(figura).find('img:first').addClass('seleccion'); if (this.sala.sonido()) { $('#audio_seleccion')[0].play(); } } } } casilla_click(casilla) { const seleccion = juego.getFigure($('.seleccion').closest('.chess_figure').attr('data-figureid')); if (seleccion) { this.mover(seleccion, parseInt($(casilla).attr('data-x')), parseInt($(casilla).attr('data-y'))); } } finalizar_click() { switch (this.estado) { case 0: // sin iniciar if (this.color == 'blancas') { if (!this.getFigureInCell((CASILLAS - 1) / 2, (CASILLAS + 1) / 2).data) { showToast.show('???msg.placeCentralPlayer???'); return; } } break; // 1: esperando táctica del rival case 2: // saque inicial if (this.getPelota().x == (CASILLAS - 1) / 2 && this.getPelota().y == (CASILLAS + 1) / 2 && !this.getFigureInCell((CASILLAS - 1) / 2, (CASILLAS + 1) / 2).figureHTML.find('img:first').hasClass("figura_movida")) { showToast.show('???msg.moveTheBall???'); return; } else { // Este caso no debnería darse porque el estado sería el 3 al mover la pelota? this.estado = 4; } break; case 3: // partido iniciado, turno blancas this.estado = 4; break; case 4: // partido iniciado, turno negras this.estado = 3; break; } if (this.estado == 0) { // Mando táctica this.sala.conexion.enviar('mandar_tactica', this.getMovimientos()); this.estado = 1; this.actualizar_texto_turno(); } else if (this.turno) { // Fin turno this.actualizar_turno(this.cambiar_color(this.turno), true); this.sala.conexion.enviar('fin_turno', null); } else { this.actualizar_texto_turno(); } this.movimientos = []; // Vacío los movimientos this.limpiar_tablero(); this.habilitar_color(false); if (this.sala.sonido()) { $('#audio_boton')[0].play(); } } mostrar_reglas_click() { let reglasHtml = ``; const box = bootbox.alert({ title: 'help ???rules.title???', locale: 'en', scrollable: true, backdrop: true, closeButton: false, message: reglasHtml, buttons: { ok: { className: 'button azul' } } }); box.on('shown.bs.modal', () => { // Inicia el carousel después de que se haya mostrado el diálogo try { $('#carouselControls').carousel(); } catch (error) { // No hacemos nada. Da un error en la consola pero funciona bien } }); } }