CursosEmpresasBlogLiveConfPrecios

Detectando colisiones con arrays

Clase 13 de 24 • Taller Práctico de JavaScript: ¡Crea tu Primer Videojuego!

Clase anteriorSiguiente clase

Contenido del curso

Introducción

  • 1
    Programemos un juego con JavaScript

    Programemos un juego con JavaScript

    17:13 min

Canvas

  • 2
    ¿Qué es canvas en JavaScript?

    ¿Qué es canvas en JavaScript?

    18:37 min
  • 3
    Tamaño del canvas y sus elementos

    Tamaño del canvas y sus elementos

    17:37 min
  • 4
    Canvas responsive

    Canvas responsive

    12:37 min

Mapa del juego

  • 5
    ¿Qué es un array bidimensional?

    ¿Qué es un array bidimensional?

    05:48 min
  • 6
    Arreglos multidimensionales en JavaScript

    Arreglos multidimensionales en JavaScript

    23:38 min
  • 7
    Refactor del mapa de juego

    Refactor del mapa de juego

    20:48 min

Movimientos del jugador

  • 8
    Eventos y botones

    Eventos y botones

    14:14 min
  • 9
    Objeto playerPosition

    Objeto playerPosition

    11:34 min
  • 10
    Limpieza de movimientos

    Limpieza de movimientos

    09:53 min
  • 11
    No te salgas del mapa

    No te salgas del mapa

    11:15 min

Colisiones

  • 12
    Detectando colisiones fijas

    Detectando colisiones fijas

    13:29 min
  • 13
    Detectando colisiones con arrays

    Detectando colisiones con arrays

    Viendo ahora
  • 14
    Victoria: subiendo de nivel

    Victoria: subiendo de nivel

    07:50 min
  • 15
    Derrota: perdiendo vidas

    Derrota: perdiendo vidas

    11:45 min

Bonus: adictividad

  • 16
    Sistema de vidas y corazones

    Sistema de vidas y corazones

    13:02 min
  • 17
    Sistema de tiempo y puntajes

    Sistema de tiempo y puntajes

    19:30 min
  • 18
    ¿Qué es localStorage?

    ¿Qué es localStorage?

    07:33 min
  • 19
    Guardando records del jugador

    Guardando records del jugador

    18:35 min

Deploy

  • 20
    Depurando errores del juego

    Depurando errores del juego

    23:16 min
  • 21
    Desplegando el juego a GitHub Pages

    Desplegando el juego a GitHub Pages

    07:39 min

Próximos pasos

  • 22
    Reto: reinicio del juego

    Reto: reinicio del juego

    03:36 min
  • 23
    Reto: timeouts de victoria o derrota

    Reto: timeouts de victoria o derrota

    04:14 min
  • 24
    ¿Quieres un simulador laboral?

    ¿Quieres un simulador laboral?

    06:53 min
Tomar examen

Escuelas

  • Desarrollo Web
    • Fundamentos del Desarrollo Web Profesional
    • Diseño y Desarrollo Frontend
    • Desarrollo Frontend con JavaScript
    • Desarrollo Frontend con Vue.js
    • Desarrollo Frontend con Angular
    • Desarrollo Frontend con React.js
    • Desarrollo Backend con Node.js
    • Desarrollo Backend con Python
    • Desarrollo Backend con Java
    • Desarrollo Backend con PHP
    • Desarrollo Backend con Ruby
    • Bases de Datos para Web
    • Seguridad Web & API
    • Testing Automatizado y QA para Web
    • Arquitecturas Web Modernas y Escalabilidad
    • DevOps y Cloud para Desarrolladores Web
  • English Academy
    • Inglés Básico A1
    • Inglés Básico A2
    • Inglés Intermedio B1
    • Inglés Intermedio Alto B2
    • Inglés Avanzado C1
    • Inglés para Propósitos Específicos
    • Inglés de Negocios
  • Marketing Digital
    • Fundamentos de Marketing Digital
    • Marketing de Contenidos y Redacción Persuasiva
    • SEO y Posicionamiento Web
    • Social Media Marketing y Community Management
    • Publicidad Digital y Paid Media
    • Analítica Digital y Optimización (CRO)
    • Estrategia de Marketing y Growth
    • Marketing de Marca y Comunicación Estratégica
    • Marketing para E-commerce
    • Marketing B2B
    • Inteligencia Artificial Aplicada al Marketing
    • Automatización del Marketing
    • Marca Personal y Marketing Freelance
    • Ventas y Experiencia del Cliente
    • Creación de Contenido para Redes Sociales
  • Inteligencia Artificial y Data Science
    • Fundamentos de Data Science y AI
    • Análisis y Visualización de Datos
    • Machine Learning y Deep Learning
    • Data Engineer
    • Inteligencia Artificial para la Productividad
    • Desarrollo de Aplicaciones con IA
    • AI Software Engineer
  • Ciberseguridad
    • Fundamentos de Ciberseguridad
    • Hacking Ético y Pentesting (Red Team)
    • Análisis de Malware e Ingeniería Forense
    • Seguridad Defensiva y Cumplimiento (Blue Team)
    • Ciberseguridad Estratégica
  • Liderazgo y Habilidades Blandas
    • Fundamentos de Habilidades Profesionales
    • Liderazgo y Gestión de Equipos
    • Comunicación Avanzada y Oratoria
    • Negociación y Resolución de Conflictos
    • Inteligencia Emocional y Autogestión
    • Productividad y Herramientas Digitales
    • Gestión de Proyectos y Metodologías Ágiles
    • Desarrollo de Carrera y Marca Personal
    • Diversidad, Inclusión y Entorno Laboral Saludable
    • Filosofía y Estrategia para Líderes
  • Diseño de Producto y UX
    • Fundamentos de Diseño UX/UI
    • Investigación de Usuarios (UX Research)
    • Arquitectura de Información y Usabilidad
    • Diseño de Interfaces y Prototipado (UI Design)
    • Sistemas de Diseño y DesignOps
    • Redacción UX (UX Writing)
    • Creatividad e Innovación en Diseño
    • Diseño Accesible e Inclusivo
    • Diseño Asistido por Inteligencia Artificial
    • Gestión de Producto y Liderazgo en Diseño
    • Diseño de Interacciones Emergentes (VUI/VR)
    • Desarrollo Web para Diseñadores
    • Diseño y Prototipado No-Code
  • Contenido Audiovisual
    • Fundamentos de Producción Audiovisual
    • Producción de Video para Plataformas Digitales
    • Producción de Audio y Podcast
    • Fotografía y Diseño Gráfico para Contenido Digital
    • Motion Graphics y Animación
    • Contenido Interactivo y Realidad Aumentada
    • Estrategia, Marketing y Monetización de Contenidos
  • Desarrollo Móvil
    • Fundamentos de Desarrollo Móvil
    • Desarrollo Nativo Android con Kotlin
    • Desarrollo Nativo iOS con Swift
    • Desarrollo Multiplataforma con React Native
    • Desarrollo Multiplataforma con Flutter
    • Arquitectura y Patrones de Diseño Móvil
    • Integración de APIs y Persistencia Móvil
    • Testing y Despliegue en Móvil
    • Diseño UX/UI para Móviles
  • Diseño Gráfico y Arte Digital
    • Fundamentos del Diseño Gráfico y Digital
    • Diseño de Identidad Visual y Branding
    • Ilustración Digital y Arte Conceptual
    • Diseño Editorial y de Empaques
    • Motion Graphics y Animación 3D
    • Diseño Gráfico Asistido por Inteligencia Artificial
    • Creatividad e Innovación en Diseño
  • Programación
    • Fundamentos de Programación e Ingeniería de Software
    • Herramientas de IA para el trabajo
    • Matemáticas para Programación
    • Programación con Python
    • Programación con JavaScript
    • Programación con TypeScript
    • Programación Orientada a Objetos con Java
    • Desarrollo con C# y .NET
    • Programación con PHP
    • Programación con Go y Rust
    • Programación Móvil con Swift y Kotlin
    • Programación con C y C++
    • Administración Básica de Servidores Linux
  • Negocios
    • Fundamentos de Negocios y Emprendimiento
    • Estrategia y Crecimiento Empresarial
    • Finanzas Personales y Corporativas
    • Inversión en Mercados Financieros
    • Ventas, CRM y Experiencia del Cliente
    • Operaciones, Logística y E-commerce
    • Gestión de Proyectos y Metodologías Ágiles
    • Aspectos Legales y Cumplimiento
    • Habilidades Directivas y Crecimiento Profesional
    • Diversidad e Inclusión en el Entorno Laboral
    • Herramientas Digitales y Automatización para Negocios
  • Blockchain y Web3
    • Fundamentos de Blockchain y Web3
    • Desarrollo de Smart Contracts y dApps
    • Finanzas Descentralizadas (DeFi)
    • NFTs y Economía de Creadores
    • Seguridad Blockchain
    • Ecosistemas Blockchain Alternativos (No-EVM)
    • Producto, Marketing y Legal en Web3
  • Recursos Humanos
    • Fundamentos y Cultura Organizacional en RRHH
    • Atracción y Selección de Talento
    • Cultura y Employee Experience
    • Gestión y Desarrollo de Talento
    • Desarrollo y Evaluación de Liderazgo
    • Diversidad, Equidad e Inclusión
    • AI y Automatización en Recursos Humanos
    • Tecnología y Automatización en RRHH
  • Finanzas e Inversiones
    • Fundamentos de Finanzas Personales y Corporativas
    • Análisis y Valoración Financiera
    • Inversión y Mercados de Capitales
    • Finanzas Descentralizadas (DeFi) y Criptoactivos
    • Finanzas y Estrategia para Startups
    • Inteligencia Artificial Aplicada a Finanzas
    • Domina Excel
    • Financial Analyst
    • Conseguir trabajo en Finanzas e Inversiones
  • Startups
    • Fundamentos y Validación de Ideas
    • Estrategia de Negocio y Product-Market Fit
    • Desarrollo de Producto y Operaciones Lean
    • Finanzas, Legal y Fundraising
    • Marketing, Ventas y Growth para Startups
    • Cultura, Talento y Liderazgo
    • Finanzas y Operaciones en Ecommerce
    • Startups Web3 y Blockchain
    • Startups con Impacto Social
    • Expansión y Ecosistema Startup
  • Cloud Computing y DevOps
    • Fundamentos de Cloud y DevOps
    • Administración de Servidores Linux
    • Contenerización y Orquestación
    • Infraestructura como Código (IaC) y CI/CD
    • Amazon Web Services
    • Microsoft Azure
    • Serverless y Observabilidad
    • Certificaciones Cloud (Preparación)
    • Plataforma Cloud GCP

Platzi y comunidad

  • Platzi Business
  • Live Classes
  • Lanzamientos
  • Executive Program
  • Trabaja con nosotros
  • Podcast

Recursos

  • Manual de Marca

Soporte

  • Preguntas Frecuentes
  • Contáctanos

Legal

  • Términos y Condiciones
  • Privacidad
  • Tyc promociones
Reconocimientos
Reconocimientos
Logo reconocimientoTop 40 Mejores EdTech del mundo · 2024
Logo reconocimientoPrimera Startup Latina admitida en YC · 2014
Logo reconocimientoPrimera Startup EdTech · 2018
Logo reconocimientoCEO Ganador Medalla por la Educación T4 & HP · 2024
Logo reconocimientoCEO Mejor Emprendedor del año · 2024
De LATAM conpara el mundo
YoutubeInstagramLinkedInTikTokFacebookX (Twitter)Threads
        Manuel Araujo

        Manuel Araujo

        student•
        hace 3 años

        Tranquilo Juan, el error de los decimales me pasó desde la primera vez que probé el código jejeje. Te creemos!

          Gianluca Enzo Procopio

          Gianluca Enzo Procopio

          student•
          hace 3 años

          X2 jajajaj

          JUAN DAVID MARIN URIBE

          JUAN DAVID MARIN URIBE

          student•
          hace 3 años

          x3 Despues de un rato debugueando me di cuenta lo que pasaba, sin saber que en los ultimos 3 minutos del video estaba la explicaion jajaj

        Angel David Velasco Bonifaz

        Angel David Velasco Bonifaz

        student•
        hace 3 años

        Para no volver hacer el array en cada movimiento y estar limpiando, solo coloque una variable bandera.

        let flag=true;

        y donde asignamos las posiciones de las bombas se pone un condicional.

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

        y afuera del ciclo for each de las rows, colocamos la bandera en falso

        flag=false;

        con eso cuando se vuelva a pasar ya no agregara otra vez las bombas

          César Augusto Cortés Labrada

          César Augusto Cortés Labrada

          student•
          hace 3 años

          Me parece una solución bastante acertada.

          Luis Palomo

          Luis Palomo

          student•
          hace 3 años

          Si, yo pensé lo mismo. Si el array fuera más largo estaríamos renderizando siempre eso.

        marco antonio

        marco antonio

        student•
        hace 3 años

        ver tanta re-iteración hace que me duela la ram y me lastime el procesador XD, Ya hablando en serio el código de la clase se ve un poco.. rebelde, me cuesta seguirlo

        como sea agregue algunas cosillas a mi código y lo he hecho un poquito mas eficiente creo que esta listo para que lo encapsule en una clase y haga unas modificaciones finales para que sea adaptativo
        //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 explociones = Array(); let vidas = 3; 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(Victoria() && actualizado) return; cargarMapa(); clear(); paintEvent(); paintEventPlayer(); paintEventExplosion(); paintEventGameOver(); paintEventVictory(); actualizado = true;} function cargarMapa(){ if(nivel_actual == nivel || Victoria()) 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 && !Victoria()) mapa.forEach((char, idx) => { if(char == 'O' && posJugador == undefined) puntoDePartida = posJugador = idx; juego.fillText(emojis[char], posX(idx), posY(idx) );});} function paintEventPlayer(){ if(victoryEvent()) paintEventVictory(); else { 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 && mapa[posJugador] == 'X'){ explociones.push(posJugador); --vidas; juego.fillText(emojis['BOMB_COLLISION'],posX(posJugador),posY(posJugador)); posJugador = puntoDePartida;} if(!vidas) { explociones = Array(); return false;} /*juego terminado*/ return true; /*continuar con el juego*/} function paintEventExplosion(){ if(!explociones.length) return; explociones.forEach((pos) =>{ clearRect(pos); juego.fillText(emojis['BOMB_COLLISION'],posX(pos),posY(pos));});} function victoryEvent(){ if(mapa[posJugador] != 'I') return false; else if(nivel < map.length) ++nivel; explociones = Array(); if(Victoria()) return true; posJugador = prePosJugador = undefined; actualizado = false; update(); return false;} function paintEventGameOver(){ if(vidas) return; paintScreen('Game Over','GAME_OVER', '#FF2F22', '#211A27');} function paintEventVictory(){ if(!Victoria()) return; paintScreen('Has Ganado','WIN','#ffd700','#01433A');} function Victoria(){return nivel >= map.length;} function paintScreen(txt, emoji, colortxt = '#fff', backgroundColor ='#000'){ juego.clearRect(0,0, canvas_t, canvas_t); mapa.forEach((char, idx) =>{ if(char == 'X') char = emoji; juego.fillText(emojis[char],posX(idx),posY(idx));}); const fuente = celda_t - celda_t / 10 ; const media = canvas_t / 2; juego.fillStyle = backgroundColor; juego.fillRect(0, media - (fuente /2), canvas_t, fuente); juego.textAlign = 'center'; juego.fillStyle = colortxt; juego.fillText(txt, media, media + fuente/3); juego.textAlign='end';} //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();}
          Aaron Santiago Loyo Zabala

          Aaron Santiago Loyo Zabala

          student•
          hace 3 años

          Mucho Texto

          Emilio Sala

          Emilio Sala

          student•
          hace 3 años

          tal vez el propósito de la clase es enseñarnos lo que no debemos hacer y buscar mejor formas de resolver los problemas que nos van surgiendo por nuestra cuenta. en los aportes hay muy buenas formas de avanzar

        Valeria Soledad Paez

        Valeria Soledad Paez

        student•
        hace 3 años

        para no cambiar el const del array

        enemyPosition.splice(0, enemyPosition.length);
        Eduard Barrios

        Eduard Barrios

        student•
        hace 3 años

        jajajaja me da risa que a Juan no le parece el error pero a mi me apreció antes de que él lo mencionara y lo solucioné luego él lo menciona pero no le sale y a mi me sale cada que muevo al jugador

        Kevin Camacho

        Kevin Camacho

        student•
        hace 3 años

        vaciar un array

        Así me enseñó Notion IA.

        const array = ['h', 'o', 'l', 'a', 'm', 'u', 'n', 'd', 'o'] array.length = 0

        Obviamente funciona pero no se si es la mejor manera de hacerlo.

        Jhon Eduard Bocanegra Ortiz

        Jhon Eduard Bocanegra Ortiz

        student•
        hace 3 años
        lalala.png
        Gianluca Enzo Procopio

        Gianluca Enzo Procopio

        student•
        hace 3 años

        Para detectar una colisión hice una validación true/false con el método SOME de arrays. Lo vimos en el curso de manipulación de arrays. Pero si no lo viste, el metodo some se trata de que si al menos un elemento del array cumple con la condición, devuelve true.

        if(enemyPosition.some(item => item.x == playerPosition.x && item.y == playerPosition.y)){ alert("Chocaste con una bomba") }
        Luis Palomo

        Luis Palomo

        student•
        hace 3 años

        Juan! A mi me pasó el error que decías. Incluso lo arreglé antes que lo mencionaras y me rascaba la cabeza pensando porque a mi no me funcionaba y a vos si. Así que te entiendo jaja.

          Gianluca Enzo Procopio

          Gianluca Enzo Procopio

          student•
          hace 3 años

          X2 jajajajaja

        Hector Maluy Fernandez

        Hector Maluy Fernandez

        student•
        hace 3 años

        Mejor ponemos todas las coordenadas a dos decimales y nos quitamos de problemas.

        platzi.png

        leonardo alies fuentes

        leonardo alies fuentes

        student•
        hace 3 años

        la verdad no me funciona el código copie y pegue el tuyo y tampoco me funciono mmm no por cual motivo

          Rubén Cuello

          Rubén Cuello

          student•
          hace 3 años

          Hola @leoaliesf397. ¿Podrías compartirnos tu código y una descripción un poco más detallada sobre qué es lo que no funciona? De esta manera estoy seguro de que podremos ayudarte.

          Juan camilo piedrahita londoño

          Juan camilo piedrahita londoño

          student•
          hace 3 años

          Colocastes el toFixed(3)? A mi no me estaba funcionando. Pero con toFixed(3). No hubo problema

        Nestor Rios Garcia

        Nestor Rios Garcia

        student•
        hace 2 años

        Yo tengo un contador de movimientos

        let moves = 0;

        Y aumenta cada vez que se mueve el jugador

        function movePlayer(direction) { moves++ . . .

        Asi que si integro mi contador en el condicional solo se ejecutara una vez

        if (column === 'X' && moves === 0) { bombsPositions.push({ x: xPosition, y: yPosition }) }
        Mauricio Combariza

        Mauricio Combariza

        student•
        hace 3 años

        Yo cree una funcion render, una start game y una movePlayer y en la de startGame cree el array con todos los elementos, incluyendo los espacios y los regalos y lo que pongamos después, en el render no creo ningun array. Este es mi código:

        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') level = 0 // setCanvasSize() } if(item.elem === 'I') { console.log('Ganaste eeee') if(level > maps.length - 1){ console.log('Fin del juego Ganaste!!') } else { level += 1 mapaActual = [] startGame() } } } }) }
        Alejandro Ramos

        Alejandro Ramos

        student•
        hace 3 años

        yo estoy usando Math.Floor en lugar del toFixed e.e

        Carlos Andres Alavez Santiago

        Carlos Andres Alavez Santiago

        student•
        hace 3 años

        Convertí los maps a Let, agregue un index para cambiar de mapa, para checar si es bomba o regalo, convertí las coordenadas a posición de un arrglo, para solucionar el problema de los decimales, usé Math.Round.

        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++; } } }

        Aquí dejo el resto del programa, donde incluso reinicio de niviel con un index al playerPosition, que se resetea cada que encuentra bomba.

        Dejo todo el programa porque hice varios cambios

        const canvas= document.querySelector('#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 elementSize; let indexMap = 0; let map; let mapRows; let mapCols; let posX; let posY; const playerPosition={ x: undefined, y: undefined, i: 0, }; window.addEventListener('load', setCanvasSize); window.addEventListener('resize',setCanvasSize); function setCanvasSize(){ if (window.innerHeight > window.innerWidth){ canvasSize = window.innerWidth * 0.80; } else{ canvasSize = window.innerHeight * 0.80; } canvas.setAttribute('width', canvasSize); canvas.setAttribute('height', canvasSize); elementSize = canvasSize/10; startGame(); } function startGame(){ game.font = elementSize-10 + 'px Verdana'; game.textAlign = 'end'; convertMap(); game.clearRect(0,0,canvasSize,canvasSize); mapCols.forEach((rows,rowsI) => { rows.forEach((item, itemI)=>{ if(item == 'O' && playerPosition.i==0){ playerPosition.x = elementSize*(itemI+1); playerPosition.y = elementSize*(rowsI+1); playerPosition.i = 1; //console.log(elementSize*(itemI+1), elementSize*(rowsI+1)); } game.fillText(emojis[item], elementSize*(itemI+1), elementSize*(rowsI+1)); }); }); movePlayer(); /* for(let i=1; i<=10;i++){ for(let j=1; j<=10; j++){ game.fillText(emojis[mapCols[i-1][j-1]], elementSize*j, elementSize*i); } } */ } function convertMap(){ map = maps[indexMap]; mapRows = map.trim().split('\n'); mapCols = mapRows.map(row=>row.trim().split('')); } function movePlayer(){ game.fillText(emojis['PLAYER'], playerPosition.x, playerPosition.y); } window.addEventListener('keydown', moveByKeys); btnUp.addEventListener('click',moveUp); btnLeft.addEventListener('click',moveLeft); btnRight.addEventListener('click',moveRight); btnDown.addEventListener('click',moveDown); function moveByKeys(event){ if(event.key=='ArrowUp'){ moveUp(); } else if(event.key=='ArrowDown'){ moveDown(); } else if(event.key=='ArrowRight'){ moveRight(); } if(event.key=='ArrowLeft'){ moveLeft(); } } 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++; } } }
        David Fernando Estacio Quiroz

        David Fernando Estacio Quiroz

        student•
        hace 3 años

        Yo decidí hacer algo diferente, en lugar de guardar la posición del jugador en pixeles guardé la posición por filas y columnas:

        if(!playerPosition.X && key == 'O'){ playerPosition.X = i; playerPosition.Y = j; }

        Uso esta funcion para renderizar al jugador:

        function renderPlayer() { console.log(playerPosition) game.fillText( emojis['PLAYER'] , Math.floor(elementSize * playerPosition.X+1), Math.floor(elementSize * playerPosition.Y+1) ); }

        Y luego, para detectar las colisiones, uso un condicional en cada movimiento que invoca a una función:

        function isColliding(newRow, newColumn) { switch (columns[newRow][newColumn]) { case 'O': console.log('Returned to the start'); (nivel-1 < 0) ? nivel=nivel : nivel-=1; break; case 'X': console.log('Collided'); return true; case 'I': console.log('Finished level'); (nivel+1 == maps.length) ? nivel=nivel : nivel+=1; break; default: break; } return false }
        David Ochoa

        David Ochoa

        student•
        hace 3 años

        Para evitar el problema de que las posiciones no coincidan, lo solucione almacenando los indices de cada bomba y del regalo en lugar de su valor "x" y "y"

        if (col == "I") { giftIndex = { ix: colI, iy: rowI, }; } if (col == "X") { bombIndexes.push({ ix: colI, iy: rowI }); }

        De igual manera mi objeto de player position almacena el indice en el que se encuentra

        if (col == "O") { if (!playerPosition.x && !playerPosition.y) { playerPosition = { x: posX, y: posY, ix: colI, iy: rowI, }; } }

        Y finalmente se realiza la comparación con los índices

        function checkCollision() { const giftCollitionX = giftIndex.ix == playerPosition.ix; const giftCollitionY = giftIndex.iy == playerPosition.iy; const isGift = giftCollitionX && giftCollitionY; if (isGift) { console.log("Ganaste!"); return; } const isBomb = bombIndexes.find((bomb) => { const collitionX = bomb.ix == playerPosition.ix; const collitionY = bomb.iy == playerPosition.iy; return collitionX && collitionY; }); if (isBomb) { console.log("Colision"); return; } }

        Espero haber ayudado a alguien 😉

        Ivo Zayas

        Ivo Zayas

        student•
        hace 3 años

        Hola amiguitos!!! comparto mi solución que creo que es más práctica:

        if (col == 'O') { if (!playerPosition.x && !playerPosition.y){ playerPosition.x = posX playerPosition.y = posY } } else if(col == 'I'){ checkGiftCollision(posX, posY) } else if(col == 'X'){ checkBombCollision(posX, posY) }

        Cuando estoy fijándome dentro del forEach() si el indice actual es una bomba o un regalo, llamo a las funciones 'chackBombCollision()' o 'checkGiftCollision()' dependiedno el caso. Estas reciben como parámetro la posición actual de 'col' (posX y posY).

        function checkGiftCollision(giftX, giftY){ if (giftY.toFixed(3) == playerPosition.y.toFixed(3) && giftX.toFixed(3) == playerPosition.x.toFixed(3)) { console.log('Felicidades'); } }

        function checkBombCollision(bombX, bombY) { if (bombY.toFixed(3) == playerPosition.y.toFixed(3) && bombX.toFixed(3) == playerPosition.x.toFixed(3)) { console.log('Perdiste'); } }

        Entonces comparo 'playerPosition.x' y 'playerPosition.y' con 'giftX' y 'giftY' o 'bombX' y 'bombY' y listo el pollo pelada la gallina!!! Por ahora creo que funciona, no se si se va a complicar más adelante. Aparte puedo prescindir de los objetos 'giftPosition' y 'enemyPositions' que necesitaba el profe para su solución.

        Cristian Zapata

        Cristian Zapata

        student•
        hace 3 años

        No es que no le salga el error, es que la consola no saca el error sino que no se ejecuta el console.log

        Andres Eduardo Maneiro Antunez

        Andres Eduardo Maneiro Antunez

        student•
        hace 3 años

        mi solucion es que no cree ningun array, me aparecio mas simple realizar condicionales cuando se renderiza el mapa

        la logica es mas simple, cuando se realiza un movimiento del jugador llama la function de render, y en el renderizado compara tan la "I" que es el regalo y la "X" que es el obstaciulo, llama a una funcion de vicoria o de derrota

        function renderMap() { game.font = `${elementsSize}px Verdana`; game.textAlign = 'end'; const map = maps[level]; game.clearRect(0, 0, canvasSize, canvasSize); const mapRows = map.trim().split('\n'); //trim() es un metodo que remueve los espacios en blanco de los treing y lo devuelve en un nuevo `string` sin modificar el original, el .split, elimina el caracter que se le indique en el argumento const mapRowsCols = mapRows.map(row => row.trim().split('')); game.clearRect(0, 0, canvasSize, canvasSize); mapRowsCols.forEach((row, rowIndex) => { row.forEach((col, colIndex) => { const emoji = emojis[col]; const posX = (elementsSize * (colIndex + 1))+12; const posY = elementsSize * (rowIndex + 1); if (col == 'O') { playerPosition.initialX = posX; playerPosition.initialY = posY; }; if (col == 'I') { if(playerPosition.x == posX && playerPosition.y == posY) { win(); return } } if (col == 'X') { if(playerPosition.x == posX && playerPosition.y == posY) { lose() return } } game.fillText(emoji, posX, posY); }); }); return