106

Guía desde cero: tu propio juego de Rick and Morty con Vue.js

224260Puntos

hace 3 años

¿Así que ya has avanzado mucho en tu camino ninja como Frontend Developer? ¡Felicidades!, pero es hora de hacer algo con esas increíbles habilidades que tienes 👀… ¡Juguemos un poco con Vue!

Espera… ¿Vue? ¡Pero yo no sé nada de Vue!

¡No te preocupes! Esto también es para ti, a lo largo de este blogpost te guiaré paso a paso para que podamos desarrollar este proyecto con Vue desde 0, y quién sabe, a lo mejor te animas a aprenderlo 😉.

Nuestro increíble proyecto

¡Hagamos un juego! Nuestro proyecto será un juego que interactúa con la API de Rick & Morty. Este nos mostrará una tarjetita misteriosa, y debajo de ella otras 3 tarjetitas, cada una con un personaje de la serie; nosotros tendremos que adivinar cuál de ellas eligió el juego. ¿Tienes ganas de empezar? ¡Vamos!

game-ended

Preparándonos para empezar

Para trabajar como todos unos profesionales estaremos haciendo uso de la terminal para facilitarnos algunos procesos. En mi caso trabajaré desde Linux Ubuntu 20.04, pero tú puedes trabajar desde Windows o macOS, solo necesitas tener una terminal basada en UNIX.

Para el caso de macOS, su terminal es más que suficiente, por lo que con ella podrás trabajar sin problemas 💪. Para el caso de Windows, te sugiero trabajar con WSL, puedes aprender a cómo instalarlo en el Curso de Prework: Configuración de Entorno de Desarrollo en Windows 😉.

También puedes aprender más a fondo algunos de los comandos y trucos que usaremos en este blogpost en el Curso de Introducción a la Terminal y Línea de Comandos 👈👀.

Lo primero que haremos será crear la carpeta de nuestro proyecto y movernos a ella, puedes crearla y nombrarla a como prefieras:

mkdir rick-morty-game && cd rick-morty-game

Y como todo profesional, antes de escribir código, crearemos nuestro repositorio de git (te recomiendo empezar a trabajar con la rama main):

git init
creating-repository.png

Trabajaremos este proyecto con Vue 3, y lo haremos por medio del CLI (sí, los profesionales trabajamos desde el CLI 😈). Para ello, vamos al sitio oficial de Vue CLI, estando ahí veremos algunos cuantos avisos sobre la actualización del Vue CLI. Lo más importante a considerar aquí es que necesitamos una versión de Node.js superior a la 8.9, aunque se recomienda la versión 10. Puedes revisar tu versión con el siguiente comando:

node--version

Si tienes una versión antigua es hora de actualizarla 😉.

También, veremos el comando que nos permitirá instalar Vue CLI usando NPM (o yarn como alternativa).

Vue-CLI-page.png

Simplemente copia el comando y ponlo en tu terminal para que se instale. En mi caso lo hago anteponiendo la palabra sudo, ya que al ser una instalación global, esta requiere que NPM pueda modificar algunos directorios de administrador:

Vue-CLI-installation.png

¡Genial! Ahora sí estamos listos para empezar. Para crear un nuevo proyecto de Vue debemos usar el comando vue create <folder-name>, puedes crear el proyecto dentro de una nueva carpeta, o puedes usar la carpeta actual poniendo un punto en lugar del nombre de la carpeta, en este caso lo crearemos dentro de la carpeta que ya tenemos creada:

vue create .

Esto nos preguntará si queremos usar la carpeta actual para crear nuestro proyecto, por defecto viene seleccionada la opción “Y”, damos enter para confirmar:

vue-create-confirm.png

A continuación nos preguntará qué preset queremos usar. Vue te permite crear tus propios presets, pero como recién instalamos el CLI seleccionaremos el preset que dice Default (Vue 3 Preview) ([Vue 3] babel, eslint) moviendo el selector con las flechas del teclado:

Vue-preset.png

Esto empezará a generar toda nuestra estructura de carpetas y archivos ya configurados para empezar a trabajar con Vue 3 (sí, así de cómodo es el CLI 😉). Una vez terminado te dirá que todo fue creado satisfactoriamente dentro de nuestra carpeta y nos sugerirá un comando para ver nuestro proyecto de Vue: npm run serve ¡Ejecutémoslo!

Vue Running.png

¡Tenemos nuestra aplicación corriendo con Vue! Regresemos a la terminal, hay algunas cuantas cosas interesantes que quiero mostrarte:

Vue-terminal-running.png

Es importante aprender a leer lo que nos dice la terminal, en este caso nos dice que la aplicación está corriendo y nos muestra dos URL:

  • Local: Esta es la URL con la que podemos acceder a nivel local, es decir, desde nuestra propia computadora.
  • Network: Esta es la URL con la que podremos acceder a nuestra aplicación de Vue desde otros dispositivos conectados a la misma red.

También te dice que estás corriendo en modo de desarrollo, para compilar el proyecto en modo producción (optimizado) puedes ejecutar el comando npm run build 😉.

¡Creando nuestro juego!

¡Bien! Ya tenemos un proyecto con Vue creado, hora de programar 🤠. Nuestro componente principal está ubicado en src/App.vue, este componente contiene el HTML, JavaScript y CSS solo de ese componente. Esta es la estructura básica de cada componente en Vue:

<template><div><p>El HTML del componente debe estar dentro de una etiqueta template, y esta solo debe tener una etiqueta hija.</p><p>Si pones más etiquetas hijas de template, en versiones anteriores a Vue 3 te dará un error 👀.</p></div></template><script>// Podemos importar componentes para usarlosimport ComponentName from"./components/ComponentName"// Exportamos la información por medio de un objeto JSON de ESTE componenteexportdefault {

    // El nombre de nuestro componente
    name: "",

    // Una lista en JSON de los componentes que este componente utiliza
    components: {
        ComponentName
    },

    // Podemos poner aún más funciones!

}

</script><style>/* Aquí podemos poner reglas CSS, Sass, Less, etc. La etiqueta puede contener el atributo scoped para que los estilos se apliquen solo a este componente. */body {
        background: green;
    }
</style>

Como puedes ver, un componente de Vue contiene prácticamente a nuestros 3 lenguajes principales de desarrollo web. No es obligatorio poner los 3, pero al menos uno debe estar presente.

¡Creemos un componente!

La estructura de nuestro juego es muy sencilla, ya que prácticamente solo tendremos un componente Card. Este componente será cada una de nuestras tarjetitas, para ello, dentro de nuestra carpeta src/components crearemos un componente llamado Card.vue y dentro pondremos el siguiente código:

<template><divclass="card"><divclass="front"><h2>Rick Sánchez</h2><pictureclass="image-container"><imgsrc="https://i.pinimg.com/originals/ac/51/52/ac5152b9f7f50781b2b01e35463fc4e6.jpg"alt="Rick Sánchez"></picture></div></div></template>

Ahora debemos exportar la información de este componente, para ello agregamos una etiqueta <script> debajo de nuestro <template>:

<script>exportdefault {
    name: "Card"
}

</script>

Es algo muy sencillo, solo tendremos el nombre del personaje y su imagen. No profundizaremos en los estilos, pero puedes encontrarlos aquí, solo recuerda que debes ponerlos en una etiqueta <style scoped></style> debajo de nuestro <script>.

¡Muy bien! Ya que tenemos el componente listo (por ahora) nos toca importar este componente dentro de nuestro componente principal (tú recuerdas cuál es nuestro componente principal 👀). Borramos todo lo que tiene dicho componente, ya que no lo necesitaremos, y ponemos lo siguiente:

<template><mainclass="dashboard"><divclass="selected-card"><Card /></div><divclass="options"><Card /><Card /><Card /></div></main></template>

Básicamente es el tablero, arriba tiene la tarjeta que el juego seleccionará y abajo nuestras 3 posibles opciones. También debemos exportar la información de nuestro componente principal, pero en este caso estamos usando un componente externo, así que también debemos importarlo, así debería quedar nuestro <script>:

<script>import Card from"./components/Card";

    exportdefault {

        name: "App",

        components: {
            Card
        }

    }

</script>

Los estilos de este componente los puedes encontrar aquí 👈👀. Con esto listo, el juego debería verse algo así:

Vue-game-prev.png

¡¿Qué?! ¿Ya tan rápido tenemos todo eso?..

¡Sí! Es la magia de usar componentes y los estilos hacen el resto 😉. Lo genial de esto es que si inspeccionas una tarjetita y le pones la clase closed verás cómo esta tarjetita se cierra.

Closing-card

Conectándonos a la API de Rick & Morty

Muy bien, ya creamos nuestro primer componente, ahora falta conectarnos a la API para traernos a los personajes, para ello crearemos un archivo que haga ese trabajo por nosotros. Dentro de nuestra carpeta src crearemos una carpeta llamada utils, y dentro de la misma crearemos un archivo llamado api.js, dentro pondremos el siguiente código:

const APIUrl = "https://rickandmortyapi.com/api/character";

// Obtiene un número aleatoriofunctionrandomNumber(min, max) {
    returnMath.floor(Math.random() * (max - min) ) + min;
}

// Hace la solicitud a la API de Rick & MortyasyncfunctionfetchCharacter(url) {   
    returnawait fetch(url)
                .then(response => response.json())
                .then(data => data);
}

// Obtiene 3 personajes aleatoriamente consultando a la APIasyncfunctiongetCharacters() {

    return [
        await fetchCharacter(`${APIUrl}/${randomNumber(1, 669)}`),
        await fetchCharacter(`${APIUrl}/${randomNumber(1, 669)}`),
        await fetchCharacter(`${APIUrl}/${randomNumber(1, 669)}`),
    ];

}

export { getCharacters, randomNumber };

Es muy sencillo, tenemos tres funciones:

  1. randomNumber es una función que nos devolverá un número aleatorio entre un mínimo y un máximo.
  2. fetchCharacter es una función que hará la solicitud del personaje hacia la API de Rick & Morty y nos devolverá un JSON con la información de dicho personaje.
  3. getCharacters es una función que nos devolverá un array con 3 posiciones, cada una de ellas contendrá a un personaje que nos devuelva la API.

También guardamos en una constante el endpoint de la API que se encarga de proporcionarnos a los personajes. Dicho endpoint puede proveernos de hasta 699 personajes, por lo que mediante nuestra función randomNumber() elegimos uno al azar.

Quiero que notes cómo la función fetchCharacter() y getCharacters() son asíncronas, esto es porque la solicitud la hacemos mediante la función fetch(), que también es asíncrona, es por ello que nos apoyamos de las palabras async y await 👀.

Al final exportamos a las funciones getCharacters() y randomNumber(), ya que usaremos ambas más adelante, pero estas funciones hay que importarlas en alguna parte. Las importaremos dentro de nuestro App.vue, esto porque es el componente principal el que contiene a todas nuestras tarjetitas, así que es este componente quien tiene que decidir cuál tarjeta elegir. En el apartado de <script> de dicho componente, antes de importar nuestro componente Card, importaremos nuestras funciones del archivo api.js:

import { getCharacters, randomNumber } from"./utils/api";

¡Y ya estamos listos para usarlas! ¿Dónde las usaremos? Nos apoyaremos de los hooks de Vue, que básicamente son diferentes momentos que tiene Vue para renderizar nuestra aplicación, en especial del hook beforeCreate(). ¿Recuerdas que exportamos la información de nuestro componente en formato JSON? Bien, ahí mismo, debajo de components podemos añadir este hook, pero recuerda que usaremos una función asíncrona, así que añadiremos este hook con async:

components: {
    Card
},

async beforeCreate() {
    console.log(await getCharacters());
}

Si ponemos un console.log con nuestra función getCharacters() verás que la API ya nos está dando información de los personajes, y si recargas la página verás que es información aleatoria:

Rick-Morty-API-Response.png

Pasemos los datos de la API a nuestras tarjetas

¡Perfecto!, ya tenemos los datos de la API con los personajes que necesitamos de forma aleatoria, ahora solo falta que nuestro juego elija un personaje y muestre las opciones en pantalla. Para elegir a nuestro personaje lo haremos de manera aleatoria también, ¿recuerdas que la función getCharacters() nos devuelve un array de 3 posiciones? Bien, usando la función randomNumber() elegiremos al azar una de esas posiciones, lo que nos devolverá un personaje al azar:

asyncbeforeCreate() {
    
    const characters = await getCharacters();
    const chosenCharacter = characters[ randomNumber(0, 2) ];

}

Como ya sabrás elegimos un número entre 0 y 2, ya que solo tenemos 3 posiciones dentro de nuestro array 👀.

Para asignar cada personaje a cada tarjetita haremos uso de los bindings de Vue. Con Vue tenemos una función llamada data(), esta función debe retornar un objeto con cada una de las variables que usaremos en nuestro <template>. Crearemos esta función data() arriba de nuestra función beforeCreate():

data() {
    return {
        options: [],
        chosenCharacter: {}
    }
},

asyncbeforeCreate() {
    // Código que ya teníamos creado
}

Inicializamos ambas variables vacías, ya que serán rellenadas cuando nuestro beforeCreate haga la consulta de los personajes, y para hacer esto debemos modificar dicha función para asignar los resultados a nuestras variables, por lo que al final quedaría así:

asyncbeforeCreate() {
    
    const characters = await getCharacters();
    const chosenCharacter = characters[ randomNumber(0, 2) ];

    this.options = characters;
    this.chosenCharacter = chosenCharacter;

}

¡Ahora que tenemos nuestras variables listas podemos imprimirlas en nuestro <template>!

Para poder asignar los personajes a cada tarjeta necesitamos pasarle los datos del personaje a nuestro componente Card, ya que es este componente el que renderiza cada tarjetita, esto lo podemos hacer poniendo como atributo “dos puntos” y el nombre con el que queramos pasarle los datos. Por ejemplo, para pasarle los datos de nuestro personaje elegido al componente Card nuestro HTML debería quedar así:

<div class="selected-card">
    <Card:character="chosenCharacter":closed="true" /></div>

En este caso, le estamos pasando por medio de la propiedad character los datos de nuestro chosenCharacter (recuerda que este último es el personaje que nuestro juego eligió y que guardamos como variable para pasar al <template>). El valor se pone directamente dentro de las comillas, gracias a esos dos puntos que pusimos antes del nombre de nuestra propiedad Vue sabe que se trata de una variable en lugar de un string literal. También estamos pasando una propiedad llamada closed, esta propiedad nos dirá si la tarjeta debería renderizarse cerrada inicialmente o si debería estar abierta, como esta es la tarjeta que eligió el juego tiene que estar inicialmente cerrada.

Ahora solo nos queda recibir dichos atributos dentro de nuestro componente Card, y para ello, dentro de la información que estamos exportando, podemos añadir una propiedad llamada props quien será la que reciba dichos datos, por lo que podríamos añadirla debajo de su nombre. El export del componente Card quedaría así:

<script>exportdefault {
    
    name: "Card",

    props: ["character", "closed"]

}

</script>

¡Ahora podemos usar las variables character y closed dentro del HTML de nuestro componente Card! Recuerda que la variable character es un objeto JSON, es el JSON que nos devolvió la API, por lo que podemos imprimir dicha información dentro de nuestro <template> usando las dobles llaves {{ }}. El HTML de nuestro componente Card quedaría así:

<template><divclass="card":class="{ closed }"><divclass="front"><h2>{{ character.name }}</h2><pictureclass="image-container"><img:src="character.image":alt="character.name"></picture></div></div></template>

Antes de ver el resultado en pantalla te recomiendo comentar la sección “options” dentro del <template> de tu App.vue para evitar problemas con las otras cards.

Quiero que veas que aquí están pasando algunas cosas interesantes:

  1. Tenemos 2 atributos class en el div de card, pero una de ellas tiene dos puntos. Para Vue, si le pones dos puntos a una clase, este lo tomará como un objeto JSON de clases el cual deberá tener condiciones. La key del objeto JSON es la clase que quieres asignar, y el value de ese objeto JSON es la condición que quieres poner para saber si agregar o no dicha clase, si una condición se cumple, entonces Vue agrega esa clase.
    En este caso, la key (la clase que queremos agregar) es closed, pero la condición de esa clase está dada por una variable… ¡Que también se llama closed! Es esta variable que recibimos en nuestro props, y si recuerdas, es una variable booleana, por lo que la magia de ECMAScript 6+ nos permite acortar este JSON. Pero si quisiéramos hacerlo de la forma larga, debería quedar así:
<div class="card" :class="{ closed: closed }">
    💡 El primer closed es la clase que quiero poner, el segundo closed es la condición, queen este caso es un booleano que viene desde nuestro props.
</div>
  1. En el <h2> estamos pintando el nombre usando las {{ }}, pero en el <img> estamos pintando los datos usando la nomenclatura de “dos puntos”, esto es por lo que ya te expliqué hace unos párrafos ☝👀.

¡Nuestra tarjeta elegida ya tiene a su personaje! Ahora solo nos falta pintar las posibles opciones dentro de nuestro App.vue. Estas opciones son un array, recuerda que cuando asignamos las variables que pasarán a nuestro HTML, para la variable options asignamos el arreglo de personajes que nos devolvió la función getCharacters(). Para recorrer un array dentro de Vue usamos una directiva llamada v-for, por lo que el apartado de nuestras opciones debería quedar así:

<divclass="options">
    <Card v-for="option in options" :key="option.id" :character="option" :closed="false" />
</div>

Aquí sucedieron algunas cosas interesantes:

  1. Eliminamos 2 cards, ya que solo eran para ver nuestro maquetado.
  2. El v-for es prácticamente un for...of de JavaScript, es decir, recorremos cada personaje y por cada una de ellos lo gurdamos dentro de una variable option.
  3. Tenemos un atributo :key, este atributo lo necesita Vue para identificar a cada elemento del v-for, la key que le pasamos es el id del personaje que nos devuelve la API.
  4. Por último, recordemos que nuestro componente Card recibe un atributo llamado character, como estamos recorriendo el array de personajes le podemos pasar directamente todo el personaje, además, estamos mandando el atributo :closed como false porque queremos que estás tarjetas sí aparezcan abiertas inicialmente.

Hasta ahora nuestro juego ya debería estar casi terminado, por lo que si vamos al navegador deberíamos verlo así:

Vue-game-mostly-finished.png

Recuerda que aquí nuestro juego ya nos está cargando a las 3 posibles opciones y ya eligió a una de ellas, ahora nos toca programar la interacción con el usuario para que elija una tarjeta 😎.

Para hacer esto, simplemente debemos agregarle un evento click a nuestras tarjetas, en Vue podemos agregar eventos usando una arroba (@) seguido del nombre del evento directamente en nuestro componente. Sabiendo esto, a nuestro componente Card que tenemos dentro del div con la clase options le agregaremos el evento click, y cuando este evento suceda mandaremos a llamar a un método llamado validate() al cual le pasaremos como parámetro el id del personaje que seleccionamos, este método lo crearemos en un momento:

<Card 
    v-for="option in options":key="option.id":character="option":closed="false"@click="validate(option.id)"
/>

Para mejorar la legibilidad puse los atributos en forma de lista, ahora solo nos falta crear el método validate. Para crear este método, debajo de nuestra función beforeCreate() crearemos un nuevo objeto llamado methods, y dentro de ese objeto podemos crear cuantos métodos queramos, para este caso solo crearemos el método validate:

asyncbeforeCreate() {
    // Código que ya teníamos creado
},

methods: {

    validate(chosenCharacter) {

        // Aquí haremos la validación

    }

}

¡Ya solo nos falta hacer la validación y girar la tarjetita cuando el usuario acierte! Recordemos que tenemos una variable dentro de nuestra función data() que contiene el personaje que el juego eligió, y que por el parámetro de nuestro método validate recibimos el id del personaje al que el usuario le hizo click… ya sabes qué sigue ¿verdad? 👀:


validate(chosenCharacter) {

    if (chosenCharacter === this.chosenCharacter.id) {
        this.isClosed = false;
        alert("¡Lo has adivinado!");
    }
    else {
        alert("Personaje incorrecto, inténtalo de nuevo");
    }

}

Con esta pequeña validación podemos informarle al usuario si ha ganado o no, pero quiero que veas que puse this.isClosed = false;, esto es porque también necesitamos girar la tarjeta cuando el usuario adivine, para ello, dentro de nuestra función data() crearemos una nueva variable llamada isClosed que empezará por defecto en true, al final debería quedar así:

data() {
    return {
        options: [],
        chosenCharacter: {},
        isClosed: true
    }
},

Y en nuestro componente Card que está dentro del div con la clase selected-card simplemente cambiamos ese :closed="false" que teníamos hardcodeado por :closed="isClosed", de esta forma cuando el usuario acierte y el valor de isClosed cambie a true la tarjetita se abrirá:

<Card :character="chosenCharacter":closed="isClosed" />

¡Y listo! Con eso hemos terminado nuestro juego, como puedes ver solo agregamos una validación sencilla al final e hicimos que nuestra tarjetita se abra. Nuestro juego podría mejorar aún más, podríamos agregarle una opción para cargar nuevos personajes después de adivinar uno, ya tenemos la lógica para cargar el personaje, simplemente podríamos aislar esa lógica en un nuevo método, ¡o incluso podrías agregarle un score! ¿Te atreves a hacerlo? 👀.

Las posibilidades de mejorar este juego son infinitas, y Vue nos permite hacer todo esto de una forma muy fácil. A lo largo de este blogpost vimos muchas de las funcionalidades de Vue: componentes, comunicación entre componentes, two way data binding, consumo de API, eventos, hooks, métodos, etc. Pero la verdad es que Vue tiene todavía mucho más para dar, hay temas muy interesantes que complementan a esta librería y nos permite crear cosas aún más impresionantes como Vuex, Vue Router, Composition API o incluso JSX por si vienes de React, es por eso que Vue se autodenomina “El framework progresivo”.

Vue tiene mucho campo para explorar, es una librería muy cómoda y completa para trabajar además de que te permite lograr resultados poderosos. No olvides que puedes ver este proyecto funcionando en el siguiente enlace, y también puedes encontrar el repositorio de este proyecto en GitHub:

¡Genial! Has dado un paso más en tu camino ninja como Fronted Developer, pero ahora te toca a ti seguir aprendiendo. Si te gustaría aprender un poco más sobre este framework y profundizar más en él te invito a que tomes nuestra ruta de Frontend con Vue.js donde crearás proyectos todavía más increíbles 😉.

Y recuerda #NuncaParesDeAprender 😄.

Carlos
Carlos
RetaxMaster

224260Puntos

hace 3 años

Todas sus entradas
Escribe tu comentario
+ 2
Ordenar por:
5
36569Puntos

Lo logré!
Todavía no aprendo Vue ni algún framework o llibrería, pero estaba apunto de aprender alguno(terminé el curso de librerias y frameworks en la escuela de Desarrollo Web) y dudada sobre cual aprender primero, pero como sugirieron:

  • Vue
  • React
  • Angular.

Me gusto vue a primeras impresiones! 😄, no lo sentí dificil, muy buen tutorial!, me dio alguna idea inicial de lo que es Vue.
Será lo próximo que aprendere sin duda.

Dejo el repositorio nada más porque todavía no se hacer deploy de una aplicación de Vue:D: https://github.com/paolojoaquin/rick-morty-game
Si alguien me ayudara a hacer deploy se lo agradecería 😄.

3
224260Puntos
3 años

¡Hey, felicidades! Me alegro de que lo hayas conseguido y te haya gustado Vue 💚. Ya sabes por donde continuar, en la ruta de Vue de Platzi aprenderás a dominarlo muy bien, (y spoiler) en uno de los cursos vas a hacer un proyecto increíble 👀.

Para hacer deploy te recomiendo usar Netlify, no es difícil, simplemente tienes que enlazar tu repositorio de GitHub, te recomiendo tomar el Curso de Introducción al Despliegue de Aplicaciones para que te des una idea de cómo puedes hacer deploy de tus aplicaciones 👀

1
1765Puntos
3 años

Gran trabajo paolojoaquin

3
7787Puntos

No uso Vue.js pero personalmente me gusto tu enfoque!! A intentar algo nuevo.

2
304Puntos

Nada mal compañero, excelente contribución.

2
5425Puntos

Nada mal, al empezar a estudiar Vue este tutorial vale oro, anima, motiva a quien empieza, y mas aun sin conocer las VueBootstrap, Vuetifiy… para hacer componentes mas rapidos y bonitos

1

Lástima que React sea tan popular. Vue es lo máximo. Gracias por este post!

1

Me encanto este tutorial, me has convencido de ir ahora por Vue la verdad es que me parece increíble todo lo que se puede lograr con el.

1
22519Puntos

Bro se que porque es un tutorial es extenso pero opino que este es muy extenso

4
224260Puntos
3 años

No es largo, las imágenes y el código hacen que se vea largo, pero si realizas la práctica si te llevará algunos cuantos minutos de lectura 😉

9
212520Puntos
3 años

Vivan los tutoriales largos.

2
22519Puntos
3 años

Jejejee si lo bueno es que esta bien explicado y muy intuitivo como lo es vue esta bueno el tutorial bro eso si

1
14801Puntos

Genial, espero sacar un tiempo para poderlo hacer 😄

0
6363Puntos

¿alguna solucion para el problema que da en firefox la propiedad CSS backface-visibility?