Tranquilo Juan, el error de los decimales me pasó desde la primera vez que probé el código jejeje. Te creemos!
Introducción
Programemos un juego con JavaScript
Canvas
¿Qué es canvas en JavaScript?
Tamaño del canvas y sus elementos
Canvas responsive
Mapa del juego
¿Qué es un array bidimensional?
Arreglos multidimensionales en JavaScript
Refactor del mapa de juego
Movimientos del jugador
Eventos y botones
Objeto playerPosition
Limpieza de movimientos
No te salgas del mapa
Colisiones
Detectando colisiones fijas
Detectando colisiones con arrays
Victoria: subiendo de nivel
Derrota: perdiendo vidas
Bonus: adictividad
Sistema de vidas y corazones
Sistema de tiempo y puntajes
¿Qué es localStorage?
Guardando records del jugador
Deploy
Depurando errores del juego
Desplegando el juego a GitHub Pages
Próximos pasos
Reto: reinicio del juego
Reto: timeouts de victoria o derrota
¿Quieres un simulador laboral?
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Juan David Castro Gallego
Aportes 36
Preguntas 1
Tranquilo Juan, el error de los decimales me pasó desde la primera vez que probé el código jejeje. Te creemos!
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
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();}
para no cambiar el const del array
enemyPosition.splice(0, enemyPosition.length);
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
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.
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")
}
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.
Mejor ponemos todas las coordenadas a dos decimales y nos quitamos de problemas.
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
})
}
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()
}
}
}
})
}
yo estoy usando Math.Floor en lugar del toFixed e.e
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++;
}
}
}
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
}
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 😉
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.
No es que no le salga el error, es que la consola no saca el error sino que no se ejecuta el console.log
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
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. = )
el error del que habla juan no tiene que ver con los decimales. mas bien tiene que ver conque cuando se hace mas grande o pequeña la pantalla la calabera osea el jugador no cambia su tamaño
tube el problema de los decimales desde el primer video, asi que ya me la esparaba
En mi caso puse un Math.round para redondear a enteros
function setCanvasSize(){
// para hacer que el canvas adopte el tamaño de la ventana html se requiere de realizar los siguientes comandos
elementSize = Math.round((Math.min(canvasSize = window.innerHeight *.8, canvasSize = window.innerWidth *.8)) /10);
canvasSize = elementSize*10;
canvas.setAttribute( 'width', canvasSize );
canvas.setAttribute( 'height', canvasSize);
startGame()
}
Luego en la funcion de moverPlayer, uso el arreglo de mapsColsRow
function movePlayer(){
const posiX = (playerPosition.x/elementSize)-1;
const posiY = (playerPosition.y/elementSize)-1;
if( playerPosition.x == gitPosition.x && playerPosition.y == gitPosition.y){
console.log('encontro el bambu');
}else if( mapRowCols[posiY][posiX] == 'X' ){
console.log('Ha una bomba X');
} else {
console.log('Ok');
}
//console.log( {elementSize, mapRowCols, playerPosition, posiX ,posiY} );
game.fillText( emojis['PLAYER'], playerPosition.x, playerPosition.y);
}
Solución de errores
Mi solución:
En mi caso no tuve problemas con el array de bombitas, ya que la función que se ejecuta cada vez que se realiza un movimiento es el movPlayer().
Por otro lado…no sé como no le sale el error al prof si desde que empezamos las colisiones de una tenía ese error 😂.
Al final tambien le coloque una validación para que me imprimiera en consola si el jugador vuelve a la puerta (Solo para entrenar jajajajaja)
const doorCollisionX = doorPosition.x.toFixed(3) === playerPosition.x.toFixed(3);
const doorCollisionY = doorPosition.y.toFixed(3) === playerPosition.y.toFixed(3);
const doorCollision = doorCollisionX && doorCollisionY;
if (doorCollision) {
if(messageInDoor == false) {
console.log('Good luck');
messageInDoor = true;
} else if(messageInDoor == true) {
console.log('Do you want to go at the previous level back?');
};
};
Me sirvió el toFixed(3)
Justamente me paso que… solo algunas bombas explotaban, porque los decimales no coincidian con la posicion del jugador. Entonces solucionamos con el metodo toFixed(5)=tomando en cuenta 5 decimales, que vimos en la clase anterior!
My solution:
positionBombs.forEach(e => {
const bombCollisionX = e.x.toFixed(5) == playerPosition.x.toFixed(5)
const bombCollisionY = e.y.toFixed(5) == playerPosition.y.toFixed(5)
const BOMB_COLLISION = (bombCollisionX && bombCollisionY)
if(BOMB_COLLISION){
console.log('EXplotastE!')
}
})
ami si me manda error si no usaba el toFixed(3)
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()
}
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?