PICO-8 Tutorial #2: Funciones y Variables


Funciones

Las funciones y variables son dos de los conceptos más básicos de cualquier lenguaje de programación. Hasta ahora hemos usado funciones que ya estaban creadas, nosotros no hemos escrito que hace PRINT() ni los parámetros que dicha función acepta. Sin embargo, una parte fundamental para programar en general es aprender cómo escribir nuestras propias funciones.

En LUA podemos escribir nuestras propias funciones de la siguiente forma:

  1. Declaramos a PICO-8 que vamos a crear una función con la palabra reservada FUNCTION.
  1. Damos un nombre a nuestra función.
  1. Abrimos y cerramos paréntesis. Ya sea para introducir algún tipo de valor o bien para dejarlo vacío.
  1. Intro  y escribimos END indicando a PICO-8 que nuestra función ha terminado.

Hemos modificado nuestro código del ejemplo anterior de la siguiente forma:

Una función ejecuta cualquier bloque de código que se encuentre entre su declaración y el END.

Sin embargo, esto no es todo, una vez declarada y definida nuestra función hay que llamarla para que se ejecute. De hecho, si haces un RUN de nuestro anterior script no va a suceder nada. Hay que lanzar la función. Esto se hace del siguiente modo:

Ahora sí, nuestra función se va a ejecutar. Cuidado aquí hay 2 puntos importantes:

  • El orden, recuerda que PICO-8 ejecuta y compila secuencialmente, hay muchos lenguajes de programación que permiten que pongas la  declaración de la función en cualquier lugar del código, mientras sea accesible se ejecutará. Aquí no, si ponemos la llamada a la función antes que la declaración de esta PICO-8 nos devolverá un error de vacío o null, conforme no sabe a qué te refieres. Ve la función pero como aún no la ha compilado no sabe que hacer con ello y el programa deja de ejecutarse mostrando el error.
  • El objetivo de las funciones es reutilizar el código sin tener que volver a escribirlo por lo que, aunque no tiene mucho sentido utilizar una función con una sola línea de código, tienes que entender que la gracia de todo esto es que podemos llamar múltiples veces y cada vez que lo llamemos ejecutará el bloque de código contenido en la función. Esto gana sentido cuando nuestras funciones contienen por ejemplo 50 líneas de código y necesitamos ejecutarlas por ejemplo 20 veces en puntos distintos de nuestro programa. No hay que copiar las mismas lineas de codigo en esos 20 puntos, ¡sencillamente llamamos a la función!

Para mostrar un poco el último punto Vamos a llamar 3 veces la función y ejecutar nuestro programa:

Espero que se haya entendido el concepto de las funciones, porque ahora, mirando ya a PICO-8 y al desarrollo de los videojuegos vamos a hablar de las 3 funciones vitales propias de PICO-8 y que van a estar presentes en todos nuestros juegos ya que nos permiten controlar el flujo del juego:

  • function _init() : Esta función, siempre que conste en nuestro script se ejecutara al empezar a ejecutar nuestro programa. Y se ejecuta una sola vez. En esta función pueden haber, por ejemplo, líneas de código encargadas de mostrar el menú, disparar la música, limpiar la pantalla, en resumen todas aquellas acciones que necesitemos iniciar.

  • function _update() : Esta función ejecutará todas las líneas de código que se encuentren en ella, en cada frame, desde que se inicia el juego. Esta función se puede entender como un bucle y de hecho en desarrollo para videojuegos tiene el nombre de “bucle de juego”. Piensa pues que un juego necesita ser reactivo a nuestras acciones, a cada frame puede pasar algo, por lo que es necesario un bucle que compruebe y se ejecute en cada frame. El ejemplo más fácil de imaginar aquí, es el input de un botón que hace que nuestro personaje se mueva o salte o ataque. En todos los frames nuestro jugador tiene la posibilidad de pulsar ese botón y el personaje tendrá que reaccionar acorde a ello. Cualquiera que sean las líneas de código que se encarguen de esto tendrán que estar en la función _update().

 

  • function _draw() : Al igual que _update(), draw también se ejecuta en cada frame del juego, a veces. Si bien _update() siempre va a ejecutarse en todos los frames del juego, SIEMPRE, la función _draw() está diseñada para ejecutarse solo cuando se detectan cambios. Es una función pensada para optimizar el rendimiento de PICO-8, ya que actualizar 30 o 60 frames por segundo con todo el código puede ser algo pesado para la máquina y puede resultar en ralentizaciones. De hecho, una de las tareas más pesadas para PICO-8 es tener que dibujar los pixeles en la pantalla. Esta función permite hacerlo solo cuando realmente es necesario ahorrando tiempo de procesamiento y optimizando el uso de la memoria. Por ello es habitual que en esta función encontremos todo lo relacionado con la parte de representar gráficamente el juego.

Vamos a usar las 3 tal y como estaban en los ejemplos, mira lo que ocurre al ejecutar:

Si seguimos el flujo, lo primero que se ejecuta es _init por lo que la pantalla se limpia de todo texto que se mostrará anteriormente. Siguen a la ejecución _update y _draw lo que hace que la palabra update y el corazón se impriman infinitamente por pantalla mientras dure la ejecución del programa. Podemos imaginar por el funcionamiento de estas funciones que el corazón al no cambiar de posición o dato en realidad solo es procesado una vez y se queda mostrándose en pantalla mientras que el comando de print update se ejecuta cada vez.

Variables

Normalmente la definición de variables en programación suele ser algo parecido a contenedores de datos en algún formato concreto. Pueden entenderse como cajas, no físicas, sino virtuales, que pueden guardar números enteros, cadenas de caracteres, decimales, valores booleanos, etc. Podemos almacenar lo que queramos en una variable, el nombre de nuestro personaje principal, su sprite, los puntos de vida que tiene, etc. Por ello las variables pueden llegar a ser bastante complejas.

También es relevante que entendamos, especialmente en un entorno de desarrollo de videojuegos, que las variables son útiles porque pueden cambiar (¡variar! bles), no tienen porque ser valores estáticos sino que se pueden modificar a través de nuestro código. Será de hecho así, como podremos hacer por ejemplo que un objeto o personaje se mueva en la pantalla.

¡Vamos, pues! a crear nuestras primeras variables. La creación de una variable se distingue en dos partes: 

  • Declaración: Al igual que las funciones tenemos que declarar una variable, para ello,  le podemos poner el nombre que queramos seguido de un = .

  • Definición: Definir su contenido o sea introducir el dato que almacena es lo que se conoce como definir la variable.

Al contrario que otros lenguajes de programación LUA no requiere distinguir el tipo de dato que introducimos al definir la variable. Por lo que podemos declarar una variable y definir sencillamente del siguiente modo:

Si es importante que seas consciente de que no es lo mismo guardar un número que una cadena de texto o string o bien un valor booleano. A la hora de compilar nuestro programa, aunque LUA sea flexible en este sentido, si podemos tener problemas al mezclar varios tiempos de variables.

¿Para qué hemos hecho esto? Bien vamos a recuperar nuestra línea de código que era el corazón. Vamos a sustituir los datos introducidos como parámetros dentro del print por los nombres de nuestras variables. Observa qué sucede:

 

Cambiar una variable

Vamos a conjuntar lo que hemos aprendido sobre funciones y variables para modificar nuestra variable y alterar la posición de nuestro corazón. Usando la función _update, que sabemos que se ejecuta en cada frame del juego. Vamos a usar una variable dentro del método para que en cada frame variamos su valor por +1. Para ello tenemos que sumar asignar a esa variable la propia variable y sumarle + 1 a cualquiera que sea el valor de esta.

Se que es un poco confuso pero espero que con el ejemplo quede claro:

  • Declaramos las siguientes variables:

  • Dentro de la función _update modificamos m_x y m_y tal y como se explicaba arriba, recuerda que puedes poner el nombre que quieras a estas variables. Las he nombrado así para implicar que una se traducirá en el movimiento en el eje de las x y el otro en el movimiento en el eje de la y.

  • Finalmente haz el print en draw usando las variables que hemos declarado:

   

Es importante que pongas el cls() en draw, si en cada frame no limpiamos la pantalla empezaremos a copiar nuestro corazón sin borrarlo en la nueva coordenada creado un efecto bastante curioso. Pruébalo si quieres.

El resultado de ejecutar este código debe ser un corazón rojo que se mueve en diagonal (estamos moviendo nuestro corazón ambos ejes a la vez) y se va de la pantalla:

Código completo:

color_♥ = 8

texto = "♥"

m_x = 10

m_y = 10

function _init()

    

end

function _update()

    m_x = m_x + 1

    m_y = m_y + 1

end

function _draw()

cls()

print(texto, m_x, m_y, color_♥)

    

end

¿Por qué no pruebas a cambiar el color también del mismo modo y ver que pasa? ¿O a cambiar el incremento que reciben las variables? ¿o quizá a quitar ahora sí, el cls() y ver que sucede?

¿Entiendes porque el corazón se repite? o porque cambia de color constantemente? Si es así mi misión para este post ha finalizado :) y ¡hemos creado nuestro primer objeto en movimiento!

Leave a comment

Log in with itch.io to leave a comment.