No tienes acceso a esta clase

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

Detectando colisiones con arrays

13/24
Recursos

Aportes 12

Preguntas 0

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.

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

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

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

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.


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

Hice un objeto bomb position que por dentro tiene como arrays las coordenadas x / y de cada ‘X’ que se encuentre en el render del startGame(), además de un indicador de flag para que no se llenen nuevamente las mismas posiciones de las bombas dentro del render de la pantalla:

const bombsPos = {
    x: [],
    y: [],
};
let bombFlag = true;

...
 function startGame(){
...
if (col == 'X' && bombFlag == true) {
                bombsPos.x.push(posX);
                bombsPos.y.push(posY);
            }
...
bombFlag = false;
}

... //mas adelante

function movePlayer() {
    game.fillText(emojis['PLAYER'], playerPos.x, playerPos.y);

    let bombExpX = bombsPos.x.find( bomb => bomb == playerPos.x);
    let bombExpY = bombsPos.y.find( bomb => bomb == playerPos.y);

    if (playerPos.x == giftPos.x && playerPos.y == giftPos.y){
        level += 1;
        startGame();
    } else if (bombExpX == playerPos.x && bombExpY == playerPos.y) {
        console.log('BOOOOM')
    }    
  //esto nos permite además de la colision del regalito y pasar a otro nivel, también detectar la colision con las bombas sabiendo su coordenada  
}

En mi caso el error de los decimales me lo tope clases atrás y aun con el uso del método toFixed por si solo no soluciono el problema causado por la imprecisión de JS con los decimales. Lo solucioné de la siguiente manera:

function fixNumber(num) {
  return Number(num.toFixed(3));
}

Me costo encontrar la solucion para que el array no siga aumentando, lo hice de de esta manera:
Creo una constante que tendra la posicion de cada bomba en un array, pero tambien otra variable que sera la posicion inicial del player, que seria donde esta ubicada la puerta

const bombsPosition =[];
let startPosition =[];

Luego de tener las coordenadas de mi pocision inicial, creo un condicional para validar varias cosas(esto dentro de mi funcion starGame()

if(mapRowsCols[1][i][z-1] == 'X' && playerPosition.x === startPosition[0] && playerPosition.y === startPosition[1]){
                bombsPosition.push({x: elementSize*i, y: elementSize*z})
            }

De esta forma solo se agregaran las ubicaciones de las bombas, una sola vez y no en cada movimiento del player que llama a la funcion starGame()

Para limpiar el array de enemiesPositions, primero lo declararía con var o let para poder modificar su valor luego, luego escribiría dentro de la función startGame():

enemiesPositions = [];

justo debajo del .clearRect que usamos para limpiar el canvas

Este es mi aporte para detectar las colisiones con las bombas, en mi caso son árboles y no bombas.

Se crea el objeto global

const elementsPositions = {
    tree : [],
    bomb : [],
}

Luego, dentro de la función starGame() cree un array que guarda las posiciones de cada árbol y
luego guarda ese array de 2 elementos en la propiedad elementsPositions.tree:

if(emojis[col]=='🌲'){
                const treePosition = [];
                treePosition.push(posX.toFixed(2));
                treePosition.push(posY.toFixed(2));
                elementsPositions.tree.push(treePosition);
 }

Luego dentro de la función movePlayer() hago un ciclo para forEach y comparo si concuerdan las posiciones de algún árbol con la de mi player para renderizar la llamada de fuego en esa posición. Cabe destacar que la llama la renderizo después de renderizar al personaje.

elementsPositions.tree.forEach(row => {
        if(row[0] == player.x.toFixed(2) && row[1] == player.y.toFixed(2)){
            game.fillText(emojis['COLLISION'], player.x, player.y);
        }    
 });

Ahora sólo resta conocer la solución del profesor y aprender algo nuevo. = )

También se puede utilizar el objeto Set para poder utilizar su método clear(). Así no tendremos problemas con el const.

Asi me quedo
Tengo dos fucniones

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

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

Esa las uso dentro de mi objeto

const map={
...
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()
        }

    },
...
}

Y por ultimo mi funcion StartGame

function startGame() {
    map.bombPosition = []
    map.render()
    map.playerPosition.render()
}