No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Detectando colisiones fijas

12/24
Recursos

Aportes 40

Preguntas 0

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.


Mi soluci贸n fue cambiar completamente la l贸gica, de medir pixeles a medir posiciones, eso me solucion贸 muchos problemas 鉁.
Me explico; lo 煤nico que hice fue cambiar la posici贸n en X y Y a n煤meros enteros. Luego con estos hago todas las comparaciones. c:

As铆 por ejemplo para que no se salga de la pantalla solo tengo que ver que no bajen los valores de 1 o se pasen de 10.

As铆 con todo, y con esa sencilla condicional me detecta todas las colisiones.

Aqu铆 dejo el c贸digo 馃摎: https://github.com/ssaldana-dev/game-js

Creo que se deber铆a colocar la l贸gica en las funciones de moveUp, moveDown, etc. porque ah铆 se esta modificando la posici贸n del jugador.

lo de las colisiones fue muy f谩cil solo tuve que comparar el movimiento del jugador con el 铆ndex del mapa sin sumar canvasSize ni comparar X ni Y y pues ya 馃槄


La ventaja que veo que tiene mi c贸digo es que convert铆 el map en un arreglo normal de toda la vida intente asemejarlo a lo que normalmente veo en ensamblador por lo que las colisiones no resultan tan engorrosas ni confusas o al menos eso creo 馃

//contect
const canvas = document.querySelector('#game');
const btnArriba = document.querySelector('#arriba');
const btnAbajo = document.querySelector('#abajo');
const btnDer = document.querySelector('#derecha');
const btnIzq = document.querySelector('#izquierda');

const juego  = canvas.getContext('2d');

//signals: 
window.addEventListener('load', resizeEvent);
window.addEventListener('resize', resizeEvent);


let posJugador     = undefined; let mapa     = Array();  let nivel = 0;
let prePosJugador  = undefined; let celda_t  = 0;        let nivel_actual = undefined;
let puntoDePartida = Number(0); let canvas_t = 0;        var actualizado  = Boolean(false);
let vidas          = Array();

function resizeEvent(){
    actualizado = false;
    canvas_t = (window.innerWidth < window.innerHeight ? window.innerWidth : window.innerHeight) *.75 ;
    canvas.setAttribute('width', canvas_t);
    canvas.setAttribute('height',canvas_t);
    celda_t = canvas_t / 10;
    juego.textAlign='end';
    juego.font = celda_t - celda_t / 10 +'px arial';
    update();}


function update(){
    if(vidas.length == 3 && actualizado) return;
    cargarMapa();
    clear();
    paintEvent();
    paintEventPlayer();
    paintEventGameOver();
    actualizado = true;}


function cargarMapa(){
    if(nivel_actual == nivel) return;

    nivel_actual = nivel;
    mapa = map[nivel].match(/[IOX-]/g);}


function clear(){
    if(!actualizado) {
        juego.clearRect(0,0, canvas_t, canvas_t);
        return;}

    if(posJugador == prePosJugador) return;
    clearRect(posJugador);
    clearRect(prePosJugador);}


function clearRect(indice){
    const x  = posX(indice ) - celda_t / 10;
    const y  = posY(indice ) + celda_t / 5;
    juego.clearRect(x - 1 ,y , - celda_t, - (celda_t + 1));}


function posY(indice){ return (~~(indice/10) + 1) * celda_t - celda_t / 5; }
function posX(indice){ return (indice - (~~(indice/10) * 10) + 1) * celda_t + celda_t / 10;}


function paintEvent(){
    if(!actualizado)
        mapa.forEach((char, idx) => {
            if(char == 'O' && posJugador == undefined) puntoDePartida = posJugador = idx;       
            juego.fillText(emojis[char], posX(idx), posY(idx) );});}


function paintEventPlayer(){
    if(mapa[posJugador] == 'I') {
        nivel = nivel + 1 <= 2 ? ++nivel : 0;
        posJugador = prePosJugador = undefined;
        actualizado = false;
        update();
        return;}

    if(posJugador != undefined && prePosJugador != posJugador){
        juego.fillText(emojis[mapa[prePosJugador]],posX(prePosJugador),posY(prePosJugador));

        if(collisionEvent()) juego.fillText(emojis['PLAYER'], posX(posJugador),posY(posJugador));
        else paintEventGameOver();}}


function collisionEvent(){
    if(vidas.length < 3 && mapa[posJugador] == 'X'){ 
        vidas.push(posJugador);
        juego.fillText(emojis['BOMB_COLLISION'],posX(posJugador),posY(posJugador));
        posJugador = puntoDePartida;}
    if(vidas.length == 3) return false; /*juego terminado*/
    return true; /*continuar con el juego*/}


function paintEventGameOver(){
    juego.textAlign='end';
        vidas.forEach((idx) =>{
            clearRect(idx);
            juego.fillText(emojis['BOMB_COLLISION'],posX(idx),posY(idx));});

    if(vidas.length < 3) return;

    const fuente = celda_t - celda_t / 10 ;
    const media = canvas_t / 2;
    juego.fillStyle = '#000000';
    juego.fillRect(0, media - (fuente /2), canvas_t, fuente);
    juego.textAlign = 'center';
    juego.fillStyle = '#ff5555';
    juego.fillText('Game Over', media, media + fuente/3);}


//signals:
window.addEventListener('keydown',keyMov);
btnArriba.addEventListener('click', movArriba);
btnAbajo.addEventListener('click', movAbajo);
btnDer.addEventListener('click', movDer);
btnIzq.addEventListener('click', movIzq);

//slots:
function keyMov(event){
    switch(event.keyCode){
        case 37: movIzq();    break;//izquierda
        case 38: movArriba(); break;//arriba
        case 39: movDer();    break; //derecha
        case 40: movAbajo();  break;//abajo
        default:              break;}}


function movArriba(){
    prePosJugador = posJugador;
    posJugador -= 10;
    if(posJugador < 0) posJugador = prePosJugador;
    update();}


function movAbajo(){
    prePosJugador = posJugador;
    posJugador += 10;
    if(posJugador >= 100) posJugador = prePosJugador;
    update();}


function movDer(){
    prePosJugador = posJugador;
    const pered = (~~(posJugador / 10)) *10 + 10;
    ++posJugador;
    if(posJugador >= pered) posJugador = prePosJugador;
    update();}


function movIzq(){
    prePosJugador = posJugador;
    const pered  = ~~(posJugador /10) * 10; 
    --posJugador;
    if(posJugador < pered) posJugador = prePosJugador;
    update();}

Paus茅 un segundo la clase porque no me detectaba la colisi贸n y era por los decimales (yo pensaba que hab铆a hecho algo mal). Puse play y dijo que ese era el problema jaja

Y pensar que a mi me salio el error de los decimales en el primer mapa 馃ぃ

Yo si tuve ese error de los decimales

Una soluci贸n que se me ocurre es redondear las coordenadas a dos decimales.

const posX = parseFloat((elementSize * (indexColumn + 1)).toFixed(2));
const posY = parseFloat((elementSize * (indexRow + 1)).toFixed(2));

playerPosition.x = posX;
playerPosition.y = posY;

giftPosition.x = posX;
giftPosition.y = posY;

Para detectar la colisi贸n, cambiar de nivel y dibujar al jugador cree una funci贸n mapPlayer 馃槂
Juego boom

const canvas = document.querySelector("#game");
const game = canvas.getContext("2d");
const up = document.getElementById("up");
const down = document.getElementById("down");
const left = document.getElementById("left");
const right = document.getElementById("right");
let leveltoplay = 0; 
let moveVertical=1;
let moveHorizontal=1;
const playerPosition = {};

window.addEventListener("load",setCanvasSize);
window.addEventListener("resize",setCanvasSize);
// addEventLister movimiento del jugador 
up.addEventListener("click",moveWithButton);
down.addEventListener("click",moveWithButton);
left.addEventListener("click",moveWithButton);
right.addEventListener("click",moveWithButton);
window.addEventListener("keyup",keyDetection);


let canvassize;

function setCanvasSize(){
    
    if( window.innerWidth > window.innerHeight ){
        canvassize = window.innerHeight*0.70;
    }else{
        canvassize = window.innerWidth*0.60;
        
    }  
    
    canvas.setAttribute("width", canvassize);
    canvas.setAttribute("height", canvassize);
    startGame();
}
function startGame(){
    // Espera que se cargue la p谩gina
    // game.fillRect(0,50,100,100);
    // game.clearRect(50,50,100,100);
    // game.fillStyle ="Purple"; 
    // game.font = "25px Verdana";
    // game.textAlign ="center"; //start, end, left, center, right
    // game.fillText("Platzi",50,50,200);
    // const valueheight = window.innerHeight; // height value of windows
    // const valuewidth = window.innerWidth; // width value of windows 

    /* other form to fill the map 
    const valuemaps = Object.keys(emojis);
    console.log(valuemaps);
    let count1 = 1;
    let count2 = 1;
    for (let i = 0; i <maps[0].length; i++) {
        for (let j = 0; j < valuemaps.length; j++) {
           if(maps[0][i] == valuemaps[j]){
            game.fillText(emojis[valuemaps[j]] ,elementSize * count1 , elementSize * count2);
            if(count1 == 10){
                count1 = 1;
                count2++;
            }else{
                count1++;
               
            }          
           }
        }
        if(count2 > 10){
            count2 = 1 ;
        }  
    }
    console.log({count1,count2})
    
    */
    
    const elementSize = canvassize/10;
    console.log({elementSize,game});  
    game.textAlign = "end";
    game.textBaseline = "bottom"; // align text en forma vertical 'top', 'hanging', 'middle', 'alphabetic', 'ideographic', 'bottom'
    game.font = String (elementSize -10) + "px Arial" ;
    renderMap(leveltoplay);
    

    
}
function renderMap(level){
    game.clearRect(0,0,canvas.width,canvas.height);
    const  filterMap = maps[level].trim().split("\n");
    const maprender = filterMap.map(function(key){ return key.trim().split("")});
    mapObjetcs(maprender);
    
}
function moveWithButton(event){
    
    if(event.path[0].id == "up"){
        moveVertical--;
    }else if(event.path[0].id == "down"){
        moveVertical++;
    }else if(event.path[0].id == "left"){
        moveHorizontal--;
    }else if(event.path[0].id == "right"){
        moveHorizontal++;
    }
    condicionalPosition();
    console.log({moveHorizontal,moveVertical});
    movePlayer();
}
function keyDetection(event){
    const keyButtonMove = [38,37,39,40];
    
    keyButtonMove.forEach(function(key){
        if(event.keyCode == key){
            
            if(key == 38){
                moveVertical--;
            }else if(key == 40){
                moveVertical++;
            }else if(key == 37){
                moveHorizontal--;
            }else if(key == 39){
                moveHorizontal++;
            }
            condicionalPosition();
            console.log({moveHorizontal,moveVertical});
            movePlayer();
        }
    });    
}
function condicionalPosition(){
    if(moveVertical>10){
        moveVertical =10;
    }else if(moveVertical < 1){
        moveVertical =1;
    }
    if(moveHorizontal>10){
        moveHorizontal =10;
    }else if(moveHorizontal < 1){
        moveHorizontal =1;
    }
}
function movePlayer(){
    renderMap(leveltoplay);
    // game.fillText(emojis['PLAYER'] ,elementSize * moveHorizontal , elementSize * moveVertical);
}
function mapObjetcs(maprender){
   
    const elementSize = canvassize/10;
    for (let i = 0; i < 10; i++) {
        for (let j = 0; j < 10; j++) {

            game.fillText(emojis[maprender[j][i]] ,elementSize * (i+1) , elementSize * (j+1));      
            
        }
        
    }
    
    mapPlayer(elementSize,maprender);
     
}

function mapPlayer(elementSize,maprender){
    const valuegif= [];
    for (let i = 0; i < 10; i++) {
        for (let j = 0; j < 10; j++) {
           

            if(maprender[j][i]=='O'){
                if (!playerPosition["y"]) {
                    playerPosition["y"] = j + 1;
                    moveVertical=j+1;
                } else {
                    playerPosition["y"] = moveVertical;
                }
                if(!playerPosition["x"]){
                    playerPosition["x"] = i + 1;
                    moveHorizontal = i+1;
                }else{
                    playerPosition["x"] = moveHorizontal;
                }
                game.fillText(emojis['PLAYER'] ,elementSize * playerPosition.x , elementSize * playerPosition.y);
                
        
            }
            if(maprender[j][i]=='I'){
                valuegif.push(i+1);
                valuegif.push(j+1);                
                
            }
            
                 
        }
        
    }
    console.log({valuegif,playerPosition});
    if(maprender[playerPosition.y-1][playerPosition.x-1] == "X"){
        
        // game.fillText(emojis['PLAYER'] ,elementSize * moveHorizontal , elementSize * moveVertical);
        setTimeout(() =>{yourDie()},200);
        
    }
    if((valuegif[1])==playerPosition.y && (valuegif[0])==playerPosition.x){
        leveltoplay++;
        if(leveltoplay>2){leveltoplay=0;}
        startGame();
    }
    
    
    

    
}
function yourDie(){
    window.confirm("Moriste");
    playerPosition.x = undefined;
    playerPosition.y = undefined;
    startGame();
}

Creo una variable 鈥渂ombas鈥 que es una rray vac铆o:

var bombas = [];

Complemento el condicional que guarda las posiciones con el siguiente c贸digo, para que agregue cada par de coordenadas en el array bombas cuando col coincida con X:

 else if (col == 'X') {
                bombas.push(posX, posY);
            }

Dentro de la funci贸n movePlayer, agrego el siguiente ciclo for que inicia en 0 y aumenta 2 unidades con cada iteraci贸n, para asegurarme siempre mirar una coordenada de X de una bomba. Dentro del ciclo for, un condicional que compare la coordenada x de la bomba con la coordenada x del player, as铆 como la coordenada y de la bomba (cuyo indice siempre ser谩 i+1) con la coordenada y del player, y en caso de ser ambos pares iguales, imprima un mensaje en consola:

    for(i=0; i < bombas.length; i=i+2) {
        if(bombas[i].toFixed(3) == playerPosition.x.toFixed(3) && bombas[i+1].toFixed(3) == playerPosition.y.toFixed(3)) {
            console.log("Explosi贸n!!!");
        }
    }

Yo us茅 Math.trunc para el problema de los decimales

<function movePlayer(){
    const giftCollsionX = Math.trunc(playerPosition.x) == Math.trunc(giftPosition.x);
    const giftCollsionY = Math.trunc(playerPosition.y) == Math.trunc(giftPosition.y);
    const giftCollision = giftCollsionX && giftCollsionY

    if(giftCollision){
        alert("Ganaste")
    }

    game.fillText(emojis["PLAYER"], playerPosition.x, playerPosition.y)

}> 

Hola, les comparto mi soluci贸n al desaf铆o.

  1. Creo una variable global para almacenar la posici贸n de todas las bombas let bombs = [ ];

  2. En la funci贸n startGame creo el siguiente condicional para agregar las posiciones de las bombas.

  3. Cree una funci贸n para verificar si la posici贸n del jugador coincide con alguna bomba

  4. Ahora ejecuto esa funci贸n cada vez que se mueve el jugador.

  5. Por 煤ltimo, en la funci贸n setCanvasSize reasigno la variable bombs = [ ]

Mi soluci贸n paso a paso

  • Pasos:
























Yo cre茅 una variable 鈥榖ombArr鈥 que se inicializa en la funci贸n startGame() como un arreglo vac铆o y cuando se pinta el mapa agrega por cada bomba un objeto con la posici贸n en 鈥榅鈥 y 鈥榊鈥 de la misma.

if (col == 'X') {
				bombArr.push({ x: posX, y: posY });
			}

Entonces se valida si al mover el personaje alg煤n objeto del arreglo coincide en X y en Y con el personaje.

function movePlayer() {
	const giftCollisionX = Math.trunc(playerPosition.x) == Math.trunc(giftPosition.x);
	const giftCollisionY = Math.trunc(playerPosition.y) == Math.trunc(giftPosition.y);

	const bombCollisionX = bombArr.find(bomb => Math.trunc(bomb.x) == Math.trunc(playerPosition.x));
	const bombCollisionY = bombArr.find(bomb => Math.trunc(bomb.y) == Math.trunc(playerPosition.y));

	if (giftCollisionX && giftCollisionY) {
		console.log('ganaste!');
	} else if (bombCollisionX && bombCollisionY) {
		console.log('perdiste!');
	} else {
		game.fillText(emojis['PLAYER'], playerPosition.x, playerPosition.y);
	}
}

Pude detectar las colisiones 馃槂 asi:

  1. Crear Array
const bombPosition = [];
  1. Llenarlo con cada una de las posiciones de la bombita
// Coordenadas de las bombas
      else if (col==='X'){
        bombPosition.push({

          bombPositionX : posX,
          bombPositionY : posY
          
        })
  1. Recorrerlo
function bombColision(){
  for (let i = 0; i < bombPosition.length; i++) { 
    if(playerPosition.x === bombPosition[i].bombPositionX && playerPosition.y === bombPosition[i].bombPositionY){
      console.log("boom");
    }
  }
}

Pero al momento de que choca con las bombas me imprime varios 鈥淏OOM鈥

Helpp!

Mi solucion fue hacer push de objetos con las coordenadas x,y por cada bomba hacia a un array para luego con un forEach en la funcion movePlayer recorrer dicho array a la vez que se comparan las coordenadas con las del jugador hasta obtener un match.

const obstacleCollision = obstacles.forEach(obstacle => {
    let obstaclePosX = obstacle.x.toFixed() == playerPosition.x.toFixed()
    let obstaclesPosY = obstacle.y.toFixed() == playerPosition.y.toFixed()
    if(obstaclePosX && obstaclesPosY){
      console.log('BOOOOOMMMMM!!!')
    }
  })

game.js

const canvas = document.querySelector("#game");
const game = canvas.getContext("2d");

window.addEventListener("DOMContentLoaded", startGame);
window.addEventListener("resize", setCanvasSize);

// Obtener referencias a los botones
const upButton = document.getElementById("up");
const leftButton = document.getElementById("left");
const rightButton = document.getElementById("right");
const downButton = document.getElementById("down");

// Agregar manejadores de eventos a los botones
upButton.addEventListener("click", () => movePlayer("up"));
leftButton.addEventListener("click", () => movePlayer("left"));
rightButton.addEventListener("click", () => movePlayer("right"));
downButton.addEventListener("click", () => movePlayer("down"));

document.addEventListener("keydown", handleKeyDown);

let playerPosition = {
  x: undefined,
  y: undefined,
};
let giftPosition = {
  x: undefined,
  y: undefined,
};
let bombPosition = [];

let startMap = 0;
function handleKeyDown(event) {
  const key = event.key.toLowerCase();
  let direction;

  switch (key) {
    case "arrowup":
    case "w":
      direction = "up";
      break;
    case "arrowleft":
    case "a":
      direction = "left";
      break;
    case "arrowright":
    case "d":
      direction = "right";
      break;
    case "arrowdown":
    case "s":
      direction = "down";
      break;
    default:
      return;
  }

  // Realizar alguna acci贸n basada en la direcci贸n detectada
  // Por ejemplo, llamar a una funci贸n para mover al jugador en esa direcci贸n
  movePlayer(direction);
}

let elementsSize;
let map;

function startGame() {
  parseMap();
  setCanvasSize();
}

function movePlayer(direction) {
  // Realizar acciones seg煤n la direcci贸n recibida
  switch (direction) {
    case "up":
      if (!(playerPosition.y > 0)) {
        return; // No se cumple la condici贸n, se sale de la funci贸n sin hacer nada
      }
      playerPosition.y -= 1;
      // L贸gica para mover al jugador hacia arriba
      break;
    case "left":
      if (!(playerPosition.x > 0)) {
        return; // No se cumple la condici贸n, se sale de la funci贸n sin hacer nada
      }
      playerPosition.x -= 1;
      // L贸gica para mover al jugador hacia la izquierda
      break;
    case "right":
      if (!(playerPosition.x < 9)) {
        return; // No se cumple la condici贸n, se sale de la funci贸n sin hacer nada
      }
      playerPosition.x += 1;
      // L贸gica para mover al jugador hacia la derecha
      break;
    case "down":
      if (!(playerPosition.y < 9)) {
        return; // No se cumple la condici贸n, se sale de la funci贸n sin hacer nada
      }
      playerPosition.y += 1;
      // L贸gica para mover al jugador hacia abajo
      break;
    default:
      return;
  }

  if (
    giftPosition.x === playerPosition.x &&
    giftPosition.y === playerPosition.y
  ) {
    startMap++;
    bombPosition = [];
    startGame();
    return;
  } else if (
    bombPosition.some(
      (bombItem) =>
        bombItem.x === playerPosition.x && bombItem.y === playerPosition.y
    )
  ) {
    game.fillText(
      emojis.BOMB_COLLISION,
      playerPosition.x * elementsSize,
      (playerPosition.y + 1) * elementsSize
    );

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

    setTimeout(function () {
      startGame();
    }, 600);

    return;
  }

  // Actualizar el juego, dibujar el mapa actualizado, etc.
  drawMap();
}

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

  canvas.width = canvasSize;
  canvas.height = canvasSize;

  elementsSize = Math.floor(canvasSize / 10 - 1);

  game.font = `${elementsSize}px Verdana`;

  drawMap();
}

function drawMap() {
  game.clearRect(0, 0, canvas.width, canvas.height);

  map.forEach((row, y) => {
    row.forEach((emoji, x) => {
      game.fillText(emoji, x * elementsSize, (y + 1) * elementsSize);

      if (emoji === "馃毆") {
        if (playerPosition.x === undefined && playerPosition.y === undefined) {
          playerPosition = { x, y };
        } // Utiliza object destructuring para simplificar la asignaci贸n de coordenadas
      }
      if (emoji === "馃巵") {
        giftPosition = { x, y };
      }
      if (emoji === "馃挘") {
        bombPosition.push({ x, y });
      }
    });
  });

  game.fillText(
    emojis.PLAYER,
    playerPosition.x * elementsSize,
    (playerPosition.y + 1) * elementsSize
  ); // Utiliza la notaci贸n de puntos para acceder a las propiedades del objeto emojis
}

function parseMap() {
  try {
    const mapString = maps[startMap].trim();
    const lines = mapString.split("\n").map((line) => line.trim());

    map = lines.map((line) => line.split("").map((symbol) => emojis[symbol]));
  } catch (error) {
    startMap = 0;
    playerPosition = {
      x: undefined,
      y: undefined,
    };
    parseMap();
  }
}

Detectar las colisiones no me resulto dificil lo que si se me complico fue como alojar la ubicacion de las bombas por nivel ya que me generaban duplicados para eso modifique el codigo de esta forma

Variables con la que trabajaremos

const canvas = document.querySelector('#game');
const game = canvas.getContext('2d');
const buttons = {
    up: document.querySelector('#up'),
    left: document.querySelector('#left'),
    right: document.querySelector('#right'),
    down: document.querySelector('#down')
};

let canvasSize;
let elementsSize;
let lvl = 0;
//Utilizamos genX y genY para corregir el problema que el emoji del jugador no sea responsive y provoque problemas de coordenadas y hacemos que el jugador se ubique en medio de la posicion (ej. 0,5) y se desplace en un entorno de 10x10
// x e y siguen siendo las coordenadas contextuadas con el resto de los elementos para detectar colisiones
const playerPosition = {
    x: undefined,
    y: undefined,
    genX: undefined,
    genY: undefined,
};
// Utilizaremos esta constante para ubicar la locacion de la meta en cada uno de los mapas
const giftPosition = {
    x: undefined,
    y: undefined,
};

// Sera la constante donde alojaremos las coordenadas de cada una de las bombas de cada uno de los mapas
const bombsPosition = {

}

// Espera a que cargue el contenido html de la pagina antes de lanzar la funcion
window.addEventListener('load', resizeCanvas);
window.addEventListener('resize', resizeCanvas);

Function de start game

 function startGame (lvl) {
    game.font = elementsSize + 'px Verdana';
    //Situamos los elementos en el medio de la casilla tanto horizontal como verticalmente
    game.textAlign = "center";
    game.textBaseline = 'middle';

    const map = maps[lvl]
//Agarramos el mapa del array de mapas y le quitamos los espacios en blanco al inicio y al final con trim y luego con split creamos un arreglo donde el inicio y el final de cada elemento se marca por los saltos de linea '\n'
    const mapRows = map.trim().split('\n');
//Del array resultante usamos map para recorrer cada uno de sus elementos (rows) limpiando los espacios en blanco con trim y luego separandolos por "filas" con split
    const mapRowCols = mapRows.map(row => row.trim().split(''));
    game.clearRect(0,0,canvasSize, canvasSize);
//Recorremos con for each el array bidimensional a partir del string del map y recibimos dos parametros su valor y su indice
    mapRowCols.forEach((row, rowIndex) => {
//Recorremos las filas iterando sobre cada columna y recibimos su valor y su indice
        row.forEach((col, colIndex) => {
//Declaramos que valor tendra el emoji en esa columna
            const emoji = emojis[col];
//Definimos el posicionamiento que tendra en horizontal y vertical esa columna al alinearse en el canvas (ej: elementsSize vale 60 el elemento se insertara en el medio que seria 30)
            const posX = elementsSize * (colIndex + 1/2);
            const posY = elementsSize * (rowIndex + 1/2);
//Solo le damos coordenadas a la posicion del jugador si aun no fueron dadas (si no fue definida en x no hace falta verificar que no haya sido definida en y ya que siempre se definen las dos)       
            if (col == 'O') {
                if (!playerPosition.x && !playerPosition.y) {
                playerPosition.genX = posX / elementsSize
                playerPosition.genY = posY / elementsSize
                playerPosition.x = posX
                playerPosition.y = posY   
                }}
// Localizamos la ubicacion de la meta para comprobar colision posteriormente
            else if (col == 'I') {
                giftPosition.x = posX
                giftPosition.y = posY
            } 
//Verificamos si el objeto donde se alojan las coordenadas de las bombas ya cuenta con una propiedad con el valor del nivel y si no la tiene la creamos como un array vacio
            else if (col == 'X') {
                if (!bombsPosition.hasOwnProperty(lvl)) {
                    bombsPosition[lvl] = []
                }
//Verificamos que las coordenadas no hayan sido alojadas aun y si no las insertamos en el array de arriba
                const coordExists = bombsPosition[lvl].some(coord => coord[0] === posX && coord[1] === posY);
                if (!coordExists) {
                    bombsPosition[lvl].push([posX, posY]);
                }
            }
//Llenamos en nuestro canvas con cada iteracion
            game.fillText(emoji, posX, posY)
        });
    });
    movePlayer()
}

Funciones de movimiento

function movePlayer() {
// Ubicamos al jugador en la cuadrilla obteniendo su ubicacion por medio de las variables genX/Y
    game.fillText(emojis['PLAYER'], playerPosition.genX * elementsSize, playerPosition.genY * elementsSize);
// Corregimos las coordenadas x e y del jugador para que coincidan con su ubicacion actual
    playerPosition.x = ((playerPosition.genX) * elementsSize);
    playerPosition.y = ((playerPosition.genY) * elementsSize);
// Detectamos la colision con las bombas y la meta
    bombsDetection()
    giftDetection()
}

window.addEventListener('keydown', moveByKeys);
buttons.up.addEventListener('click', moveUp);
buttons.left.addEventListener('click', moveLeft);
buttons.right.addEventListener('click', moveRight);
buttons.down.addEventListener('click', moveDown);
 
function moveByKeys(event) {
    if (event.key == 'ArrowUp') moveUp();
    else if (event.key == 'ArrowLeft') moveLeft();
    else if (event.key == 'ArrowRight') moveRight();
    else if (event.key == 'ArrowDown') moveDown();
}
function moveUp() {
    playerPosition.genY -= 1;
//Si el jugador se desplaza fuera del canvas lo volvemos a insertar en la primera posicion de la coordenada y
    if (playerPosition.genY < 0) {
        playerPosition.genY = 0.5;
    }
    startGame(lvl);
}
function moveLeft() {
    playerPosition.genX -= 1;
//Si el jugador se desplaza fuera del canvas lo volvemos a insertar en la primera posicion de la coordenada x
    if (playerPosition.genX < 0) {
        playerPosition.genX = 0.5;
    }
    startGame(lvl);
}
function moveRight() {
    playerPosition.genX += 1;
//Si el jugador se desplaza fuera del canvas lo volvemos a insertar en la ultima posicion de la coordenada x
    if (playerPosition.genX > 10) {
        playerPosition.genX = 9.5;
    }
    startGame(lvl);
}
function moveDown() {
    playerPosition.genY += 1;
//Si el jugador se desplaza fuera del canvas lo volvemos a insertar en la ultima posicion de la coordenada y
    if (playerPosition.genY > 10) {
        playerPosition.genY = 9.5;
    }
    startGame(lvl);
}

Funciones de deteccion

function bombsDetection () {
//Buscamos una coincidencia en el array contenido en la propiedad lvl(ej. 0) y en caso de que la posicion del jugador coincida con alguna de las bombas reseteamos su posicion al inicio del mapa 
    bombsDetected = bombsPosition[lvl].find(bomb => bomb[0] == playerPosition.x && bomb[1] == playerPosition.y)
    if (bombsDetected) {
        console.log("collision detected")
        playerPosition.x =  undefined;
        playerPosition.y =  undefined;
        startGame(lvl)
      }
}

function giftDetection () {
//Verificamos si la posicion del jugador y la meta son identicas y si lo son lo desplazamos al siguiente nivel, si llegamos al ultimo nivel volvemos al primero
    if (playerPosition.x == giftPosition.x && playerPosition.y == giftPosition.y) {
        console.log("gift detected")
        if (lvl < (maps.length - 1)) {
            lvl += 1;
        } else {
            playerPosition.x =  undefined;
            playerPosition.y =  undefined;
            lvl = 0
        }
        startGame(lvl)
        } 
}

Funcion de resize

function resizeCanvas () {
    windowHeight = window.innerHeight * 0.8
    windowWidth = window.innerWidth * 0.8
//Dependiendo del tama帽o de la pantalla, va a colocar el tama帽o cuadrado del canvas
//Al dividir entre 10 y luego aproximar el valor a un entero garantiza que el canvas ser谩 un entero m煤ltiplo de 10. Finalmente se multiplica la expresi贸n por 10 para obtener el dato real del canvas
//Con Math.ceil nos ahorramos el problema de los decimales
    if (window.innerHeight > window.innerWidth) {
        if ((windowWidth % 10) !== 0) {
             canvasSize = Math.ceil(windowWidth / 10) * 10;
        } else {
             canvasSize = windowWidth;
        }} 
    else {
        if ((windowHeight % 10) !== 0) {
             canvasSize = Math.ceil(windowHeight / 10) * 10;
        } else {
             canvasSize = windowHeight;
        }
    }

     canvas.setAttribute('width', canvasSize);
     canvas.setAttribute('height', canvasSize);
     elementsSize = (canvasSize / 10);
     startGame(lvl)
     
 }

Yo cambie las variables del maps a let y agregue un indeci

let indexMap = 0;
let map;
let mapRows;
let mapCols;

Cree una funci贸n para convertir el mapa siguiente

function convertMap(){
    map = maps[indexMap];
    mapRows = map.trim().split('\n');
    mapCols = mapRows.map(row=>row.trim().split(''));
}

A la posici贸n del jugador ingres茅 una bandera i, esta se resetea al iniciar el juego o cuando colisiona con una bomba

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

Y cada movimiento de jugador agregu茅 lo siguiente

function moveUp(){
    if(playerPosition.y>elementSize){
        playerPosition.y-=elementSize;
        detectarObjeto();
    }
    setCanvasSize();
    
}
function moveLeft(){
    if(playerPosition.x > elementSize+1){
        playerPosition.x -= elementSize;
        detectarObjeto();
    }
    setCanvasSize();
}
function moveRight(){
    if(playerPosition.x<elementSize*10){
        playerPosition.x+=elementSize;
        detectarObjeto();
    } 
    setCanvasSize();
}
function moveDown(){
    if(playerPosition.y < elementSize*10){
        playerPosition.y+=elementSize;
        detectarObjeto();
    }
    
    setCanvasSize();
}
function detectarObjeto(){
    posX = Math.round(playerPosition.x/elementSize)-1;
    posY = Math.round(playerPosition.y/elementSize)-1;
    if(mapCols[posY][posX]==='X'){
        playerPosition.i=0;
    }
    else if(mapCols[posY][posX]==='I'){
        if(indexMap< (maps.length-1)){
            indexMap++;
        }
        
    }

}```


yo me encontre con el mismo error, y tuve pausado el video, cuando volvi a poner el video lo entendi todo jaja, lo unico que no me queda claro es por que tuve que cambiar las validaciones en los movimientos, pero bueno, ahi voy entendiendo de a poco, muy bueno!!!

Mi soluci贸n:
Genere una funci贸n collision la cual comparta la posici贸n actual del jugador contra el array del mapa (variable global)
la cual es llamada desde cada funci贸n de movimiento

Saludos!

Ubiqu茅 el condiconal de coordenadas en la funci贸n de aparecer al jugador, as铆 solo la escribo una vez y me detecta solo el caso cuando las coordenadas del jugador y regalito coinciden:

function movePlayer() {
    game.fillText(emojis['PLAYER'], playerPos.x, playerPos.y);
    if (playerPos.x == giftPos.x && playerPos.y == giftPos.y){
        console.log("you're here!")
    }
}

Tambi茅n se podr铆a realizar la colusi贸n cuando el player abandone el camino libre de obst谩culos.

Muy buena la explicaci贸n del const para un objeto.
Ahora me surge una duda. Seria lo mismo declarar el objeto con let ?

Les comparto mi soluci贸n a los retos que se presentaron hasta el momento鈥 Me da pereza explicar ya que mi c贸digo est谩 quedando bastante diferente del de la clase, pero intent茅 que sea lo m谩s claro posible. Las posiciones las manejo con n煤meros enteros y no vuelvo a hacer render de todo el mapa cada vez que se mueve el personaje.

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

let canvasSize = Math.min(window.innerHeight, window.innerWidth)*0.8;
let elementSize = canvasSize/10;

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

let lvl = 0;
let lives = 3;

const initialPosition = {
  posX: undefined,
  posY: undefined,
}

const position = {
  posX: undefined,
  posY: undefined,
}

window.addEventListener('load', renderMap);
window.addEventListener('resize', resizeMap);

function resizeMap() {
  canvasSize = Math.min(window.innerHeight, window.innerWidth)*0.8;
  elementSize = canvasSize/10;
  
  canvas.setAttribute('width', canvasSize);
  canvas.setAttribute('height', canvasSize);

  renderMap();
}

function renderMap() {
  game.font = (`${elementSize * 0.85}px verdana`);
  game.textAlign = 'end' 

  const map = maps[lvl];
  const mapRow = map.trim().replaceAll(' ', '').split('\n');
  const mapRowCol = mapRow.map( row => row.split(''));
  
  mapRowCol.forEach((row, rowI) => {
    row.forEach((col, colI) => {
      const emoji = emojis[col];
      const posX = elementSize * (colI + 1);
      const posY = elementSize * (rowI + 1);
      game.fillText(emoji, posX, posY);
      if (col === 'O') {
        //Divido todo por elementSize para que las posiciones queden definidas del 1 al 10
        initialPosition.posX = posX/elementSize;
        initialPosition.posY = posY/elementSize;
        
        if (!position.posX){
          position.posX = posX/elementSize;
          position.posY = posY/elementSize;
        }
      }
    })
  });
  game.fillText(emojis['PLAYER'], position.posX * elementSize, position.posY * elementSize);
}

function startGame() {
  lives = 3;
  lvl = 0;
  vidas.innerText = `Vidas: ${lives}`;
  position.posX = undefined;
  position.posY = undefined;
  game.clearRect(0, 0, canvasSize, canvasSize);
  renderMap();
}

btnUp.addEventListener('click', moveUp);
btnLeft.addEventListener('click', moveLeft);
btnRight.addEventListener('click', moveRight);
btnDown.addEventListener('click', moveDown);
window.addEventListener('keydown', (event) => {
  switch (event.key) {
    case 'ArrowUp':
      moveUp()
      break;
    
    case 'ArrowLeft':
      moveLeft()
      break;

    case 'ArrowRight':
      moveRight()
      break;

    case 'ArrowDown':
      moveDown()
      break;
    default:
        break;
  }
})

function moveUp() {
  move('up');
}
function moveLeft() {
  move('left');
}
function moveRight() {
  move('right');
}
function moveDown() {
  move('down');
}

function clear(position) {
  const startClearX = position.posX * elementSize - elementSize;
  const startClearY = position.posY * elementSize - (elementSize * .83);
  const endClearX = elementSize;
  const endClearY = (elementSize * 1.08);
  game.clearRect(startClearX, startClearY, endClearX, endClearY);
}

function move(dir) {
  if (lives == 0){
    startGame();
    return
  }

  const previousPosition = {
    posX: position.posX,
    posY: position.posY,
  }

  if (dir === 'up') position.posY -= 1;
  else if (dir === 'left') position.posX -= 1;
  else if (dir === 'right') position.posX += 1;
  else if (dir === 'down') position.posY += 1;
  
  if (position.posX < 1 || position.posY < 1 || position.posX > 10 || position.posY > 10) {
    position.posX = previousPosition.posX;
    position.posY = previousPosition.posY;
    return
  }

  clear(previousPosition);
  
  if (previousPosition.posX == initialPosition.posX && previousPosition.posY == initialPosition.posY) {
    game.fillText(emojis['O'], previousPosition.posX * elementSize, previousPosition.posY * elementSize)
  }
  
  const map = maps[lvl];
  const mapRow = map.trim().replaceAll(' ', '').split('\n');
  const mapRowCol = mapRow.map( row => row.split(''));
  const emoji = mapRowCol[position.posY - 1][position.posX - 1];

  if (emoji === 'X'){
    clear(position);
    game.fillText(emojis['BOMB_COLLISION'], position.posX * elementSize, position.posY * elementSize);
    lives -= 1;
    vidas.innerText = `Vidas: ${lives}`
    if (lives == 0) {
      game.clearRect(0, 0, canvasSize, canvasSize);
      game.fillText('YOU LOSE!!!   \n'+ emojis['GAME_OVER'], canvasSize*0.8, canvasSize*0.5 )
      return
    }
    position.posX = initialPosition.posX;
    position.posY = initialPosition.posY;
  }

  if (emoji === 'I') {
    lvl += 1;
    game.clearRect(0, 0, canvasSize, canvasSize);
    if (lvl == maps.length) {
      game.fillText('YOU WIN!!!   \n'+ emojis['WIN'], canvasSize*0.8, canvasSize*0.5 )
      lives = 0
      return
    }
    renderMap();
    return
  }

  game.fillText(emojis['PLAYER'], position.posX * elementSize, position.posY * elementSize);
}
ya se me rompi贸 el jueguito y no encuentro que hice mal

me gusto mucho el ejemplo de Sergio Alejandro Salda帽a Rangel, el uso los indices de los elementos, en vez de usar los pixeles, y tambien creo una funcion que ayuda a calcular la posicion de cada elemento las cuales son (getx y getY), al hacer esto se vuelve el juego mucho mas personalizable y es muchisimo mas facil calcular las coliciones, asi mismo cambie algunas cosas, como el bombPosition, en vez de usar simples variables, a X y a Y les puse un array y pongo cada cordenada de las bombas en ellos, para luego con un ciclo for recorrerlos y hacer la comparacion de las bombas, asi va mi codigo:

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

const playerRender = {
  level: 2,
  playerPosition: {
    x: undefined,
    y: undefined,
  },
  giftPosition: {
    x: undefined,
    y: undefined,
  },
  bombPosition: {
    x: [],
    y: [],
  },
  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';

    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.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')
    }

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

  playerRender.movePlayer();
  startGame();
}

Yo lo hice as铆 all in one 馃槑

Psdt. Puse un setTimeout para poner el jugador por encima de todos los obstaculos

reto superado. 馃殌

Yo lo solucion茅 en los movimientos del usuario para que eval煤e si la posici贸n es igual a la del objecto (emoji).

Yo tambi茅n me top茅 con el error de los decimales y lo solucion茅 desde el principio con Math.round() y me funciona muy bien

a mi no me detectaron!! =(

Si me lleg贸 a pasar lo de que los decimales no coincid铆an xd

Para la colisi贸n de bombas cre茅 un array para almacenar las posiciones de cada bomba y luego verificar si existe colisi贸n

Agregu茅 la colisi贸n entre el jugador y el regalo en la funci贸n de movePlayer()

Hice una funcion para detectar colisiones o coincidencias en general( uso la misma funci贸n para saber si llego al regalo o si esta en la entrada):

  • La funci贸n recibe un solo parametro que es el objeto con el que queremos comparar su posicion respecto al jugador.
  • El condicional evalua si el objeto pasado en el parametro esta en el area de nuestro jugador.
  • Con la evaluacion retornar un true o false que puedo usar en otra condicional para decidir que hacer
function detectColission({ x, y }) {
  if (
    playerPosition.x - x <= blocksSize * 0.05 &&
    playerPosition.y - y <= blocksSize * 0.05 &&
    playerPosition.x + blocksSize - x >= blocksSize * 0.05 &&
    playerPosition.y + blocksSize - y >= blocksSize * 0.05
  ) {
    return true;
  } else {
    return false;
  }
}
  • Usandolo para reconocer bombas seria asi:

Tengamos en cuenta que bombsPosition es un array de objetos con la posici贸n de las bombas

 bombsPosition.forEach((bomb) => {
    if (detectColission(bomb)) {
      console.log("You lose!!");
    }
  });

No creo que sea la manera mas optima evaluar con cada movimiento y comparar con todas las posiciones pero pensare en algo mientras continuo el curso.

Si usamos la l贸gica, claramente el mejor lugar de nuestro c贸digo para colocar el condicional que detecta las colisiones es en la funci贸n movePlayer().

驴Por qu茅?
Pues precisamente porque, hasta que no movamos nuestro jugador no sabremos si est谩 en una u otra posici贸n y por lo tanto el momento exacto en el que nos desplazamos es el ideal para analizar si hay una colisi贸n.

Agregu茅 un array vac铆o para guardar las posisiones

let bombPositions = [];

luego cuando iteramos las posisiones en el mapa asignamos las coordenadas de x , y y hacemos push al array con cada posisi贸n

mapRowToCol.forEach( (row, rowIndex) => {
        row.forEach( (col, colIndex) => {

            let posX = elementSize * (colIndex + 1);
            let posY = elementSize * (rowIndex + 1);        
            let emoji = emojis [col];

            let bombPosition = {
                X: undefined,
                Y: undefined,
            }
          
            if (col == 'O') {
                if(!playerPosition.X && !playerPosition.Y){
                    playerPosition.X = posX;
                    playerPosition.Y = posY;
                };
            } else if (col == 'I') {
                giftPosition.X = posX;
                giftPosition.Y = posY;
            } else if (col == 'X') {
                bombPosition.X = posX;
                bombPosition.Y = posY;

                bombPositions.push(bombPosition);
            
            } 

La razon por la cual los objetos constantes despues se pueden cambiar, es porque nunca cambiamos el tipo de dato.

const myObject = {
x : undefined
}

myObject.x = 10 //Estamos modificando la propiedad del objeto. pero sigue siendo un objeto.

myObject = new Array(1,2) //Error: 驴Porque? Porque estamos intentando cambiar el 鈥淭IPO鈥 de dato

el dato curioso sobre los objetos en javascript no la sibia. Gracias Juan David

Como estoy un objeto literal de mi mapa, entonces ahi le inserte el array de las bombas

const map= {
...
bombPosition: [],
...
}

Y para que se agregue cada posici贸n de la bomba
En el funcion render que esta dentro de mi objeto map, hago

if (y === "X") {
                    this.bombPosition.push({ x: posX, y: posY })
                }

As铆 pues ya se guarda todas las posiciones de las bombas

Ahora me puse el reto de que se renderice el siguiente mapa, cuando gane,
tomar en cuenta

  • Cuando pase de nivel se tiene que
  1. renderizar el nuevo mapa, con el personaje en la puerta
  2. El arreglo de las posiciones de las bombas tienes que reiniicarse, ya que seran otras posiciones

Para lo que agregre una nueva funcion que se llama lvlUp().
Esta funcion le aumenta el lvl, resetea el array de las bombas, puesto que en cada nivel tendremos diferentes posiciones, y vuelve a renderizar el game, con el siguiente nivel.
Es importante la parte de limpiar el array de bombas que creamos

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

}

Entonces como estamos haciendo pr谩cticamente todo cuando se mueve el jugador,
mi funcion que lo renderiza(si est谩n haciendo como el profe, seria su movePlayer), queda asi

  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()
            }
            endGame()
        }

    }

Ah, tambien cree la funcion endGame, que est谩 lo que hace es decirme cuando perdi, y tambien va dentro del render del jugador

function endGame() {
    for (let bomb of map.bombPosition) {
        const coincideX = Math.floor(map.playerPosition.x) === Math.floor(bomb.x);
        const coincideY = Math.floor(map.playerPosition.y) === Math.floor(bomb.y);

        if (coincideY && coincideX) {
            console.log("perdiste")
        }
    }
}

Con todo esto, ya subo de nivel, y tambien me dice cuando perdi
Sin embargo el bug que me esta corriendo es que, cuando paso por encima de una bomba, me aparece como si hubiera pasado varias veces

Lo que hice fue crear un array con objetos de las posiciones de las bombas, en el mismo lugar que hicimos lo de PLAYER y GIF
y una variable global
let bombasPosition = [];

      if (col == "X") {
        bombasPosition.push({
          x: posX,
          y: posY,
        });
      }

y abajo de donde se agrego la colisi贸n de gif
EL siguiente codigo.

const bombaColision = bombasPosition.find((position) => {
    const bombaColisionX = playerPosition.x.toFixed(3) == position.x.toFixed(3);
    const bombaColisionY = playerPosition.y.toFixed(3) == position.y.toFixed(3);
    return playerPosition.x
    ? bombaColisionX && bombaColisionY
    : false;
  });
  console.log("colision",bombaColision);
  if(bombaColision) console.log("Bomba Perdiste");
};

Con el find en el memento que encuentra la colisi贸n termina de buscar.