No tienes acceso a esta clase

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

Depurando errores del juego

20/24
Recursos

Aportes 15

Preguntas 0

Ordenar por:

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

Yo lo solucioné creando otra objeto para la posición del jugador
Utilizo el objeto playerPostion para guardar el índice de la 🚪 y mi funciónmoverPlayer quedo así:
Por último, por cada movimiento con las teclas o los botones solo aumento en uno el valor de playerPostion

Les comparto mi código para que lo puedan verificar.

si esta complicado mover la pantalla mientras juegas XD
 

no mas por que mi compu no me aguanta el obs si no grabaría como queda con las animaciones mientras juego XD en fin.
 
si quieren evitar un dolor de cabeza con las posiciones y las colisiones, animaciones …o si le puse animaciones a esto cuando explotan las bombas y cuando mueres y mas cosas locas como sea esta es la solución para hacerles la vida mas sencilla
 

 
es tan fácil como transformar el mapa en un array lineal y solo crear las funciones de posX y poxY usando el índice y YA no hay mas es los mas fácil del mundo en fin espero le sirva a alguien

Para solucionar un poco los errores de los decimales, se le puede poner un toFixed(0) al ancho y alto del canvas.

https://paulaxam.github.io/taller-practico-js-videojuego/

Dejo mi jueguito, le cambié un poquito la temática para mandárselo a mi sobrino que tiene 4 añitos a que lo juegue, asique cambié las calaveras y explosiones por un paseo por el bosque. Agregué algunos mapitas, y cambié la estructura del css. De a poquito le iré agregando mas mapas y mejorándolo. Espero les guste!!!

Reposicionar al player al cambiar el tamaño de la viewport

Solución escrita:

  • Tuve que guardar el tamaño anterior del canvas, en mi caso toda la información del canvas estaba guardada globalmente en un objeto identificado como objCanvas, por lo que solo tuve que almacenarlo al inicio de la función setCanvasSize, antes de que se le asignara un nuevo tamaño al canvas. Al nuevo atributo lo llamé “oldSize”:

    .
  • Para reposicionar al player desarrolle una función que calculara los porcentajes equivalentes a las posiciones X e Y del player, a partir del tamaño anterior del canvas(oldSize). Luego ambos porcentajes llevarlos a su medida equivalente con el nuevo tamaño del canvas, lo que será suficiente para reposicionar al player. Para calcular las medidas equivalentes y porcentajes equivalentes solo utilicé la regla de tres.

    .
  • El llamado de la nueva función (repositionPlayer) se ejecutó al final de la función setCanvasSize antes de renderizar, dibujar o mostrará el juego.

La verdad fui resolviendo todos esos bugs mientras seguía el curso, y de hecho ahí faltan mencionar;
Que el tiempo que agarra para ponerlo en el record, está un poco desfasado, por unos segundo, por lo que hay que hacer unos pequeños ajuste.
Así quedo mi repo
https://estrelladlm.github.io/game-with-js/

este fue mi juego al final. https://eduardbarrios.github.io/taller_practico_JS_videogame/

Solucione lo de la calavera de la siguiente forma.
Hay que tomar la formula de la posicion en x y en y
Yo la tengo en +5 y --10 para acomodar las bombas y que no se salgan.del canvas-

      const posX = elementsSize * (col + 1) + 5;
      const posY = elementsSize * (rowIndex + 1) - 10;

Bueno vamos a despejar la ubicación de la columna y de la fila donde se encuentra nuestra calavera.

despejando col y row, me quedaron estas formulas. ahora ya se en que columna y fila se encuentra mi player

  const colPlayer=((playerPosition.x-5)/elementsSize)-1;
  const rowPlayer=((playerPosition.y+10)/elementsSize)-1;

y lo que hago es volver a realizar la misma formula de un principio con el nuevo elementSize y lo dibujamos.

  playerPosition.x=elementsSize*(colPlayer+1)+5;
  playerPosition.y=elementsSize*(rowPlayer+1)-10;
  game.fillText(emojis["PLAYER"], playerPosition.x, playerPosition.y);

y ya nos quedara nuestra calavera en la posición que esta.

Comparto mi solución para corregir el desfase del objeto jugador(calavera) al hacer resize.

Tengo dos variables globales llamadas:

let canvasSize; //Esta fue creada desde las primeras clases
let reCanvas; //Se guardará el primer canvasSize al cargar la página luego de un resize

// También agregué dos propiedades más a al objeto player; lastX y lastY
const player = {
    x: null,
    y: null,
    lastX : null,
    lastY : null,
}

Al principio de la función resizeCanvas(){} agregué el siguiente condicional

function resizeCanvas(){

    if(canvasSize){
        reCanvas = canvasSize; //Aquí se guarda el primer tamaño del canvas anterior como expliqué arriba
    }
.
.
.
	starGame();
}

Luego al llamarse starGame() justo dentro del ciclo forEach doble tengo el siguiente condicional:

starGame(){
.
.
.
map.forEach((row, rowIndex) => {
        row.forEach((col, colIndex) => {
           
            if(player.x || player.y){
                if(player.x.toFixed(2) == (elementSize*(colIndex+1.14)).toFixed(2)){
                    player.lastX = colIndex;
                }
                if(player.y.toFixed(2) == (elementSize*(rowIndex+0.88)).toFixed(2)){
                    player.lastY = rowIndex;
                }
            }
	 
	.
	.
	.
 	}
}

Como se puede ver; este condicional entra sólo si player.x o player.y tienen algún valor. Luego va a verificar si el valor de la posición de mi jugador en cada coordenada de la matriz es igual al valor de la coordenada actual dentro del ciclo y de esta manera guardará la posición del jugador dentro de la matriz, en que fila o columna está, y las guarda en player.lastX y player.lastY, ósea, estoy guardando los índices que tenía mi jugador dentro de la matriz.

Finalmente en la función movePlayer(){} ejecuto el siguiente condicional:

if(canvasSize > reCanvas || canvasSize < reCanvas){
        console.log('entro en 2');
    
        player.y = elementSize*(player.lastY+0.88);
        player.x = elementSize*(player.lastX+1.14);
       
        game.fillText(emojis['PLAYER'], player.x+4, player.y);      
    }
    else{
        //Renderizado de auto
        game.fillText(emojis['PLAYER'], player.x+4, player.y);
    }

Cuando halla un resize el va a comparar si el nuevo tamaño del canvas es mayor o menor al anterior, de ser así, va a guardar la posición en X y Y del jugador haciendo uso de los índices que tenía antes de que se haga resize, luego lo renderiza. Pero no no existe un resize pasará al else{} donde pondrá las coordenadas que normales cuando el usuario mueva al jugador.

Se que puede no entenderse sin ver el código completo. Lo estaré compartiendo la próxima clase. De todos modos es muy parecido a todo o que se ha hecho hasta ahora.

A mi solo me funciono esto con los decimales, tuve que aplicarlo a todos los valores:

canvasSize = Math.round((innerHeight * 0.8).toFixed(2));

Para reposicionar al jugador yo cree dos variables horizontalMovement y verticalMovement. Cuando se crea la calavera en startGame() le asigno columIndex y rowIndex a las dos variables anteriores, de forma que ya tengo identificada la posición inicial.

funtion startGame() {
...
	if (playerPosition.x == undefined && colum == 'O') {
        playerPosition.x = posX;
        playerPosition.y = posY;

        horizontalMovement = columIndex;
        verticalMovement = rowIndex + 1;

        console.log({ playerPosition });
      }
...
}

Ahora, cuando me muevo le resto o le sumo a horizontalMovement y verticalMovement, por ejemplo si me muevo hacia arriba:

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

  if ((playerPosition.y - elementSize).toFixed(2) < elementSize) {
    console.log('OUT');
  } else {
    playerPosition.y -= elementSize;
    verticalMovement--;

    if (enemiesCollision()) {
      levelFail();
    } else {
      giftCollision();
    }
    startGame();
  }
}

Le resto a verticalMovement.
Para que al hacer resize al llamar a setCanvaSize, si tengo valores en playerPosition, reasigno los valores de x y y usando horizontalMovement y verticalMovement :

function setCanvaSize() {
...
  if (playerPosition.x != undefined) {
      playerPosition.x = horizontalMovement * elementSize;
      playerPosition.y = verticalMovement * elementSize;
  }
...
}

En mi cabeza fue una buena idea, no sé si en cuanto a rendimiento sea buena.

cambie unos textos y variables a ingles! y asi fue como con la funcion fixNumber() arregle el codigo que el profe menciono 😃

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="./styles.css">
    <title>VideoGame Project</title>
</head>
<body>
    <div class="game-container">
        <canvas id="game"></canvas>
        <div class="btns">
            <button id="up">Up</button>
            <button id="left">Left</button>
            <button id="right">Right</button>
            <button id="down">Down</button>
        </div>
        <div class="messages">
            <p>lives: <span id="lives"></span></p>
            <p>Time: ⏰: <span id="time"></span></p>
            <p>Record: 🏁<span id="record"></span></p>
            <p id="result"></p>
        </div>
    </div>
    <script src="./maps.js"></script>
    <script src="./game.js"></script>
</body>
</html>

game.js

const canvas = document.querySelector('#game');
const game = canvas.getContext('2d');
const upButton = document.querySelector ('#up');
const rightButton = document.querySelector ('#right');
const leftButton = document.querySelector ('#left');
const downButton = document.querySelector ('#down');
const spanLives = document.querySelector('#lives')
const spanTime = document.querySelector('#time');
const spanRecord = document.querySelector('#record');
const pResult = document.querySelector('#result');

let canvasSize;
let elementsSize;
let level = 0;
let lives = 3;

let timeStart;
let timePlayer;
let timeInterval;


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

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

function fixNumber(n) {
  return Number(n.toFixed(0));
}

function setCanvasSize() {
  if (window.innerHeight > window.innerWidth) {
    canvasSize = window.innerWidth * 0.7;
  } else {
    canvasSize = window.innerHeight * 0.7;
  }
  canvasSize = Number(canvasSize.toFixed(0));
  
  canvas.setAttribute('width', canvasSize);
  canvas.setAttribute('height', canvasSize);
  
  elementsSize = fixNumber(canvasSize / 10);
  
  playerPosition.x = undefined;
  playerPosition.y = undefined;

  startGame();
}

function startGame() {
  console.log({ canvasSize, elementsSize });
  console.log(window.innerWidth, window.innerHeight);
  game.font = elementsSize + 'px Verdana';
  game.textAlign = 'end';
  
  const map = maps[level];
  if (!map) {
    gameWin();
    return;
  }

  if (!timeStart) {
    timeStart = Date.now();
    timeInterval = setInterval(showTime, 100);
    showRecord();
  }
  const mapRows = map.trim().split('\n');
  const mapRowCols = mapRows.map(row => row.trim().split(''));
  console.log({map, mapRows, mapRowCols});

  showLives();
  
  enemyPositions = [];

  game.clearRect(0, 0, canvasSize, canvasSize);
  mapRowCols.forEach((row, rowI) => {
    row.forEach((col, colI) => {
      const emoji = emojis[col];
      const posX = fixNumber(elementsSize * (colI + 1));
      const posY = fixNumber(elementsSize * (rowI + 1));

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

  movePlayer();
}

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

  if(giftCollision) {
    winningLevel();
  } 
  const enemyCollision = enemyPositions.find(enemy => {
    const enemyCollisionX =  enemy.x.toFixed(3) == playerPosition.x.toFixed(3);
    const enemyCollisionY = enemy.y.toFixed(3) == playerPosition.y.toFixed(3);
    return enemyCollisionX && enemyCollisionY;
  });

  if(enemyCollision) {
    levelFail();
  }

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

function winningLevel() {
  console.log('Level up');
  level ++;
  startGame();
}

function levelFail() {
  console.log("ENEMY!")
  lives--;

  console.log(lives)
  if(lives <= 0) {
    level = 0;
    lives = 3;
    timeStart=  undefined;
  }
  playerPosition.x = undefined;
  playerPosition.y = undefined;
  startGame();
}
function gameWin() {
  console.log('¡Terminaste el juego!');
  clearInterval(timeInterval);

  const recordTime = localStorage.getItem('record_time');
  const playerTime = Date.now() - timeStart;

  if (recordTime) {
    if (recordTime >= playerTime) {
      localStorage.setItem('record_time', playerTime)
      pResult.innerHTML ='you made a new record! Congratulations!';
     } else {
      pResult.innerHTML ='Sorry, this is not a record';
     }
  } else {
    localStorage.setItem('record_time', playerTime)
    pResult.innerHTML = 'first time playing? Try to get a new record';
  }

  console.log({recordTime, playerTime});
}

function showLives() {
  const heartsArray = Array(lives).fill(emojis['HEART']);
  console.log(heartsArray);

  spanLives.innerHTML = "";
  heartsArray.forEach(heart => spanLives.append(heart))
  
}
function showTime() {
  spanTime.innerHTML = Date.now() - timeStart;
}
function showRecord() {
  spanRecord.innerHTML = localStorage.getItem('record_time');
}

  //rowI and colI are the index
  
  // for (let row = 1; row <= 10; row++) {
    //   for (let col = 1; col <= 10; col++) {
      //     game.fillText(emojis[mapRowCols[row - 1][col - 1]], elementsSize * col, elementsSize * row);
      //   }
      // }
    
window.addEventListener('keydown', moveByKeys);
upButton.addEventListener('click', moveUp);
rightButton.addEventListener('click', moveRight);
leftButton.addEventListener('click', moveLeft);
downButton.addEventListener('click', moveDown);

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

  function moveUp() {
    console.log('Moving up');
  
    if ((playerPosition.y - elementsSize) < elementsSize) {
      console.log('OUT');
    } else {
      playerPosition.y -= elementsSize;
      startGame();
    }
  }
  function moveLeft() {
    console.log('moving left');
  
    if ((playerPosition.x - elementsSize) < 20) {
      console.log('OUT');
    } else {
      playerPosition.x -= elementsSize;
      startGame();
    }
  }
  function moveRight() {
    console.log('moving right');
  
    if ((playerPosition.x + elementsSize) > canvasSize) {
      console.log(elementsSize)
      console.log('OUT');
    } else {
      playerPosition.x += elementsSize;
      startGame();
    }
  }
  function moveDown() {
    console.log('moving down');
    
    if ((playerPosition.y + elementsSize) > canvasSize) {
      console.log('OUT');
    } else {
      playerPosition.y += elementsSize;
      startGame();
    }
  }

para solucionar lo del cambiar la solucion del jugador mientras juegas lo que hice fue establecer una variable global llamada oldElementSise y agregar una funcion llamada cambioTamañoJugador

<function setCanvasSize() {
  if (window.innerHeight > window.innerWidth) {
    canvasSize = window.innerWidth * 0.75;
  } else {
    canvasSize = window.innerHeight * 0.75;
  }
  
  canvas.setAttribute('width', canvasSize+15);
  canvas.setAttribute('height', canvasSize+15);
  oldElementZise=elementsSize;
  elementsSize = Math.floor(canvasSize / 10);
  if (playerPosition.x!=undefined && playerPosition.y!=undefined) {
    cambioTamañoJugador(elementsSize,oldElementZise);
  }
  startGame();
}
function cambioTamañoJugador(nuevaEscala,antiguaEscala) {
  playerPosition.x=playerPosition.x*(nuevaEscala/antiguaEscala);
  playerPosition.y=playerPosition.y*(nuevaEscala/antiguaEscala);
}> 

Creo 2 variables:

let ultima_x;
let ultima_y;

Dentro de la función movePlayer, le asigno a la variable ultima_x el valor de playerPosition.x, y a la variable ultima_y le asigno el valor de playerPosition.y.

    ultima_x = playerPosition.x;
    ultima_y = playerPosition.y;

Entonces dentro de la funcion setCanvasSize le asigno a playerPosition.x y playerPosition.y los últimos valores que tuvieron y que capturé en movePlayer:

        playerPosition.x = ultima_x;
        playerPosition.y = ultima_y;

Esto funciona si se hace resize de una sola dimensión a la vez, ya que en este caso las dimensiones internas del canvas se mantienen constantes. Pero si se hace resize en ambas dimensiones de la pantalla al mismo tiempo, la dimensión interna del canvas cambia constantemente y el player se desplaza.
Para resolver esto último, creo una tercera variable

let canvasSize1;

A la cual le asigno un valor con el mismo condicional del canvasSize original pero dentro de la función movePlayer

    if(window.innerHeight > window.innerWidth) {
        canvasSize1 = window.innerWidth * 0.7;
    }
    else {
        canvasSize1 = window.innerHeight * 0.7;
    }

Ahora dentro de la función setCanvasSize, modifico lo que había escrito, colocando la asignación de valores que había hecho dentro de la condición de que ambos valores de dimension del canvas sean iguales, pero que si la dimension interna del canvas cambió, entonces se utilce un factor de ajuste

    if(canvasSize == canvasSize1) {
        playerPosition.x = ultima_x;
        playerPosition.y = ultima_y;
    }
    else {
        playerPosition.x = ultima_x*(canvasSize/canvasSize1);
        playerPosition.y = ultima_y*(canvasSize/canvasSize1);
    }