Aprende a programar creando un Video juego

Héctor BlisS
FixterGeek
Published in
16 min readJul 26, 2018

Metas de aprendizaje

  • Entender que es un Lenguaje de programación.
  • Comprender que es Canvas.
  • Entender la estructura de videojuego HTML5.
  • Ser capaz de aplicar conceptos básicos de HTML.
  • Comprender la estructura básica de jugabilidad y cómo organizar tu videojuego.
  • Usar funciones de JavaScrip.
  • Comenzar a trabajar con Javascript con confianza.

Introducción

Si eres millenial (nacido entre 1980 y 2000) en algún momento de la niñez quisimos poder crear nuestros propios juegos de vídeo, de hecho, tal vez, muchos tenemos interez en la tecnología gracias a los videojuegos.
Es comun que aprendamos a programar creando paginas aburridas o a las que no les encontramos sentido, aprendemos con tutoriales repetitivos que siempre hablan de lo mismo, porqué no aprender a programar con algo que nos emociona desde niños y mejor aún con un lenguaje y herramientas que nos permite tener resultados visuales casi instantaneos.

Es por ello que el día de hoy vamos a crear un videojuego al estilo arcade que despertará a ese niño que encerraste hace muchos años dentro de ti.
¡Es hora de dejarlo jugar!

Lenguaje de Programación

Los lenguajes de Programación especifican una serie de instrucciones para que una computadora produzca diversas clases de datos. Los lenguajes de programación pueden usarse para crear programas que pongan en práctica algoritmos específicos que controlen el comportamiento físico y lógico de una computadora.

Existen 2 típos de lenguajes básicos:

Lenguaje compilado | Todo de una vez

Lenguaje interpretado | Linea por linea

Los lenguajes de programación son cosa sería pero a los desarrolladores nos encanta sacarlos de lo formal creando mascotitas =P

Github

Para este videojuego usaremos github para respaldar nuestro código, además de que usaremos esta misma herramienta para publicar nuestro juego y que todos nuestr@s amig@s ¡puedan jugarlo!

Github tiene una historia genial y utiliza una herramienta super poderosa (git) creada por el mismisimo Linus Torvalds (creador de linux) pero eso lo puedes leer en internet, por ahora solo te presentaré a la mascota de Github, saluda al poderoso Gatopulpo, y de paso crea tu cuenta en github ;) GitHub

Setup

Para comenzar a crear nuestro videojuego necesitamos tener un editor de código instalado en nuestro equipo de cómputo, para este ejercicio nos funciona perfectamente cualquiera de los siguientes:

Sublime Text 3

Visual Studio Code

Atom

También asegurate de tener instalado el navegador web Chrome el cual nos ayudará a que el resultado de nuestro videojuego se muestre correctamente. Descargalo aquí

Todo listo para empezar alv!

Los desarrolladores evitamos las largas introducciónes vamos directo al codigo ya ya ya!.
Para eso vamos a entrar a un sition web, que nos va a permitir probar el lenguaje de programación JavaScript sin necesidad de instalar nada en nuestro equipo, colocandolo directamente en el navegador. =D

así que entramos a Repl.it el cual es un interprete (ahora ya sabemos lo que es un interprete) ahi podremos aprender las partes básicas de JavaScript.

Intro a JavaScript

Variables

Las variables son basicamente contenedores de datos o información que nos van apermitir procesar, manipular y guardar los resultados de forma comoda y fluida para crear nuestros programas, las variables se declaran de la siguiente manera:

var name = "BlisS"
var date = 123989837493
var active = true
var occupation = "Educator"

Estructuras

Las estructuras de datos basicas en javascript son 2, arrays y objetos, vamos a explorar cada una:

  • Arrays o listas
var array = [1,2,3,4,5]
var lista = ["BlisS",true,34,name]
  • Objetos
var objeto = {
name: "BlisS",
date: 1225438696,
active: false,
occupation:
}
  • Mix
var objeto = {
name: "BlisS",
date: 1225438696,
active: false,
occupation: ["teacher", "educator", "hacker"]
}
var array = ["bliss", name, 78, {name:"Lupe",age:19}, "testing"]
  • Quick excersise
var object = {
name: 'Fake School',
classRooms:
[
{ teacher: ["BlisS"], students: ["Lupe"] },
{ teacher: ["Brendi"], students: ["Maria", "Jane"] }
]
}

copia esta estructura en repl.it e imprime en la consola (console.log) el nombre de Jane.

Comparaciones

Las comparaciones son estrategias para la toma de deciciones de un algoritmo o programa y por lo regular son en base a una condicional booleana, o lógica para esto se ocupa el keyword if el cual por lo regular va acompañado de el keyword else para decidir que camino se sigue dentro del programa:

if(name === "BlisS"){
console.log("Hola BlisS")
}else{
console.log("Hola desconocido")
}

Como podemos observar se ha ocupado === para una comparación exacta, esto es que es del mismo tipo de datoy con el mismo valor, podriamos usar == pero en javascript esto podria conincidir con algo así 2 == "2"
Existen diferentes tipos de comparadores que devuelven un valor booleano por ejemplo:

if(num1>num2){console.log("El "+num1 +" es mayor")}
else{console.log("El "+ num2 + "Es mayor")}
if(num1<num2){console.log("El "+num1 +" es menor")}
else{console.log("El "+ num2 + "Es menor")}
if(num1>=num2){console.log("El "+num1 +" es mayor o igual")}
else{console.log("El "+ num2 + "Es menor")}
if(num1<=num2){console.log("El "+num1 +" es menor o igual")}
else{console.log("El "+ num2 + "Es mayor")}
if(num1!==num2){console.log("El "+num1 +" es diferente")}
else{console.log("El "+ num2 + "es igual")}

Y también se pueden utilizar operadores logicos o compuertas para combinar estos comparadores:

if(num1 < num2 && num1 > num3){
console.log("el " + num3 + " es el menor de todos")
}

if(age >= 18 || hasAccess){
console.log("Pasale a beberss")
}

Cómo se puede observar, no es necesario comparar con === true, ya que de forma default es lo que un if busca.

Recordemos que podemos negar lo que un if busca (true) si negamos al principio de la comparación: if(!active) por ejemplo.

Loops

Es hora de pasar a las partes más interezantes del lenguaje y que en conjunto con las estructuras de datos nos permiten realizar tareas utiles para resolver problemas o crear soluciones.

Los ciclos o loops son literalmente repeticiones de un mismo código pero que va transformando los datos, estos ciclos pueden estar relacionados a una estructura de datos (como un array) o no.

Por ejemplo podemos crear un ciclo que imprima el incremento de un numero, para ello usaremos el primer ciclo llamado while

var number = 0;
while(number < 10){
console.log(number)
number++
}

Observa que debemos cambia el numero nosotros mismos dentro del ciclo, este código se repite hasta que la condicion ya no se cumple.

En el caso de usar un for no es necesario cambiar nosotros a mano el acumulador:

for(var number=0 ; number<10 ; number++ ){
console.log(i)
}

La sintaxis de un for tiene tres elementos principales estos son: for(valor inicial;limite;sumatoria) y como puedes ver no necesitamos hacer el aumento nosotros, esto es de forma automatica.

Existe otro metodo para crear un ciclo, pero este solo aplica para arrays, lo cual nos permite recorrer el contenido de una lista de forma más simple, la sintaxis puede parecer dificil, pero con el tiempo te familiarizarás a ella:

var array = [1,2,3,4,5,6,7,8,9]
array.forEach(function(number){
console.log(number)
})

Para entender completamente este metodo forEach hay que entender también qué es una función.

Funciones

Una funcion es un pedazito de código que se ejecuta cada que se le solicita. Es la forma más utilizada para dividir un problema en pequeños problemas más fáciles de resolver, las funciones se declaran con el keword function y tienen un par de piezas:

function sayMyName(name){
if(name === "Walter"){
console.log("Heisenberg")
}
}
sayMyName("Walter")

Observemos que aquí pasan varias cosas, de la linea 1 a la 5 se ha declarado una función con el keyword y se le asigno un nombre en este caso sayMyName con este nombre todo lo que se encuentre dentro de la funcion será reutilizable, la funcion está diseñada de tal forma que se debe entregar una variable llamada name a estas variables que la funcion espera se le conocen como argumentos, y por ultimo dentro de las llaves de la funcion se escribe justo lo que la funcion realiza. Por ultimo esta funcion se pone a trabajar gracias a que se le llama por su nombre y se le entrega el argumento necesario la linea 7 hace justamente esta función y a este se le llama invocación.

HTML5 & Canvas

Es hora de agregar una herramienta de HTML para poder usar javascript juntamente con graficos y así crear nuestro videojuego.

Canvas es la herramienta perfecta para poder llevar nuestras ideas gamer a la realidad, canvas es una etiqueta igual que cualquier otra de html, y que así mismo igual que otras se puede manipular via JavaScript, a esto se le conoce como manipulación del DOM.

Canvas tiene varios atributos muy especificos, entre ellos context, que en un momento usaremos, pero por ahora vamos a visualizar la etiqueta Canvas como lo que es, un lienzo.

canvas tag

Para utilizar laetiqueta canvas es necesario crear esta etiqueta dentro de nuestro código html, de la siguiente manera:

<html>
<head></head>
<body>
<h1>VideoGame</h1>
<canvas id="canvas" width="256" height="256">
</canvas>

</body>
</html>

Observa como la etiqueta tiene 3 atributos esenciales, un id, un ancho y un alto y gracias a esto podremos manipular nuestra etiqueta con javascript de la siguiente manera:

var canvas = document.getElementById('canvas')

Contexto

Ahora que tenemos el lienzo necesitamos una herramienta para pintar sobre él, Canvas es bastante avanzado al día de hoy y soporta diferentes contextos pero el día de hoy nos vamos a concentrar en uno de solo 2 dimensiones (2D) para crear nuestro videojuego, así que obtenemos este pincel con una variable.

var ctx = canvas.getContext('2d')

Tenemos todas las herramientas listas para comenzar a dibujar, ¡hagamoslo pues!

Rects

Vamos a empezar con la figura más básica; rectangulos, para dibujar un rectangulo se usa el metodo fillRect o strokeRect dependiendo de si queremos un rectangulo con relleno o uno con solo el contorno, de la siguiente manera:

ctx.fillStyle = "peru"
ctx.fillRect(0,0,50,50)

Un methodo es una funcion que vive dentro de un objeto, en este caso el objeto es ctx y al ser una función hoy hemos aprendido que puede recibir argumentos, o parametros así que le pasamos 4 cosas (numeros) el primero representa “x”, luego “y”, el ancho “width” y finalmente el alto “height”.

drawImage

Ya nos acercamos a las partes mas interezantes del uso de nuestro lienzo y pincel, y esque no solo podemos hacer cubos aburridos, también podemos dibujar imagenes desde un link en internet e incluso desde nuestra computadora, para esllo necesitamos usar el metodo de ctx llamado drawImage este metodo va a recibir 5 argumentos, los cuales son los siguientes por orden de aparición: “imagen”, “x”, “y”, “width” y “height” ¿Cómo se usa?

var link = "https://bit.ly/2v3FTX5"
var image = new Image()
image.src = link
ctx.drawImage(image, 0,0,50,50)

Hay que observar un par de cosas y es que para pasar una imagen dentro del metodo drawImage es necesario que sea un objeto y no solo un link, es por ello que estamos utilizando la clase Image para crear un objeto de tipo imagen y lo que hago es asignarle el link de la imagen en su atributo src. (esto es como crear una etiqueta

y colocar el link en su atributo src)

¡Tenemos un mario pixelado!

Animations

Y al fin llegamos a la parte más genial pero que puede ser la más compleja, ¡Animación! ¿Cómo puedo animar una imagen con canvas y javascript? y la respuesta no es obvia en realidad tenemos que conocer un par de herramientas más, y volver a la epoca de 1900 done el cine tomo auge gracias a la animación en base de frames esto es; cuadros o imagenes que van cambiano en un periodo de tiempo.

Así que comenzemos a mover a nuestro personaje a travez del canvas.

Lo primero que necesitamos es crear un intervalo de tiempo, y esto se hace con una herramienta de javascript llamada setInterval vamos a jugar un poco con esta herramienta y la sintaxis es la siguiente:

setInterval(function(){
console.log(number)
number++
},1000)

Ahora que sabes usar esta herramienta podemos aplicarla a nuestro personaje, dentro de este intervalo podemos cambiar la posición de mario en base a su “x” o “y” por ejemplo y con esto crear la sensación de movimiento, de paso vamos a almacenar este intervalo en una variable para poder detenerlo en algun momento:

var link = "https://bit.ly/2v3FTX5"
var number = 0
var image = new Image()
image.src = link
var interval = setInterval(function(){
ctx.drawImage(image, number,0,50,50)
if(number > 200) number = 0
number++
},1000)

Uff ¿es un montón de código vdd?, pero no hay nada aqui que con lo que hemos visto el día de hoy no puedas entender ¿se siente bien no?

teniendo pues esta herramienta que nos ayuda a crear animaciones es la hora de crear un videojuego completito ¿estas lista?

¿Donde se pone mi código JavaScript?

Nuestro código JavaScript vive en un archivo .js pero este archivo debe relacionarse a nuestro index.html y lo hacemos con una etiqueta llamada scriptesta etiqueta posee un atributo llamado src donde colocaremos el nombre de nuestro archivo .js, nuestro index.html queda entonces de la siguiente manera:

<html>
<head>
<title>Mario Figther</title>
</head>
<body>
<h1>Mario Figther</h1>
<canvas id="canvas" width="256" height="256"></canvas>

<!--aqui mero-->
<script src="main.js"></script>

</body>
</html>

Con esta sensilla configuracion ahora podemos manipular el dom de nuestro archivo HTML

¡Ya viene lo bueno!

Programación orientada a objetos

Si, ya sé has huido de esto toda tu vida, pero en realidad no es un tema tan dificil solo es que quien te lo ha enseñado tampoco lo entiende ;) vamos a intentar entender que es un constructor (clase) en JavaScript:

function Animal(sonido){
this.sonido = sonido

this.hablar = function(){
console.log('Este animal ' + this.sonido)
}
}
var gatito = new Animal("Mauya")gatito.hablar()

Estructura de un videojuego

Este es un tema que va más allá de solo HTML y JavaScript, es un tema apasionante y que genera millones de dolares en ganancias a grandes empresas, pero es una industria muy dificil de abordar, no solo por lo complejo de crear un videojuego si no también porque el estandard es tan alto que los juegos indie no generan suficientes ingresos a los desarrolladores, aún así gracias a plataformas para publicar videojuegos como GooglePlay, Steam y AppleStore entre otras, hoy en día es muy fácil porbar suerte en esta industría.

Escogimos crear un videojuego porque aún más sencillo que lo anterior es crear un videojuego en HTML y además es la manera más fácil de publicar.

Así que para comenzar vamos a poner todas las piezas en su lugar.

main.js

//canvas
//variables
//constructores
//instancias
//main functions
//aux functions
//listeners

Vamos ir poniendo nuestro código en cada una de las secciones que hemos diseñado, este código puede crecer muchisimo por ello es importante colocar las pequeñas piezas en el lugar correcto. ¡vamos pues!

El Background

Es mucho mas facil crea una funcion para obtener objetos que crearlos a mano, en JavaScript a estas funciones que crean objetos en base a una plantilla se les llama constructors y vamos a escribir nuestro primer constructor que representará el fondo de nuestro videojuego.

function Background(){
this.x = 0
this.y = 0
this.width = canvas.width
this.height = canvas.height
this.imagen = new Image()
this.imagen.src = fondo
this.imagen.onload = function(){
this.draw()
}.bind(this)

this.draw = function(){
ctx.drawImage(this.imagen, this.x, this.y, this.width, this.height)
}
}
//instancias
var board = new Background()

Para crear una instancia solo debes utilizar el keyword new con lo cual de forma automática se creará el objeto board con todos los atributos que definimos en el constructor. ¡Genial! tenemos el tablero!

Para checar cómo va nuestro juego solo debes dar doble click al archivo index.html

Y antes de continuar esta es la estructura que hasta ahora tenemos y a partir de aquí seguiremos avanzando solo con el código que vamos agregando:

//canvas
var canvas = document.getElementById('canvas')
var ctx = canvas.getContext('2d')
//ctx.fillRect(0,0,512,512)
//variables
var frames = 0
var fondo = "https://bit.ly/2LA87TH"
//clases (constructores)
function Background(){
this.x = 0
this.y = 0
this.width = canvas.width
this.height = canvas.height
this.imagen = new Image()
this.imagen.src = fondo
this.imagen.onload = function(){
this.draw()
}.bind(this)

this.draw = function(){
ctx.drawImage(this.imagen, this.x, this.y, this.width, this.height)
}
}
//instancias
var board = new Background()
//main functions
//aux functions
//listeners

Nuestro Heroe

Esta es la parte emocionante, todo juego necesita un protagonista, un heroe que salve el día, y nos toca crear a nuestro heroe!, seguramente como a mi, a ti tambíen te toco jugar Mario bros. Bueno si no, que triste. Esta es nuestra oportunidad de revivir a nuestro personaje favorito ¡Mario!.

Para ello es el momento de crear nuestro constructor correspondiente de la siguiente manera:

var mario = "https://bit.ly/2v3FTX5"function Heroe(){
this.x = canvas.width / 3
this.y = canvas.height - 50
this.width = 64
this.height = 64
this.imagen = new Image()
this.imagen.src = mario
this.imagen.onload = function(){
this.draw()
}.bind(this)

this.draw = function(){
if(this.x < 0) this.x = 0
if(this.x > canvas.width) this.x = canvas.width - 8
ctx.drawImage(this.imagen, this.x, this.y, this.width, this.height)
}
}
//instancias
var mario = new Heroe()

Con esto nuestro heroe ahora puede vivir en nuestro mundo es genial ¿no?

Enemigos

Vamos a crear un tercer constructor que nos va a permitir darle emoción a nuestro juego, y para ello vamos a revivir también a el enemigo defacto de Mario, ¡el goomba!, y también necesitaremos una clase para crear no solo un enemigo si no, ¡muchos!

function Enemy(x){
this.x = x
this.y = 0
this.width = canvas.width
this.height = canvas.height
this.imagen = new Image()
this.imagen.src = goomba
this.imagen.onload = function(){
this.draw()
}.bind(this)

this.draw = function(){
this.y++
ctx.drawImage(this.imagen, this.x, this.y, this.width, this.height)
}
}
//instancias
var enemy1 = new Enemy(0)
var enemy2 = new Enemy(128)
var enemy3 = new Enemy(384)

Aux Functions

Vamos a usar nuestras funciones auxiliares para crear muchos enemigos de forma aleatoria y colocarlos en la pantalla al mismo tiempo que conseguimos que avancen en contra de mario.

//variables
var enemies = [];
//aux functions
function generateEnemy(){
if(frames % 64 === 0){
const x = Math.floor(Math.random() * 8)
enemies.push(new Enemy(x * 64))
}
}
function drawEnemies(){
enemies.forEach(function(enemy){
enemy.draw()
})
}

De igual forma hemos colocado una función auxiliar para dibujar a los enemigos, recorriendo todo el array donde viven los enemigos y pidiendo uno por uno que se dibujen en pantalla.

!Genial! si revisas el juego, ahora mario tiene muchos enemigos, ¿tal vez sea mejor que muchos amigos no? a estos los puede matar o esquivar =P

Listeners

Es hora de controlar a nuestro personaje principal y para ello, vamos a utilizar una propiedad del navegador que se manipula con JavaScript; Listeners los listeners como su nombre lo indica, nos permiten escuchar eventos que suceden en los dispositivos de entrada de la computadora como el mouse, el microfono o el teclado, en esta ocación nos toca usar el teclado y para ello escucharemos un evento en particular, cuando una tecla es presionada y este evento se llama:
keydown

addEventListener('keydown', function(e){
if(e.keyCode === 37){
if(mario.x <= 0) return
mario.x -= 64;
}

})

Para encontrar el código de la tecla que se ha presionado podemos utilizar esta página que nos ayuda a visualizar el código de las teclas: keycode.info

Antes de mirar como queda el código completo de los controles, ahora que haz visto cómo mover a mario hacia la izquierda, ¿serías capaz de moverlo hacia la derecha por tu cuenta?

El código completo queda de la siguiente manera:

addEventListener('keydown', function(e){
if(e.keyCode === 37){
if(mario.x <= 0) return
mario.x -= 64;
}
if(e.keyCode === 39){
if(mario.x >= canvas.width-64) return
mario.x += 64;
}

})

Main functions

¡Pero nuestros controles no sirven! D= ¿que está pasando? pues si recuerdas nosotros ya aprendimos que una animación está hecha a base de frames y estos frames son probocados por un intervalo que actualiza el canvas en cierto periodo de tiempo, y eso justamente es lo que nos hace falta para ver a mario moverse, pues el cambio se realiza en su “x” el problema estiva en que no se refleja ese cambio dibujando de nuevo el canvas, y eso justamente es el trabajo de una de nuestras funciones principales:

function update(){
ctx.clearRect(0,0,canvas.width,canvas.height)
frames++
board.draw()
mario.draw()
generateEnemy()
drawEnemies()
}
function start(){
interval = setInterval(update,1000/60)
}

Observemos que las funciones principales dependen una de la otra, y la mas importante es update, pues se encarga de dibujar cada uno de los elementos. El metodo clearRect nos permite borrar el canvas antes de volver a dibujar, esto nos ayuda a ahorrar memoria.

Plus: podemos agregar musica a nuestro videojuego: poniendo un mp3 en una etiqueta audio. <audio src="https://bit.ly/2LM3jHW"></audio>

Colisiones

¡Ya estamos a nada de Terminar nuestro primer videojuego!, ¿no te emociona?, pero para que un videojuego este completo hacen falta más piezas y algunas son más complejas que otras, por ejemplo: en los videojuegos las cosas pueden chocar entre si e interactuar, pero para lograr ese tipo de interacciónes hacen falta algoritmos mas complejos y algunas veces matematicos, en Ironhack puedes aprender a fondo cómo pensar como desarrollador y a resolver los problemas más complejos, justo como las colisiones en un videojuego, pero como queremos que hoy te lleves un videojuego completo y jugable, vamos a ayudarte un poco con este algoritmo, asi que prepara tu skill de copyPaste y coloquemos este metodo en nuestro constructor de nuestro heroe.

function Heroe(){
this.x = 0
this.y = 0
this.width = canvas.width
this.height = canvas.height
this.imagen = new Image()
this.imagen.src = mario
this.imagen.onload = function(){
this.draw()
}.bind(this)

this.draw = function(){
if(this.x < 0) this.x = 0
if(this.x > canvas.width) this.x = canvas.width - 8
ctx.drawImage(this.imagen, this.x, this.y, this.width, this.height)
}

this.checkIfTouch = function(enemy){
return (this.x < enemy.x + enemy.width) &&
(this.x + this.width > enemy.x) &&
(this.y < enemy.y + enemy.height) &&
(this.y + this.height > enemy.y);
}
}

Aunque de principio paresca que no se entiende nada de lo que hace este pedacito de código, ahora mario ya podrá saber si algun enemigo llega a tocarlo, solo hace falta crear una funcion auxiliar que este revisando las coliciones en cada frame:

//aux functions
function checkCollition(){
enemies.forEach(enemy=>{
if(mario.checkIfTouch(enemy)){
gameOver()
}
})
}
//main functions
function update(){
ctx.clearRect(0,0,canvas.width,canvas.height)
frames++
board.draw()
mario.draw()
generateEnemy()
drawEnemies()
checkCollition()
}

Esta funcion checkCollition la colocamos en el update para que sea invocada cada que volvemos a dibujar el canvas. ¿Que hace esta funcion? Recorremos toda la lista de enemigos y preguntamos a mario si esta tocando a alguno. Si es así detenemos el juego con una funcion principal llamada gameOver, vamos a crearla.

Game Over

Es momento de terminar nuestro juego, y para ello vamos a usar la nueva habilidad de mario para detectar si un enemigo lo toca y de esta manera terminar nuestro juego con un enorme y horrible GAMEOVER como nos gusta =3

//main functions
function gameOver(){
clearInterval(interval)
ctx.font = "50px Avenir"
ctx.fillStyle = "white"
ctx.fillText('GAME OVER',100,100)
}

Plus: podemos dibujar la cantidad de goompas que han pasado para usarlo como puntaje: ctx.fillText("Puntos: " + enemies.length, 100,150)

Aún quedan muchos detalles por hacerle a este genial videojuego, pero hey!, mira lo que has creado por ti misma, ya tiras codigo ‘like a pro’, dejaremos los detalles para otra ocación y si se te ocurren modificaciones no dudes en implementarlas tu misma =D

Felicidades, ahora eres programadora, bienvenida al lado oscuro.

Recursos

Juego terminado

--

--

Héctor BlisS
FixterGeek

Soy de la generación que jugó con Atari, se conecto a internet con dial-up mientras mi mamá me regañaba por usar la linea, creo que soy millennial. =P