El profe: “Super bien, cómo vas viendo el juego”
Yo:
Fundamentos de Programación
Bienvenida a Platzi: ¿qué necesitas para tomar el curso?
Programación en Navegadores: Primeros Pasos
Crea tu primer sitio web
Sitios web con HTML
Estructura de árbol en HTML
Instalando tu primer editor de código
Cómo declarar variables y usar prompt
Algoritmo de piedra, papel o tijera
Algoritmo avanzado de piedra, papel o tijera
Aleatoriedad
Refactor del código usando funciones
Ciclos
Gana 3 veces
Archivos de HTML y JavaScript
¿Qué es el DOM?
Quiz: Fundamentos de Programación
Desarrollando un juego con HTML y JavaScript
Maquetación con HTML
Sección de elegir mascota
¿Dónde ubicar la etiqueta script? Conectando HTML con JavaScript
Escuchando eventos con JavaScript
addEventListener
Manipulación del DOM
Enemigos aleatorios
Ataques en JavaScript
Ataques aleatorios del enemigo
Imprimiendo ataques del enemigo
¿Ganaste, perdiste o empataste?
Tablas de verdad
Creando el contador de vidas
¿Quién ganó el juego?
Reiniciando el juego
Ocultando elementos HTML con JS para mejorar la UX del juego
Quiz: Desarrollando un juego con HTML y JavaScript
Estilos con CSS
Anatomía de CSS
Tipos de display
Flexbox
Modelo de caja
Imágenes para los Mokepones
Estilos del botón
Adaptando HTML al diseño del juego
Layout: título y ataques
Adaptando JavaScript al diseño del juego
CSS Grid
Responsive Design
Detalles finales
Quiz: Estilos con CSS
Optimización de código
Revisión de código
Don't repeat yourself (DRY)
Clases y objetos
Clases y objetos de Mokepon
Arrays o arreglos
Objetos vs. arreglos
Ciclos: manipulando el DOM con iteradores
Declaración lenta de variables
Una sola fuente de la verdad
Mascotas aleatorias con arreglos
Ataques dinámicos por cada mascota: extraer
Renderizado dinámico en HTML
Eventos de click dinámicos
Secuencia de ataques del enemigo
Iniciando el combate
Resolviendo el reto de condicionales
Optimizando el frontend del juego
Quiz: Optimización de código
Mapa con canvas
Introducción a canvas: dibujando con JavaScript
Moviendo a Capipepo hacia la derecha
Movimiento hacia todas las direcciones
Movimientos con el teclado
Imágenes y personajes de fondo
Métodos en las clases
Obstáculos y colisiones
Combate entre mokepones colisionados
Mapa responsive
Botones bonitos y viewport
Quiz: Mapa con canvas
Backend: videojuego multijugador
¿Qué es backend?
Instalación de Node.js y NPM
Terminal de comandos y Node.js
Servidor web con Express.js
HTTP, localhost, servidores y puertos
Express.js y fetch: API REST con JavaScript
JSON y POST: mokepon online
Transmisión de coordenadas
Mokepones dinámicos en el mapa
Optimizando el mapa del juego
Batalla entre jugadores
Consumiendo la API de ataques del enemigo
Quiz: Backend: videojuego multijugador
Próximos pasos
Probando el juego en varios dispositivos
¿Y ahora qué curso tomar?
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Diego De Granda
Ya tienes la lógica del mokepon que selecciona el usuario para el combate. Ahora, debes preparar al mokepon enemigo para que esté listo para combatir y determinar al ganador de la pelea.
Declara dos variables, ataquesMokeponEnemigo
para almacenar un arreglo con los ataques del enemigo seleccionado y otra variable ataqueEnemigo
donde se guardarán los ataques aleatorios para el combate.
let ataquesMokeponEnemigo;
let ataqueEnemigo = [];
Luego de que el jugador seleccione su mokepon a través de la función seleccionarMascotaJugador()
, lanza la función seleccionarMascotaEnemigo()
para ejecutar la misma lógica aleatoria para seleccionar un mokepon aleatorio y determinar sus ataques también de forma aleatoria.
function seleccionarMascotaJugador() {
// ...
seleccionarMascotaEnemigo()
}
function seleccionarMascotaEnemigo() {
let mascotaAleatoria = aleatorio(0, mokepones.length - 1);
spanMascotaEnemigo.innerHTML = mokepones[mascotaAleatoria].nombre;
ataquesMokeponEnemigo = mokepones[mascotaAleatoria].ataques;
secuenciaAtaque();
}
Una vez esté lista la lógica de los ataques del mokepon seleccionado por el usuario, lanzaremos la función ataqueAleatorioEnemigo()
para preparar los ataques del enemigo.
function secuenciaAtaque() {
botones.forEach((boton) => {
boton.addEventListener('click', (e) => {
// ...
ataqueAleatorioEnemigo();
})
})
}
Con esta función, se selecciona un ataque aleatorio del mokepon enemigo para combatir contra los ataques del mokepon del jugador, cada vez que el mismo se selecciona un ataque.
function ataqueAleatorioEnemigo() {
let ataqueAleatorio = aleatorio(0, ataquesMokeponEnemigo.length - 1);
if (ataqueAleatorio == 0 || ataqueAleatorio == 1) {
ataqueEnemigo.push('FUEGO');
} else if (ataqueAleatorio == 3 || ataqueAleatorio == 4) {
ataqueEnemigo.push('AGUA');
} else {
ataqueEnemigo.push('TIERRA');
}
console.log(ataqueEnemigo);
combate();
}
La lógica para el combate está casi lista, tanto la lógica del mokepon y del usuario como el mokepon aleatorio. Solo resta un paso para finalizar la lógica de todo el combate de tu videojuego.
Contribución creada por: Kevin Fiorentino (Platzi Contributor)
Aportes 115
Preguntas 41
El profe: “Super bien, cómo vas viendo el juego”
Yo:
Hola!! yo cambié un poquito el código porque entiendo que si dejamos solo en random la elección del enemigo de la secuencia de ataques no se está considerando el personaje elegido por el mismo, es decir, si el enemigo elige por ejemplo Hipodoge, el random de la secuancia de ataques del enemigo solo debería formarse por 3 aguas, 1fuego y 1 tierra (cualquier combinación de estos 5 elementos). No se si estoy interpretando mal la solución que se propone, pero en todo caso dejo mi aporte de como lo implementé en mi código.
La variable** ataquePC** contiene los ataques del personaje elegido por el enemigo, luego lo que hice fue ordenar estos ataques en forma random con el método sort()
ataquePC.sort(()=>Math.random()-0.5**)**;
De esta forma, el enemigo solo podrá atacar con una secuencia que corresponda al personaje elegido por la pc.
Los errores te hacen mas fuerte, yo despues de terminar las clases del profe diego:
posdata: buen trabajo¡¡
Aqui mi solucion para que se tome en cuenta la mascota del enemigo y para que sus ataques no puedan repetirse:
let newArray = []
function selectEnemyPet () {
let randomPet = randomNumber(0, mokepones.length - 1);
enemysPet.innerHTML = mokepones[randomPet].name;
enemysAttack = mokepones[randomPet].attack;
for (let ind in enemysAttack) {
newArray.push(ind);
}
console.log(enemysAttack);
};
function setEnemyAttack () {
console.log(newArray);
let randomInd = randomNumber(0, newArray.length - 1);
let randomAttack;
if (newArray.length <= 1) {
randomAttack = newArray[0];
} else {
randomAttack = newArray[randomInd];
}
console.log(randomAttack);
if (enemysAttack[randomAttack].name === "🔥") {
enemyAttackCounter.push("FUEGO");
} else if (enemysAttack[randomAttack].name === "🌊") {
enemyAttackCounter.push("AGUA");
} else if (enemysAttack[randomAttack].name === "🌱") {
enemyAttackCounter.push("TIERRA");
}
newArray.splice(randomAttack, 1);
console.log(enemyAttackCounter);
};
NOTA: me tomo un laaarrrgo rato(horas) dar con la solucion, y estoy seguro que hay muchas soluciones posibles, asi que no te rindas y nunca pares de aprender!
alamaye en este punto ya siento más dificil seguirle el paso al profe. Me detengo mucho a analizar y comprender pero ME ENCANTA :3
Espero poder tener la capacidad de aprender y aplicar las lógicas que ha venido haciendo el prof en estas últimas clases en otros proyectos sin ayuda
Veo a muchas personas con experiencia en los comentarios, dando soluciones que a veces nosotros los nuevos ni comprendemos jajajaja… Estoy haciendo el curso tal cual y como lo hace el profesor con el fin de entender lo máximo posible y luego de culminarlo pasar a una de sus rutas desde 0 :´).
Sugiero que en vez de añadir un cambio de calor al botón después de ser seleccionado mejor sele agregue la propiedad disable, esto para evitar que vuelva a usar.
Se asignan los ataques del enemigo, de manera aleatoria, guardándolo en un arreglo
En la función ataqueAleatorioEnemigo()
creo el siguiente código
// Variable que guarde un número (índice)
let i = aleatorio(0, ataquesMokeponEnemigo.length - 1)
/* Se valida ataque asignado según índice y se guarda el nombre en el array ataqueEnemigo */
if (ataquesMokeponEnemigo[i].nombre === '🔥') {
ataqueEnemigo.push('FUEGO')
} else if (ataquesMokeponEnemigo[i].nombre === '🌊') {
ataqueEnemigo.push('AGUA')
} else {
ataqueEnemigo.push('TIERRA')
}
/// Se elimina ataque asignado a enemigo del arreglo ataquesMokeponEnemigo
ataquesMokeponEnemigo.splice(i, 1)
Creo que algo que pude confundir un poco, es que se están creando las funciones de manera implícita pero el hecho de que se defina allí, no significa que ocurra ahora mismo.
boton.addEventListener(‘click’, (e) => { }
Esto significa que estoy creando una funcion sin nombre, por lo que solo se ven los parentesis, y estoy pasandole como parámetro “e”, el cual es un objeto estandar del sistema y que estaba disponible en ese momento DENTRO de addEventListener… Entonces:
funcionSinNombre(e) se ejecutará correctamente, pero, no se puede llamar desde otro punto porque no tiene un nombre explícito… También puede resultar más dificil de depurar.
Me parece excelente como va el curso, pero hay conceptos que requieren práctica para que los más nuevos lo entiendan, y explicarlos un poquito podría potenciar su uso en la creatividad de todos. Yo soy nuevo en JavaScript, espero no equivocarme mucho y que les sea util.
Cada vez que veo que comete un error y no le puedo decir, automaticamente entro en MOD ANSIEDAD
Jajaja
Mis secuencias solo son TIERRA, TIERRA, TIERRA, TIERRA sin importar que seleccione, Tengo el código tal cual, A este punto es bien difcil y no entiendo casi nada, solo quiero acabar el curso por ansiedad geez T_T
Igual que algunos compañeros, me di cuenta que en la solución planteada por el profe no se tienen en cuenta los ataques del mokepon enemigo y si estos se repiten o no. Estuve intentando seguir la lógica de que una vez que elijamos un ataque, el enemigo elija un ataque también y así fue como me quedó.
Lo primero que hice fue crear un array global (enemyAttacks) para almacenar los números aleatorios que se convertirán en los ataques enemigos. Luego creé otro array global (enemySequence) en el que se almacena la secuencia de ataques enemigos ya transformados en emojis(los cuales he estado utilizando como ataques)
Luego, igual que el profe, declaré una variable y le agregué el número aleatorio entre 0 y 4 en este caso
function chooseEnemyAttack() {
let randomAttack = randomNumber(0, (enemyMokeponAttack.length - 1))
Posteriormente utilicé el método includes para verificar si el número aleatorio randomAttack que se acaba de generar se encuentra en el array enemyAttacks.
if (enemyAttacks.includes(randomAttack) === false)
Si la condición no se cumple (false)(el ataque no se repite)
entonces se agrega el numero aleatorio randomAttack al array enemyAttacks y se genera un nuevo condicional en el cual comparamos al array que contiene los ataques del mokepon enemigo enemyMokeponAttacks en la posicion randomAttack(que tiene como valor un numero de ataque que no se ha repetido, por ejemplo el 2) en su .name (que tiene por nombre el emoji correspondiente) con los distintos ataques 🔥, 💧 o 🍃 y si coincide, el ataque será agregado al array que contiene la secuencia de ataques enemigos enemySequence. Luego llama a la funcion que compara los ataques para dar una victoria (la cual se encuentra rota ahora mismo)
if (enemyAttacks.includes(randomAttack) === false) {
enemyAttacks.push(randomAttack)
if (enemyMokeponAttacks[randomAttack].name == "🔥") {
enemySequence.push("🔥")
}
else if (enemyMokeponAttacks[randomAttack].name == "💧") {
enemySequence.push("💧")
}
else {
enemySequence.push("🍃")
}
battleResult()
}
Y por último, si la condición en la que comparamos si el número aleatorio que se generó al inicio de la función randomAttack nos da como resultado true quiere decir que el número aleatorio se repite dentro del array de ataques enemyAttacks y se repetiría el ataque, asi que no se realiza el .push sino que se llama nuevamente a la funcion para que empiece de nuevo y logre encontrar un número que no se repita
else {
chooseEnemyAttack()
}
}
Intenté explicar lo mejor que pude, espero que les sirva de ayuda!
y se supone que esto es programación básica, pero es muy interesante, por que hace que uno piense en las soluciones, aparte de que si uno pone atención hay otras cosas que se le puede agregar al codigo para que valla quedando mas pulido
Sinceramente a este punto requiere bastante detenimiento entender que esta pasando, pero me emociona ver que el código funciona y todas las cosas que son posibles realizar.
Super F!
Se rompio mi codigo JS
Selecciono los ataques pero ninguno se registra y solo se queda alli el juego
Profe Diego ayudeeee
Así hice para que me seleccione los ataques del enemigo, le pase la variable ‘mascotaAleatorio’, la cual ya tenía el valor del mokepon seleccionado por el enemigo, y luego creo la función para que le agregue los ataques al arreglo ataqueEnemigo.
function ataqueAleatorioEnemigo(mascotaAleatorio) {
let ataques=mokepones[mascotaAleatorio].ataques
ataqueAleatorio = ataques[aleatorio(ataques.length-1)].nombre.toUpperCase()
ataqueEnemigo.push(ataqueAleatorio)
console.log(ataqueEnemigo)
}
ni a mi novia le presto tanta atención como a estas clases de la clase 50 hasta aquí 🤣🤣🤣🤣
Buenas a todos! Duré 2 días, pero finalmente logre hacer que el ataque del enemigo sea fiel a las normas del juego! lo pensé de muchas maneras, pero un poco de lógica y la función .includes() me terminaron bastando!
Declaré un array en global (arrayVerificacion) para cargar los números aleatorios ahí, para luego preguntar con el if y la funcion includes si el numero aleatorio se encuentra repetido en el arrayVerificacion, si no se encontraba, entonces que cargue el numero en el array del ataque del enemigo.
El segundo if es para que a medida de que el array del jugador guarde sus ataques, el array del enemigo vaya acorde a elegir y guardar sus ataques a la par, hasta llegar a 5.length los 2. Espero haberlos ayudado!!
function ataqAlEnemigo(){
let ataqueAleatorioEn = aleatorio(0, ataqMokeponEnemigo.length -1)
if(!arrayVerificacion.includes(ataqueAleatorioEn)){
ataqEnemigo.push(ataqMokeponEnemigo[ataqueAleatorioEn].nombre)
}
arrayVerificacion.push(ataqueAleatorioEn)
// console.log(ataqEnemigo)
// console.log(ataqueAleatorioEn)
if (ataqEnemigo.length === ataqJugador.length) {
iniciarPelea()
} else {
ataqAlEnemigo()
}
}
Me demoré un chingo de tiempo para darme cuenta de que habia tipeado mal, y era con mayùscula. Les dejo esta herramienta donde pueden comparar el código suyo con el del profe.
https://pinetools.com/es/diff-comparar-archivos
Siento que hay un error en la interpretación del juego, ya que dependiendo del personaje, este puede tener más ataques de fuego o más de agua o más de tierra. Con la solución propuesta por Diego, el arrays que se crea con los ataques del enemigo no se tiene en cuenta que personaje es. Les comparto mi solución:
function selectWarriorEnemy(){
let ramdonEnemy = random(0, warriors.length - 1)
spanWarriorEnemyName.innerHTML = warriors[ramdonEnemy].name
enemyAttacks = warriors[ramdonEnemy].attacks
ramdomEnemyAttack(enemyAttacks)
}
function ramdomEnemyAttack(enemyAttacks) {
for (var i = enemyAttacks.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = enemyAttacks[i];
enemyAttacks[i] = enemyAttacks[j];
enemyAttacks[j] = temp;
}
console.log(enemyAttacks)
}
Me cuentan sus opiniones de esta sugerencia de mejora. Un abrazo !!!
En cuanto el profesor dijo que íbamos a cambiar la lógica del juego pensé que eso era un error 👎🏻⛔️y una mala práctica🙅🏼♀️🚫, que en un buen proyecto lo adecuado sería que la ruta estuviera bien planteada desde el principio y que no fuera necesario cambiarla a mitad. Una cosa es cambiar la forma de los botones y otra cambiar la lógica.
También me venía fatal porque yo tengo variaciones y adaptarme a los cambios me supone un quebradero fuerte de cabeza.
PERO entonces me vino la iluminación y me di cuenta de que yo no estoy en ningún proyecto real, que estoy aprendiendo y que perderle el miedo a tener que cambiar la lógica a mitad es literalmente uno de los aprendizajes más valiosos. Molesto en un proyecto real, valiososo en nuestro parque de juegos.
Así que les comparto mi momento de iluminación por si les sirve porque también se habían desubicado y pensaban “dios mío a este paso la startup se nos va al guano en dos semanas”
Buenas! desde la clase anterior me esta costando entender. Desde la clase 47 hasta la 55 me hice un resumen y fui escribiendo los codigos con notas y distintos colores para poder identificar cada variable y/o funcion. importante para mi visualmente escribi todo en cada hoja solo en una carilla. Ustedes tienen otro metodo?
Hasta el momento, con cada clase voy observando como existen muchas maneras de hacer las cosas. Cada vez se pone más interesante.!
note que el programa que hizo el profe era muy genérico así que la solución que hice para hacerlo de pendiendo de la mascota del enemigo fu esta
function ataqueAleatoriEnemigo()
{
let ataqueAleatorio = aleatorio(0,ataqueEnemigo.length - 1)
ataqueEnemigo.push(mokepones[enemigo].ataques[ataque
Aleatorio].nombre)
console.log(ataqueEnemigo)
combate()
}
donde enemigo es el numero aleatorio que genera en la función que selecciona la mascota del enemigo y la volví variable global para usarla en esta función
3 horas me demore en completar el reto, y añadí los ataque en los resultados para poder corroborar que si son las comparaciones correctas
Optimize un poco el código en la función de ataqueAleatorioEnemigo, en vez de usar una secuencia if guarde el mokepon del enemigo en una varibale y cambie todo ese codigo por el siguiente
Pero entonces lo del ataque aleatorio cuando dijo que si llegan mas ataques los guarda, pero aquí estamos con 5
entonces no veo la optimización del if porque manualmente digito los números 0 a 5. Pero bueno esperar las otras clases para ver en que termina 😅
function ataqueAleatorioEnemigo() {
let ataqueAleatorio = aleatorio(0, ataquesMokeponEnemigo.length - 1);
if (ataqueAleatorio == 0 || ataqueAleatorio == 1) {
ataqueEnemigo.push('FUEGO');
} else if (ataqueAleatorio == 3 || ataqueAleatorio == 4) {
ataqueEnemigo.push('AGUA');
} else {
ataqueEnemigo.push('TIERRA');
}
console.log(ataqueEnemigo);
combate();
}
Pensé que yo era el único perdido acá, pero bueno veo que varios somos primiparos adelantando conocimientos para luego de a poco comprender.
Casi se me rompe el código de tantos cambio, casi no la cuento xd🤯
Hola a todos. Si al momento de ejecutar el código les sale en la consola que su elección fue solo [TIERRA, TIERRA, TIERRA], les recomiendo poner un console.log(e) debajo del boton.addEventListener(“click”, (e) => { para así ver en la consola cómo está almacenado el emoji del botón que seleccionaron y lo copien tal y como está en el navegador con todo y espacios en su código para que la condición pueda ser True y pueda variar dependiendo del botón elegido.
las probabilidades de ataque enemigo son las siguientes:
fuego: 40%
agua: 40%
tierra: 20%
Hola, como muchos han comentado esta solución no considera cual es la mascota del enemigo. Comparto mi solución que creo más sencilla y es usando una función que se llama splice(), la cual va recortando los ataques del mokepon, por lo tanto, no repetiremos el ataque seleccionado. Saludos y espero que les ayude a los que no han entendido.
<code>
function ataqueAleatorioEnemigo(){
let ataqueAleatorio = aleatorio(0,ataquesMokeponEnemigo.length-1)
ataqueEnemigo.push(ataquesMokeponEnemigo[ataqueAleatorio].nombre)
ataquesMokeponEnemigo.splice(ataqueAleatorio,1)
console.log(ataqueEnemigo)
combate()
}
function secuenciaAtaqueEnemigo() {
let ataqueAleatorio = aleatorio(0, ataquesPersonajeEnemigo.length - 1)
if (ataquesPersonajeEnemigo[ataqueAleatorio].nombre === "🪨") {
ataqueEnemigo.push("Rock")
} else if(ataquesPersonajeEnemigo[ataqueAleatorio].nombre === "✂️") {
ataqueEnemigo.push("Scissors")
} else {
ataqueEnemigo.push("Paper")
}
console.log(ataqueEnemigo)
ataquesPersonajeEnemigo.splice(ataqueAleatorio, 1)
}
Dejo por aqui mi avance en el curso de programacion basica, tome un camino muy diferente al que hicieron.
Mis mokepones tienen 120 puntos de vida y cada ataque tiene un daño base, segun el tipo de mokepon y el tipo de ataque, del enemigo y del jugador, hace un calculo de aumento o decrecimiento del daño, tambien agregue una funcion de curacion limitada a 3 usos. Me gustaria que le echaran un ojo y me dieran su opinion.
Este es el github
y por aca les dejo el juego en githubpages
Yo lo que hice para que tomara en cuenta la mascota del enemigo es:
1 crear un objeto mascotaEnemigo
donde se guarda la mascota aleatoria del enemigo.
2 con la función
numeroAleatorio(0, mascotaEnemigo.ataques.length)
generar un número aleatorio para elegir un ataque aleatorio de los que tiene la mascota y guardalo en una variable auxiliar “ataque”.
3 guardar el ataque del enemigo en la variable “ataqueEnemigo” de la siguiente forma
ataqueEnemigo = mascotaEnemigo.ataques[ataque]
4 borrar del array “mascotaEnemigo.ataques” el ataque ya usado
mascotaEnemigo.ataques.splice(ataque, 1)
Les dejo la documentación que encontré sobre arrays en JS donde encontré este método, hay otros métodos para borrar elementos de un array pero este es el que mas se ajusto a lo que necesitaba Docuemtacion Arrays
Y aquí sobre el método splice()
Y listo, de esa forma el enemigo selecciona ataques según su personaje y a medida que ataca no puede volver a usar esos mismos ataques.
Al igual que muchos aquí, también me parece que no usar los ataques que ya están establecidos en el arreglo de la clase (class) de los mokepones en mi caso son armas, pues no es lo lógico, así que mi solución fue crear un nuevo arreglo y a este arreglo enviar la copia de lo ya creado luego desordenar el arreglo para que los ataques no sean siempre los mismos, la línea de código que use fue la siguiente tuArreglo.sort(function(){return Math.random() - 0.5 });, el resto fue comparar las posiciones de los arreglos, modificar los mensajes y listo.
He realizado algunas variantes al código, para que use las opciones de ataque del mokepon que escoge la computador.
También le agregé una nueva llave al arreglo de los ataques del mokepon, para que contenga la descripción del ataque
let opponentMokepon
function sequenceAttacks(){
let buttonsAttacks=document.querySelectorAll('.button-attack')
buttonsAttacks.forEach((buttonAttack) => {
buttonAttack.addEventListener('click', (e) => {
attacksplayer.push(buttonAttack.value)
buttonAttack.style.background='#001D6E'
console.log(attacksplayer)
opponentRandomAttack()
})
})
}
function chooseOpponentMokepon(){
let mokeponRandomnumber = randomnumber(0,mokepons.length-1)
opponentMokepon=mokepons[mokeponRandomnumber]
spanMokeponOpponent.innerHTML = opponentMokepon.name
imgMokeponOpponent.alt=opponentMokepon.name
imgMokeponOpponent.src=opponentMokepon.image
sequenceAttacks()
}
function opponentRandomAttack(){
let attackindex=randomnumber(1,opponentMokepon.attacks.length-1)
attacksopponent.push(opponentMokepon.attacks[attackindex].desc)
battle()
}
La solución que encontré (después de horas xd) al problema mencionado en los comentarios fue en la función donde se selecciona los ataques aleatorios, ordenar aleatoriamente los ataques del personaje del enemigo y luego ir agregándolos al array de ataques seleccionados y al mismo tiempo eliminándolos del array de los ataques del personaje, para que no se repitan, por eso se selecciona el primer ataque del array e inmediatamente se elimina para que a la próxima vez que se seleccione un ataque se tenga que elegir otro y nunca se elija el mismo de antes :
function seleccionarAtaqueEnemigo(){
ataquesMokeponEnemigo.sort(()=>Math.random()-0.5)
ataqueSeleccionadoEnemigo.push(ataquesMokeponEnemigo[0].nombre)
ataquesMokeponEnemigo.shift()
console.log(ataqueSeleccionadoEnemigo)
combate()
Se me hace un poco complicado seguir a este profesor. Quiero terminar los videos pero esta ha sido la seccion que menos he aprendido. Quizas conecto mejor con otro metodo de explicacion porque en esta seccion ando en el limbo
TENGO buen nivel en javascript pero estas clases se vuelven cada vez muy difícil de entender por la falta de explicación.!!!
Gracias al aporte de Paula Inés Cudicio me inspiré a realizar esta solución al problema. Para que el enemigo elija los ataques de acuerdo a su mascota
Blablabla, tengo problemas para seguir comentando 😦 la verdad es que no se si sea un bug pero estoy intentando hacer aportes pero me sale un mensaje de error abajo de la caja de texto de platzi y no me deja postear…
3 horas me demore en completar el reto, y añadí los ataque en los resultados para poder corroborar que si son las comparaciones correctas
ayen por favor mi codigo no funciona y ya ise todo lo que se tenia que hacer
Veo que se aun se repite mucho código, además cualquier mascota enemiga tendrá las mismas probabilidades de ataque sin tener en cuenta que unas puede ser mas probable que usen fuego, agua o tierra dependiendo de su tipo.
mi solución a esto es:
function ataqueEnemigoAleatorio(){
let ataqueEnemigo = mascotaEnemigo.ataques
return ataquesEnemigo[aleatorio(1,ataquesEnemigo.length)-1].id
}
ataquesEnemigo.push(ataqueEnemigoAleatorio())
y luego simplemente le agrego este resultado con el método push a la variable global ataquesEnemigo
clase 57. functionataqueAleatrioEnemigo (), se tiene (0 ó 1) fuego; (3 ó 4 ) agua; else (2)para tierra; considero no acertado por probabilidad de ocurrencia de ataques aleatorios son diferentes.
Gracias por la espectacularmente complicada clase.
Yo no le entiendo nada 😦
Alguien que pueda ayudarme por favor este ha sido el video que menos he podido entender nisiquiera bajando el mismo codigo del profesor le encuentro la logica
Les comparto mi código:
//Ataque Aleatorio del Enemigo
ataque_enemigo = personaje_enemigo.attacks[numeroRandom(0, personaje_enemigo.attacks.length -1)].nombre;
De esta manera hacemos que la elección de ataque del CPU enemigo sea dinámico.
A veces el codigo no me funciona pero si agarro y copio el codigo que esta en los recursos de la clase , magicamente si funciona , muy raro
Yo con POO cree Attacks y le doy un array de debilidades
class Attacks {
constructor(public attacks: Attack[]) {}
create(attack: Attack) {
this.attacks.push(attack);
}
getbyName(name: TypeAtacks): Attack {
return this.attacks.find((attack) => attack.type === name) as Attack;
}
public get all(): Attack[] {
return this.attacks;
}
}
y cree una funcion llamada result en la que busco la debilidad del usaurio y busco si alguna debilidad es igual al ataque del enemigo
const result = () => {
const weakUser = attacks.getbyName(ataqueJugador).weak;
const winPC = weakUser.some((attack) => {
return attack === ataqueEnemigo;
});
++turno;
if (!winPC && ataqueJugador !== ataqueEnemigo) {
changeLife('pcPetLife');
return 'ganaste';
} else if (ataqueJugador === ataqueEnemigo) {
return 'empate';
} else {
changeLife('yourPetLife');
return 'perdiste';
}
};
Símbolo de O: ||
me rompió el desactivar los botones de ataques pero lo resolvi de esta forma
<code>
function desactivarAtaques() {
botonReiniciar.style.display = "block"
botones.forEach((boton) => {
boton.disabled = true
})
}
anteriormente lo tenia asi :
<code>
function desactivarAtaques() {
botonReiniciar.style.display = "block"
botonFuego.disabled = true
botonAgua.disabled = true
botonPlanta.disabled = true
}
A estas alturas el nivel del curso se ha puesto en mi opinión cuesta arriba 😦, estaba entendiendo paso a paso bien y como que en las últimas 5 o 6 clases mi mente desconecta o no comprendo la “lógica” entiendo que todo se hace de forma dinámica porque luego pueden existir mil personajes y mil ataques y no vas a ir uno por uno indicando cada vez pero como después del día trabajando y luego cenar y ponerme a estudiar a este nivel me cuesta mucho.
Espero poder ir comprendiendo más no quiero rendirme
!!HOLA estudiantes de platzi !!! aqui les dejo un consejo de forEach es un poco largo pero util lean detenidamente y hasta el final incluso las lineas de codigo ya que son la clave para
entener forEach.
recuerdan en clases pasadas y en esta clase hemos usado forEach pueda que algunos sigan con dudas, así que lo explicare de la mejor manera :
pueden interpretar
ataques.forEach((ataque) =>{ <button id="${ataque.id}" class="ataques BAtaque">${ataque.nombre} </button>
` })
como una funcion :
ataques.forEach(function (ataque){
<button id="${ataque.id}" class="ataques BAtaque">${ataque.nombre} </button>
`
})
y lo que dice es : que forEach pasara por cada una de las variable que estan dentro del array ataques y por cada iteracion se ejecutara la “funcion ataque”, los elementos que estan dentro del array ataques son encerrados en la funcion ataque y a la vez que tambien se ejecuta el codigo que pusimos adentro de la funcion que seria el siguiente :
ataquesMokepon = `
<button id="${ataque.id}" class="ataques BAtaque">${ataque.nombre} </button>
`
entonces dentro de la variable ataquesMokepon estariamos guardando la estructura del boton que necesitamos y pueda que aqui es donde se confundieron y la analogia de la funcion nos ayudara a entender esto dijimos que ataque seria una funcion que guardaria cada linea de codigo independiente dentro de el si recordamos ataques tiene :
{nombre: '🔥', id: 'boton-fuego'}
entonces eso se guardaria dentro de la funcion ataque y ya podemos acceder desde la funcion y buscar el id que tiene guardado y tambien a su nombre como hicimos en :
<button id="${ataque.id}" class="ataques BAtaque">${ataque.nombre} </button>
`
ya que tenemos guardado el nombre y el id en la funcion podemos usarlas accediendo desde el, ya que estan guardadas dentro de la funcion que se ejecutara por cada iteracion.
Es increible como una simple letra mal puesta te complica la vida , esto es como jugar a ser detective
Solo como pregunta general, no es mejor dividir las variables en otro archivo, y las funciones en otro para que sea mas facil de acceder a ellos?
Aquí veo varios comentarios de l@s compañer@s que son principiantes y que en este punto ya están un poco perdidos, sin embargo me salen con terminologías expertas y ejemplos super avanzados y soluciones extraordinarias. A mi a las justas se me a quedado el nombre del juego 😭
Yo los ataques de la maquina los nombres del ataque no lo que me lo tome directamte del arreglo de los ataques de la mascota del pc
let ataquecontrincante=[]
function ata_contrincante(){let eleccionataquecontrincante=aleatorio(0,ataquescontrincante.length-1)
console.log(eleccionataquecontrincante)
ataquecontrincante.push(ataquescontrincante[eleccionataquecontrincante].nombre)
console.log(ataquecontrincante)
Hola el curso me ha parecido super bueno, pero a mi opinion personal no me parece que se cambie mucho la logica del juego, porque teniamos desde el inicio una logica y entonces han cambiado muchas cosas y se que quizas sea asi en la realidad de un proyecto real como tal pero eso hace que se pierdan muchas cosas como tiempo, y quizas hasta algunos estilos y demas cosas, pero para eso estamos nosotros para modificar y llevar nuestro propio proyecto a donde nosotros mismo queramos.
Me parece muy valioso que durante el curso aparezca errores y se solucionen, siento que es un poco el día a día en programación y es fundamental entender estos errores.
Recuerden que en la partde de recursos aparece el GitHub donde encuntran las líneas de código. A veces si algo no te funciona es bueno revisar y comprar línea por línea 😃
La forma en que yo hice que mi código creara 5 ataques diferentes según los ataques que tiene el mokepon enemigo fue crear una matriz de números, la cual guardara números aleatorios y comparara los existentes con el que se va a ingresar para saber si alguno es repetido, en caso de que se repita el numero creara otro y así hasta tener los 5 aleatorios
let numeros = []
var j = 0;
while(j < 5)
{
numero = aleatorio(0, ataquesMokeponEnemigo.length - 1)
var existe = false
for(var i = 0; i < numeros.length; i++)
{
if(numeros[i] == numero)
{
existe = true;
break;
}
}
if(existe == false)
{
numeros.push(numero)
j++
}
}
luego de esto recorro la matriz de numeros para hacer el push del respectivo ataque de la mascota que encaja con el numero aleatorio en su posicion
for(var i = 0; i<numeros.length; i++){
tipoAtaqueEnemigo.push(mokepones[mascotaAleatoria].ataques[numeros[i]].nombre2)
}
no se si me hice entender, pero si tienen alguna pregunta con gusto les respondo
Es interesante como se usa el metodo de los ataques de los mokepones similar al del enemigo. Aunque un falta complementar lo que dejo el profe. Se nota que esta parte es un poco tediosa, pero entretenida. A seguir aprendiendo.
Si tenemos una función que no esta mandada a llamar en ninguna otra función la función que no esta llamada no hará nada (como si no hubiera nada)
¿Quieres ver más aportes, preguntas y respuestas de la comunidad?