No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Victoria: subiendo de nivel

14/24
Recursos

Aportes 29

Preguntas 5

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Lo he logrado, pero mi codigo es una verdadera ensalada, tengo que mejorar eso, voy a tratar de explicarlo.
Lo que se me ocurrió es crear un array bidimensional donde almacena las pocisiones de las bombas, pero de cada level, de esta forma, segun el level que estamos y con la misma logica detectamos las colisiones.

En este pedazo de codigo necesito sus consejos, como podria haber hecho esto mejor:

const bombsPosition =[];

let cantidadLevels = mapRowsCols.map(element => bombsPosition.push([]));
// de esta forma a bombsPosition le agrego los arrays internos y vacios segun cuantos niveles tengamos. Como harían esto de una mejor forma?

Ya teniendo mi array con arrays internos vacios, seguimos con la misma logica con el metodo push segun el map y level los agregamos(las posiciones)

// esto esta dentro de la funcion starGame() dentro del ciclo for
if(mapRowsCols[level][i][z-1] == 'X' && flag ){
                bombsPosition[level].push({x: elementSize*i, y: elementSize*z})
            }

Tenia el problema de que una vez mi jugador salía de la primera fila, ya no podia volver a subir.

El condicional ‘if’ de la funcion moveUp(), tenia ese cambio por decimales de diferencia entre (playerPositions.y - elementsSize) y el msmo elemensSize:

Lo solucioné redondeando hacia arriba los decimales de la resta para igualar al de elementsSize y poder moverme hasta la primera fila:

Mi solución: Como desde el comienzo estaba creando un objeto de mi mapa.
Para pasar de nivel
Cree una funcion lvlUp(), la cual solo cambia la propiedad de mi objeto base, luego renderiza el siguiente lvl, llamando a la funcion startGame()

function lvlUp() {
    if (map.lvl < maps.length - 1) {
        map.lvl += 1;
        startGame()
    }

}

Para resetear todo
uso do funciones, una que detecta la colision, y la otra que le da los nuevos valores de posicion al player

}
function colision() {
    const enemyColition =map.bombPosition.find(a=>
        {
            const coincideX = map.playerPosition.x.toFixed(3) === a.x.toFixed(3);
            const coincideY = map.playerPosition.y.toFixed(3) === a.y.toFixed(3);
            return coincideY && coincideX
        })


        if (enemyColition) {
            console.log("perdiste")
        }
        return enemyColition
    
}
function resetGame(){
if (colision()){
    map.playerPosition.x=map.doorPosition.x
    map.playerPosition.y=map.doorPosition.y
    startGame()
}

Luego corro esa función cuando se mueve el jugador

 playerPosition: {
        x: undefined,
        y: undefined,
        render: function () {
            game.fillText(emojis["PLAYER"], this.y, this.x);
            const coincideX = Math.floor(this.x) === Math.floor(map.giftPosition.x);
            const coincideY = Math.floor(this.y) === Math.floor(map.giftPosition.y);

            if (coincideY && coincideX) {
                console.log("Subiste de nivel")
                lvlUp()
            }
            resetGame()
        }

    }

toooodo mi codigo

const canvas = document.getElementById('game');
const game = canvas.getContext("2d");
const btnUp = document.querySelector('#up');
const btnLeft = document.querySelector('#left');
const btnRight = document.querySelector('#right');
const btnDown = document.querySelector('#down')
let canvasSize;
let canvasElement;
const map = {
    lvl: 0,

    playerPosition: {
        x: undefined,
        y: undefined,
        render: function () {
            game.fillText(emojis["PLAYER"], this.y, this.x);
            const coincideX = Math.floor(this.x) === Math.floor(map.giftPosition.x);
            const coincideY = Math.floor(this.y) === Math.floor(map.giftPosition.y);

            if (coincideY && coincideX) {
                console.log("Subiste de nivel")
                lvlUp()
            }
            resetGame()
        }

    },
    giftPosition: {
        x: undefined,
        y: undefined,
    },
    doorPosition: {
        x: undefined,
        y: undefined,
    },
    bombPosition: [],
    render: function () {
        const Map = maps[this.lvl].match(/[IXO\-]+/g)
            .map(a => a.split("")) || console.log("No more maps")

        game.clearRect(0, 0, canvasSize, canvasSize)

        game.font = canvasElement + "px Verdana"
        game.textAlign = "end"
        Map.forEach((x, xi) => {
            x.forEach((y, yi) => {
                const posX = canvasElement * (xi + 1)
                const posY = canvasElement * (yi + 1)
                game.fillText(emojis[y], posY, posX)
               
                    if (y === "O") {
                        this.doorPosition.x = posX
                        this.doorPosition.y = posY
                        if (this.playerPosition.x === undefined && this.playerPosition.y === undefined) {
                        this.playerPosition.x = posX
                        this.playerPosition.y = posY
                        
                    }
                }
                if (y === "I") {
                    this.giftPosition.x = posX
                    this.giftPosition.y = posY
                }
                if (y === "X") {
                    this.bombPosition.push({ x: posX, y: posY })
                }
                

            })
        })
    }
}
// const playerPosition={

// }
window.addEventListener('load', setCanvasSize);
window.addEventListener('resize', setCanvasSize)


function setCanvasSize() {
    window.innerHeight > window.innerWidth
        ? canvasSize = window.innerWidth * 0.9
        : canvasSize = window.innerHeight * 0.7;


    canvas.setAttribute("height", canvasSize)
    canvas.setAttribute("width", canvasSize)
    canvasElement = canvasSize / 10;
    startGame()
}


function startGame() {
    map.bombPosition = []
    map.render()
    map.playerPosition.render()
}
function lvlUp() {
    if (map.lvl < maps.length - 1) {
        map.lvl += 1;
        startGame()
    }

}
function colision() {
    const enemyColition =map.bombPosition.find(a=>
        {
            const coincideX = map.playerPosition.x.toFixed(3) === a.x.toFixed(3);
            const coincideY = map.playerPosition.y.toFixed(3) === a.y.toFixed(3);
            return coincideY && coincideX
        })


        if (enemyColition) {
            console.log("perdiste")
        }
        return enemyColition
    
}
function resetGame(){
if (colision()){
    map.playerPosition.x=map.doorPosition.x
    map.playerPosition.y=map.doorPosition.y
    startGame()
}

}
//moviemientos
window.addEventListener("keyup", moveByKey)
btnUp.addEventListener("click", moveUp)
btnLeft.addEventListener("click", moveLeft)
btnRight.addEventListener("click", moveRight)
btnDown.addEventListener("click", moveDown)

function moveUp() {
    map.playerPosition.x - canvasElement < canvasElement
        ? map.playerPosition.x = canvasElement
        : map.playerPosition.x -= canvasElement

    startGame()
}
function moveLeft() {
    map.playerPosition.y - canvasElement < canvasElement
        ? map.playerPosition.y = canvasElement
        : map.playerPosition.y -= canvasElement
    startGame()
}
function moveRight() {
    map.playerPosition.y + canvasElement > canvasSize
        ? map.playerPosition.y = canvasSize
        : map.playerPosition.y += canvasElement
    startGame()
}
function moveDown() {
    map.playerPosition.x + canvasElement > canvasSize
        ? map.playerPosition.x = canvasSize
        : map.playerPosition.x += canvasElement
    startGame()
}
function moveByKey(event) {

    if (event.key === "ArrowUp") moveUp();
    if (event.key === "ArrowLeft") moveLeft();
    if (event.key === "ArrowRight") moveRight();
    if (event.key === "ArrowDown") moveDown();

}

Lo logramos


Asi vamos

Creo que acabo de hacer algo muy chambón jajaja.

En el IF de movePlayer que sirve para detectar la colisión con las bombas ejecute una funcion llamada gameLose la cual consiste en recargar la pagina y asi reiniciar todos los niveles.

Funciona, pero… a qué costo.

Creo dos variables(initX, initY) que guarden la ubicación de la puerta cada renderizada en el mapa, no importa que nivel sea, y esa ubicación es la que se le dará a la calavera si choca con algun elemento.

if(col=='O'){
                initX=positionX;
                initY=positionY
                if(!playerPosition.x && !playerPosition.y){
                    playerPosition.x=positionX;
                    playerPosition.y=positionY;
                   
                }

if (estallido){
            game.fillText(emojis['BOMB_COLLISION'],playerPosition.x,playerPosition.y)
            
            console.log(emojis['BOMB_COLLISION']);
            playerPosition.x=initX
            playerPosition.y=initY
           
        }
    });

Este es mi código, al principio me creaba un bucle pero chat GPT me ayudo a solucionarlo, esta en Typescript

import './style.css'
import { maps, emojis } from './maps';

const canvas = document.querySelector('#game') as HTMLCanvasElement;
const game = canvas.getContext('2d')

window.addEventListener('load', setCanvasSize);
window.addEventListener('resize', setCanvasSize)
let canvasSize: string;
let elementSize: number;
let level = 0 as number
let winPosition = {
  x:0 as number,
  y:0 as number
}
let player = emojis['PLAYER']
let playerPosition = {
  x:0 as number,
  y:0 as number
}
let mapaActual: { elem: string; x: number; y: number }[] = [];
let element: { elem: string; x: number; y: number } = {
  elem: '-',
  x: 0,
  y: 0,
};
const btnUp = document.querySelector('#up') as HTMLElement
const btnLeft = document.querySelector('#left') as HTMLElement
const btnRight = document.querySelector('#right') as HTMLElement
const btnDown = document.querySelector('#down') as HTMLElement

function setCanvasSize() {
  let height = window.innerHeight;
  let width = window.innerWidth;

  if (height > width) {
    canvasSize = `${width * 0.8}`;
  } else {
    canvasSize = `${height * 0.8}`;
  }

  elementSize = (parseFloat(canvasSize) / 10.5);

  canvas.setAttribute('width', canvasSize);
  canvas.setAttribute('height', canvasSize);
  startGame()
}

let mapa = maps[level]
  // El método trim elimina los espacios en blanco
let mapRows = mapa.trim().split('\n');
let mapRowCols = mapRows.map(row => row.trim().split(''))


function startGame() {
    console.log('Mapas:', mapa, mapRows, mapRowCols)
    mapa = maps[level]
    mapRows = mapa.trim().split('\n')
    mapRowCols = mapRows.map(row => row.trim().split(''))

  if (!game) {
    console.error('El contexto del lienzo no está disponible');
    return;
  }
  game.font= elementSize + 'px Verdana'
    mapRowCols.forEach((row, i) => {
    row.forEach((col, j) => {
      const emoji = emojis[col]
      let posX =  j * elementSize
      let posY = (i+1) * elementSize
      element = {
        elem: col,
        x: posX,
        y: posY
      }
      mapaActual.push(element)
      if (col == 'O'){
        playerPosition = {
          x: posX,
          y: posY
        }
      // Se crea un array con el valor y las coordenadas  
      }
        game.fillText(emoji, posX, posY)
    })
  })
  movePlayer()
}
function renderGame() {
  if (!game) return;
  game.clearRect(0, 0, canvas.width, canvas.height);
  mapRowCols.forEach((row, i) => {
    row.forEach((col, j) => {
      const emoji = emojis[col];
      let posX = j * elementSize;
      let posY = (i + 1) * elementSize;
      if (col === 'I'){
        winPosition = {
          x: posX,
          y: posY
        }
      }
      game.fillText(emoji, posX, posY);
      
    });
  });
}

function movePlayer() {
  if (!game) return
  renderGame()
  game.fillText(player, playerPosition.x, playerPosition.y);

  mapaActual.map(item => {
    let actualPositionX = Math.floor(playerPosition.x) === Math.floor(item.x)
    let actualPositionY = Math.floor(playerPosition.y) === Math.floor(item.y)
    let actualPosition = actualPositionX && actualPositionY
    if (actualPosition){
      console.log(item.elem)
      if(item.elem === 'X') {
        console.log('Perdiste')
        startGame()
      } 
      if(item.elem === 'I') {
        console.log('Ganaste eeee')
        if(level > maps.length - 1){
          console.log('Fin del juego Ganaste!!')
        }
        else {
          level += 1
          mapaActual = []
          startGame()
        }
      
      }
    }
      
  })
 
  
}
  


function moveUp(){
  playerPosition.y -= elementSize
  if (playerPosition.y > (elementSize * 10)) {
    playerPosition.y = 10 * elementSize
  }
  movePlayer()
}
function moveLeft(){
  playerPosition.x -= elementSize
  if (playerPosition.x < 0) {
    playerPosition.x = 0
  }
  movePlayer()
}
function moveRight(){
  playerPosition.x += elementSize
  if (playerPosition.x > (elementSize * 9)) {
    playerPosition.x = 9 * elementSize
  }
  movePlayer()
}
function moveDown(){
  playerPosition.y += elementSize
  if (playerPosition.y < elementSize) {
    playerPosition.y = elementSize
  }
  movePlayer()
}

function moveByKeys(event: KeyboardEvent) {
  if(event.key == 'ArrowUp') moveUp()
  if(event.key == 'ArrowLeft') moveLeft()
  if(event.key == 'ArrowRight') moveRight()
  if(event.key == 'ArrowDown') moveDown()
}

window.addEventListener('keyup', moveByKeys)

btnUp?.addEventListener('click', moveUp)
btnLeft?.addEventListener('click', moveLeft)
btnRight?.addEventListener('click', moveRight)
btnDown?.addEventListener('click', moveDown)
<h5>Mi Solucion</h5>

En realidad he visto que la mayoria de compañeros lo han realizado casi parecido, esta fue como lo realice yo.

// Declare un objeto con valores de x y y, despues la inicialice con la posicion en el momento que se renderiza la puerta
const doorPosition = {
  x: undefined,
  y: undefined,
}

...

if (!playerPosition.x && !playerPosition.y && col == "O") {
    playerPosition.x = positionX;
    playerPosition.y = positionY;
        
    doorPosition.x = positionX;
    doorPosition.y = positionY;
}

...
// Y con una funcion que se llama cuando el jugador choca con las bombas
function gameOver() {
  console.log("Chocaste contra un enemigo!!");
  playerPosition.x = doorPosition.x;
  playerPosition.y = doorPosition.y;
  level = 0;
  startGame();
}

++mi solución ++

en la funcion movePlayer() remplace el mensaje del condicional que compara cuando hay una colisión con las bombas, en dicho condicional introduje una nueva función

if (bombasCollision){
        repeatLevel()
    }

en la función repatLevel introduje el mensaje que había antes en el condicional, además, asigne las coordenadas de la puerta o el punto de inicio

function repeatLevel(){
    console.log('chocaste con una bomba');
    playerPosition.x = door.x ;
    playerPosition.y = door.y ;
}

¿ como extraje las coordenadas del punto inicial o la puerta?
cree un un nuevo objeto que contenga las coordenadas de la puerta, las coordenadas se insertan cuando se renderiza el mapa

const door = {
    x : undefined,
    y : undefined,
}
if (col =='O'){
                door.x = posX;
                door.y = posY;
               
                if(!playerPosition.x && !playerPosition.y){
                    playerPosition.x = posX;
                    playerPosition.y = posY;
                    console.log({playerPosition});
                }

La solucion para resetear la posicion del jugador hacia la puerta cada vez que colisione es simplemente crear una variable/contanre que haga una copia del objeto playerPosition con Object.create(playerposition) este copiara la estructura y valores mas no la referecia. Luego de esto en startGame cuando le pasamos la primera posicion a la calabera al principio del nivel pues tambien se la pasaremos a nuestro objeto de la puerta
y en cada levelUp le actualizaremos las coordenadas tomando como referencia la posicion del jugador al principio del nivel de esta manera:

function levelUp(){
  level++
  startGame()
  door.x = playerPosition.x
  door.y = playerPosition.y
 }

asi lo haria yo:

const canvas = document.querySelector("#game");
const context = canvas.getContext("2d");
const btnLeft = document.querySelector("#left");
const btnUp = document.querySelector("#up");
const btnRight = document.querySelector("#right");
const btnDown = document.querySelector("#down");

window.addEventListener("load", setCanvasSize);
window.addEventListener("resize", setCanvasSize);

let canvasSize;
let elementsSize;
let level = -1;

const playerPosition = {
	x: undefined,
	y: undefined,
};
const pricePosition = {
	x: undefined,
	y: undefined,
};
const bombPosition = {
	x: 0,
	y: 0,
};
const initialPosition = {
	x: 0,
	y: 0,
};

function startGame() {
	isPricePosition();
	delMap();

	context.textAlign = "end";
	context.font = elementsSize + "px Verdana";

	let map = maps[level];

	if (!map) {
		gameWin();
		return;
	}

	const cleanMap = map.trim().split("\n");
	const matrixMap = cleanMap.map((row) => row.trim().split(""));
	matrixMap.forEach((row, rowP) => {
		row.forEach((col, colP) => {
			let posX = Math.round(elementsSize * (colP + 1));
			let posY = Math.round(elementsSize * (rowP + 1));

			if (
				col == "O" &&
				playerPosition.x == undefined &&
				playerPosition.y == undefined
			) {
				playerPosition.x = posX;
				playerPosition.y = posY;
				initialPosition.x = posX;
				initialPosition.y = posY;
			}
			if (col == "I") {
				pricePosition.x = posX;
				pricePosition.y = posY;
			}
			if (col == "X") {
				bombPosition.x = posX;
				bombPosition.y = posY;
			}
			if (
				playerPosition.x == bombPosition.x &&
				playerPosition.y == bombPosition.y
			) {
				playerPosition.x = initialPosition.x;
				playerPosition.y = initialPosition.y;
			}
			context.fillText(emojis[col], posX, posY);
		});
	});
	console.log(
		playerPosition.x,
		playerPosition.y,
		pricePosition.x,
		pricePosition.y,
		initialPosition.x,
		initialPosition.y,
		level
	);
	movePlayer();
}

function movePlayer() {
	context.fillText(emojis["PLAYER"], playerPosition.x, playerPosition.y);
}
function delMap() {
	context.clearRect(0, 0, canvasSize, canvasSize);
}

function setCanvasSize() {
	canvasSize;
	if (window.innerWidth >= window.innerHeight) {
		canvasSize = Math.round(innerHeight * 0.8);
	} else {
		canvasSize = Math.round(innerWidth * 0.8);
	}

	canvas.setAttribute("width", canvasSize);
	canvas.setAttribute("height", canvasSize);
	elementsSize = Math.round(canvasSize * 0.1);

	startGame();
}

window.addEventListener("keydown", moveByKeys);
btnLeft.addEventListener("click", moveLeft);
btnUp.addEventListener("click", moveUp);
btnRight.addEventListener("click", moveRight);
btnDown.addEventListener("click", moveDown);

function moveByKeys(event) {
	const tecla = event.key;
	switch (tecla) {
		case "ArrowLeft":
			moveLeft();
			break;
		case "ArrowUp":
			moveUp();
			break;
		case "ArrowRight":
			moveRight();
			break;
		case "ArrowDown":
			moveDown();
			break;
		default:
			break;
	}
}

function moveLeft() {
	if (playerPosition.x > elementsSize) {
		playerPosition.x -= elementsSize;
	}
	startGame();
}
function moveUp() {
	if (playerPosition.y > elementsSize) {
		playerPosition.y -= elementsSize;
	}
	startGame();
}
function moveRight() {
	if (playerPosition.x < canvasSize) {
		playerPosition.x += elementsSize;
	}
	startGame();
}
function moveDown() {
	if (playerPosition.y < canvasSize) {
		playerPosition.y += elementsSize;
	}
	startGame();
}

function isPricePosition() {
	if (
		pricePosition.x == playerPosition.x &&
		pricePosition.y == playerPosition.y
	) {
		level++;
		playerPosition.x = undefined;
		playerPosition.y = undefined;
	}
}

function gameWin() {
	console.log("TERMINASTE EL JUEGO!");
}
// context.clearRect(50, 0, 100, 50);
// context.font = "30px Cabin";
// context.fillStyle = "green";
// context.textAlign = "center";
// context.fillText("Fabio", 100, 100);
// context.fillRect(100, 100, 1, 1);

Dentro de la función movePlayer(), en el condicional donde revisamos si enemyCollision es true, agregamos una función por ejemplo levelLost()

      if (enemyCollision) {
        console.log('Chocaste contra un enemigo :(');
        levelLost();
      }

Luego creamos dicha función levelLost() que primero le vuelve a dar los valores de undefined a las propiedades de playerPosition (si no se hace esto habrá un bucle infinito) y luego llamará a la función startGame:

function levelLost() {
    playerPosition.x = undefined;
    playerPosition.y = undefined;
    startGame();
}

s

Me ha pasado el error de los decimales, en el ultimo decimal habia una variacion y eso hacia que mi calaverita al llegar al tercer nivel se pueda salir del mapa por la parte de arriba

Este es el codigo que causaba ese error:

if(key === "up" && (playerPosition.y > elementsSize)) {
                playerPosition.y -= elementsSize
}

y lo arregle asi:

if(key === "up" && (parseInt(playerPosition.y.toFixed(3)) > parseInt(elementsSize.toFixed(3)))) {
                playerPosition.y -= elementsSize

            }

Quería aportar algo, aunque espero me confirmen si es acertado o no. Pienso que al final de la función movePlayer() debería haber un return;

Ejemplo:
movePlayer(){
.
.
.
return;
}
De esta manera siempre que un movimiento sea exitoso, osea sin colisiones, todas las ejecuciones y llamados de funciones terminen y sean sacadas de la pila de ejecuciones; de esta manera no habría que esperar a que terminará el juego para por fin obtener un return y finalizar todas ejecución en la pila.

Aquí mi solución:

  1. Lo que hice primero fue crear un objeto para obtener las posiciones de la puerta:
const doorPosition = new Map();
doorPosition.set('x', undefined);
doorPosition.set('y', undefined);
  1. Luego asignar los valores correspondientes de ‘x’ e ‘y’ en el condicional que ya teníamos:
if (col === 'O') {
    if (!playerPosition.get('x') && !playerPosition.get('y')) {
        playerPosition.set('x', posx);
        playerPosition.set('y', posy);
    }
    doorPosition.set('x', posx);
    doorPosition.set('y', posy);
}
  1. Por último construí la función restartGame():
function restartGame() {
    log('Perdiste!');
    playerPosition.set('x', doorPosition.get('x'));
    playerPosition.set('y', doorPosition.get('y'));

}
Yo cada vez que el jugador colisiona, igualé a playerPosition.x y playerPosition.y a underfined y luego llamé a la función starGame().
Mi solución para reset el nivel, y dependiendo de la cantidad de choques contra las bombas te envia hasta el principio. Primero; ```js //Cree la constante que guarda la posicion de la puerta const doorPos ={ x:undefined, y:undefined, } //en el render del mapa (el forEach) anide una condicion mas para guardar los valores de la posicion de la puerta else if (col == 'o'){ doorPos.x = posX; doorPos.y = posY; } //luego en la deteccion de la colision cree una funcion que hara el trabajo de reiniciar el nivel if (enemyCollision){ restartLevel(); } //la cual hace lo siguiente function restartLevel(){ playerPos.x = doorPos.x; // devuelve el jugador a la posicion de la puerta si choca con una bomba playerPos.y = doorPos.y; life--; // cree una variable vida en el global con el valor de 3 vidas if (life <= 0){ // si la vida llega a 0 vidas se acaba el juego gameOver(); } startGame(); // sea que pierdas una vida o sea game over se vuelve a cargar el mapa con todos sus elementos } function gameOver(){ // es decir que si pierdes las tres vidas vuelves hasta el inicio life = 3; //contador de vidas lleno level=0; //regresas al primer mapa console.log('Game Over'); } ```

en el condicional que vlidabamos la colision con las bombas agregue una funcion

    if (enemyCollision) {
        repeatLevel ()
    }

la funcion seria

function repeatLevel(){
    location.reload()
}

regresa el elemento al inicio pero si estamos en un nivel diferente nos regresa al primero

Lo que hize fue sobreescribir al nivel actual con el nivel que me interesa, en el caso de ganar ira aunmentando hasta el limite del mapa, y al perder lo multiplique por 0 para volver al primer nivel, asi va quedando mi codigo:

const canvas = document.querySelector('#game');
const game = canvas.getContext('2d');
let canvasSize;
let elementSize;

const playerRender = {
  level: 0,
  playerPosition: {
    x: undefined,
    y: undefined,
  },
  giftPosition: {
    x: undefined,
    y: undefined,
  },
  bombPosition: {
    x: [],
    y: [],
  },
  levelUp: function (){
    if (this.level < (maps.length - 1)) {
      this.level += 1;
    } else if ((this.level == (maps.length - 1)) ){
      this.levelWin();
    }
    startGame();
  },
  levelWin: function (){
    console.log('FELICIDADES!!, Ganaste el juego')
  },
  levelLost: function(){
    this.level *= 0;
    console.log('perdiste parce, a la siguiente')
  },
  movePlayer: function () {
    const x = this.getX('PLAYER', this.playerPosition.x)
    const y = this.getY('PLAYER', this.playerPosition.y)

    game.fillText(emojis['PLAYER'], x, y);
  },
  render: function () {
    if (this.level >= maps.length) {
      return console.log("Ese mapa no existe")
    }
    const map = maps[this.level].match(/[IXO\-]+/g)
      .map(a => a.split(""))
    game.font = `${elementSize}px Verdana`;
    game.textAlign = 'center';
    game.textBaseline = 'middle';

    this.bombPosition.x = [];
    this.bombPosition.y = [];

    game.clearRect(0, 0, canvasSize, canvasSize)
    map.forEach((row, rowIndex) => {
      row.forEach((col, colIndex) => {
        const emoji = emojis[col];
        const posX = this.getX(col, colIndex + 1);
        const posY = this.getY(col, rowIndex + 1);


        if (col == 'O') {
          if (!this.playerPosition.x && !this.playerPosition.y) {
            this.playerPosition.x = colIndex + 1;
            this.playerPosition.y = rowIndex + 1;
          }
        } else if (col == 'I') {
          this.giftPosition.x = colIndex + 1;
          this.giftPosition.y = rowIndex + 1;
        } else if (col == 'X') {
          this.bombPosition.x.push(colIndex + 1);
          this.bombPosition.y.push(rowIndex + 1);
        }
        


        game.fillText(emoji, posX, posY);
      });
    });

    this.movePlayer();
  },
  getX: function (icon, posicionNumber) {
    if (icon === 'X') {
      return elementSize * ((posicionNumber - 0.42));
    } else if (icon === 'I') {
      return elementSize * ((posicionNumber - 0.48));
    } else if (icon === 'O') {
      return elementSize * ((posicionNumber - 0.48));
    } else if (icon === 'PLAYER') {
      return elementSize * ((posicionNumber - 0.48));
    } else if (icon === 'BOMB_COLLISION') {
      return elementSize * ((posicionNumber - 0.42));
    }
  },
  getY: function (icon, posicionNumber) {
    if (icon === 'X') {
      return elementSize * ((posicionNumber - 0.32));
    } else if (icon === 'I') {
      return elementSize * ((posicionNumber - 0.28));
    } else if (icon === 'O') {
      return elementSize * ((posicionNumber - 0.32));
    } else if (icon === 'PLAYER') {
      return elementSize * ((posicionNumber - 0.20));
    } else if (icon === 'BOMB_COLLISION') {
      return elementSize * ((posicionNumber - 0.32));
    }
  }

}

window.addEventListener('load', setCanvasSize);
window.addEventListener('resize', setCanvasSize);

function setCanvasSize() {
  canvasSize = Math.min(window.innerWidth, window.innerHeight) * 0.7;

  canvas.setAttribute('width', canvasSize);
  canvas.setAttribute('height', canvasSize);

  elementSize = canvasSize / 10.20;

  startGame();
}


function startGame() {
  playerRender.render()
}

// Mapeo entre teclas y direcciones
const keyToDirection = {
  ArrowUp: 'up',
  ArrowLeft: 'left',
  ArrowDown: 'down',
  ArrowRight: 'right',
  w: 'up',
  a: 'left',
  s: 'down',
  d: 'right'
};

const directionToButton = {
  up: document.querySelector('#up'),
  left: document.querySelector('#left'),
  down: document.querySelector('#down'),
  right: document.querySelector('#rigth'),
};

Object.keys(directionToButton).forEach(direction => {
  directionToButton[direction].addEventListener('click', () => {
    move(direction);
  });
});

window.addEventListener('keydown', moveByKey);

function moveByKey(event) {
  const direction = keyToDirection[event.key];
  if (direction) {
    move(direction);
  }
}

function move(direction) {
  if (direction == 'up') {
    if ((playerRender.playerPosition.y) >= 2) playerRender.playerPosition.y -= 1
  } else if (direction == 'left') {
    if ((playerRender.playerPosition.x) >= 2) playerRender.playerPosition.x -= 1
  } else if (direction == 'right') {
    if (playerRender.playerPosition.x <= 9) playerRender.playerPosition.x += 1
  } else if (direction == 'down') {
    if (playerRender.playerPosition.y <= 9) playerRender.playerPosition.y += 1
  }
  
  if (playerRender.playerPosition.x == playerRender.giftPosition.x && playerRender.playerPosition.y == playerRender.giftPosition.y) {
    console.log('colision jugador con regalo')
    playerRender.levelUp();
  }

  playerRender.bombPosition.x.forEach((xBombs, indexBomb) =>{
    let yBombs = playerRender.bombPosition.y[indexBomb]
    if (playerRender.playerPosition.x == xBombs && playerRender.playerPosition.y == yBombs) {
      console.log('Colision Jugador con bombas')
      playerRender.levelLost();
    }

  })
  
  console.log('Posicion jugador', playerRender.playerPosition, 'Posicion bomba', playerRender.bombPosition)

  playerRender.movePlayer();
  startGame();
}

En un principio utilice la función setCanvas, pero después mejor hice un objeto doorPosition para guardar el valor de x e y cuando col fuera igual a ‘O’ que da el emoji de la puerta. Ambas propuestas hacen lo mismo, pero mejor solo regresar el elemento a su posición inicial que empezar con todo el canvas de nuevo

if(giftCollisionXY){
        levelUp();
    }else if(bombaCollisionXY){
        console.log('Tocaste una bomba');
        setCanvas();
    }
function initialPosition(){
    console.log('Regresaste a la posicion inicial');
    playerPosition.x = doorPosition.x;
    playerPosition.y = doorPosition.y;
}

Cómo evitar el ERROR al terminar todos los niveles


Mi solución

  • Demostración:

  • Paso a paso:

















Comparto un pequeño código para finalizar el juego, espero que les guste.

        if(maps.length > level){
            startGame();
        }else{
            console.log('Felicitaciones, has finalizado el juego.');
            finish = true;
        }

Había entendido la lógica detrás, quisiera ver como se hace el reinicio, pq a mi me sale mal xd

Interesante como el profe propone retos para desarrollar la lógica de programador en cada clase…aquí lo que hice es crear dos funciones para subir de nivel y reiniciar nivel si revienta una bomba.

Complete el reto y sinceramente no se como, si alguien me puede explicar viendo mi codigo estaria agradecido.
Basicamente hice que cuando tocabas una bomba puse que playerPosition = doorPosition. Pero nunca defini la posicion de la puerta, queda undefined. asi que con mas razon no entiendo como saber donde esta la puerta. Si alguien lo encuentra agradecido

const canvas = document.querySelector('#game');
const game = canvas.getContext('2d');
const upButton = document.getElementById('up');
const leftButton = document.getElementById('left');
const rightButton = document.getElementById('right');
const downButton = document.getElementById('down');

let canvasSize;
let elementsSize;
let level = 0;

const playerPosition = {
    x: undefined,
    y: undefined,
};

const giftPosition = {
    x: undefined,
    y: undefined,
}

const doorPosition = {
    x: undefined,
    y: undefined,
}

let bombs = [];


window.addEventListener('load', setCanvasSize);
window.addEventListener('resize', setCanvasSize);

function setCanvasSize() {
    if (window.innerHeight > window.innerWidth) {
        canvasSize = window.innerWidth * 0.8;
    } else {
        canvasSize = window.innerHeight * 0.8;
    };

    canvas.setAttribute('width', canvasSize);
    canvas.setAttribute('height', canvasSize);

    elementsSize = canvasSize / 10;

    startGame()
}

function startGame() {
    // console.log({ canvasSize, elementsSize });
    
    game.font = elementsSize + 'px Verdana';
    game.textAlign = 'end';
    
    const map = maps[level];
    
    if (!map) {
        gameWin();
        return;
    }
    
    const mapRows = map.trim().split('\n');
    const mapRowCols = mapRows.map(row => row.trim().split(''));
    
    bombs = [];
    game.clearRect(0, 0, canvasSize, canvasSize);
    mapRowCols.forEach((row, rowI) => {
        row.forEach((col, colI) => {
            const emoji = emojis[col]
            const posX = elementsSize * (colI + 1);
            const posY = elementsSize * (rowI + 1);
            
            // if (level = 1) {
            //     doorPosition.x = posX;
            //     doorPosition.y = posY;
            //     console.log('Posicion de puerta cambiada')
            // }

            if (col == 'O') {
                if (!playerPosition.x && !playerPosition.y) {
                    playerPosition.x = posX;
                    playerPosition.y = posY;
                    console.log({ playerPosition })
                }
            } else if (col == 'I') {
                    giftPosition.x = posX;
                    giftPosition.y = posY;                
            } else if (col == 'X') {
                bombs.push({
                    x: posX,
                    y: posY,
                });
            }

            game.fillText(emoji, posX, posY);
        });
    });

    movePlayer()
    //Another way to do it =>
    // if (playerPosition.x <= 5 || playerPosition.x - 1 > canvasSize) {
    //     console.log('Te FUISTE');
    // } if (playerPosition.y >=402 || playerPosition.y < 40) {
    //     console.log('Te FUISTE')
    // }

    // for (let row = 1; row <= 10; row++) {
    //     for (let col = 1; col <= 10; col++) {
    //         game.fillText(emojis[mapRowCols[row - 1][col - 1]], elementsSize * col, elementsSize * row);
    //     }
    // }
};

function movePlayer() {
    const giftCollisionX = playerPosition.x.toFixed(1) == giftPosition.x.toFixed(1);
    const giftCollisionY = playerPosition.y.toFixed(1) == giftPosition.y.toFixed(1);
    const giftCollision = giftCollisionX && giftCollisionY;

    if (giftCollision) {
        levelWin();
    }


    const bombCollision = bombs.find(enemy => {
        const bombCollisionX = enemy.x.toFixed(1) == playerPosition.x.toFixed(1);
        const bombCollisionY = enemy.y.toFixed(1) == playerPosition.y.toFixed(1);
        return bombCollisionX && bombCollisionY;
    });

    if (bombCollision) {
        youDied();
    }

    game.fillText(emojis['PLAYER'], playerPosition.x, playerPosition.y);
};

function levelWin() {
    console.log('LVLUP!');
    level++;
    startGame()
    //Another way to do it =>
    //     if (level < maps.length - 1) {
    //         level += 1;
    //         playerPosition.x = undefined;
    //         playerPosition.y = undefined;
    //         startGame()
    // }
}

function gameWin() {
    console.log('Terminaste el Juego!')
}

function youDied() {
    console.log('BOOM!');
    playerPosition.x = doorPosition.x;
    playerPosition.y = doorPosition.y;
    startGame()
}

//movimientos
window.addEventListener('keydown', moveByKeys);
upButton.addEventListener('click', moveUp);
rightButton.addEventListener('click', moveRight);
leftButton.addEventListener('click', moveLeft);
downButton.addEventListener('click', moveDown);

function moveByKeys(event) {
    if (event.key == 'ArrowUp') moveUp();
    else if (event.key == 'ArrowRight') moveRight();
    else if (event.key == 'ArrowLeft') moveLeft();
    else if (event.key == 'ArrowDown') moveDown();
};

function moveUp() {
    console.log('UP');

    if ((playerPosition.y - elementsSize) < elementsSize - 1) {
        console.log('OUTSIDE');
    } else {
        playerPosition.y -= elementsSize;
        startGame()
    }

};
function moveLeft() {
    console.log('LEFT');
    if ((playerPosition.x - elementsSize) < elementsSize) {
        console.log('OUTSIDE');
    } else {
        playerPosition.x -= elementsSize;
        startGame()
    }
};
function moveRight() {
    console.log('RIGHT');
    if ((playerPosition.x + elementsSize) > canvasSize + 2) {
        console.log('OUTSIDE')
    } else {
        playerPosition.x += elementsSize;
        startGame()
    }
};
function moveDown() {
    console.log('DOWN');
    if ((playerPosition.y + elementsSize) > canvasSize) {
        console.log('OUTSIDE')
    } else {
        playerPosition.y += elementsSize;
        startGame()
    }
};

Por estos milagros hay que encomendarse con los dioses del internet, gracias juan

Esta fue mi solución al reto

function levelWin(){
   if(level == 3){
      level = 0;
      playerPosition.x = elementsSize;
      playerPosition.y = canvasSize;
      startGame();
   }else {
      level++;
      startGame();
   }
}

Les comparto mi solución, cree una función que verifica la colisión con alguna bomba, si la colisión sucede la posición del jugador vuelve a ser undefined para que la función startGame le asigne la posición de la puerta.

La función defeat cada vez que se mueve el jugador, es decir con cada ejecución de movePlayer

Lo que hice fue crear una variable que guardara el valor inicial de cada level.

Global
const initialPosition = {
  x: undefined,
  y: undefined,
};

en moveplayer()
      if (col == "O" && !playerPosition.x) {
        initialPosition.x = posX;
        initialPosition.y = posY;
        playerPosition.x = posX;
        playerPosition.y = posY;
      }

y cree una funcion que ese ejecuta cuando hay una colision con las bombas

const gameLose=()=>{
  playerPosition.x=initialPosition.x;
  playerPosition.y=initialPosition.y;
  game.clearRect(0, 0, canvasSize, canvasSize);
  drawMap();     //Esta es la funcion startGame
  game.fillText(emojis["PLAYER"], playerPosition.x, playerPosition.y);
}