[#_lesson_1_hello] == Lección 1: Hola image::learn/01-hello.png[La lección terminada, 480] Eso es lo que tendrás al final de esta lección. No es gran cosa a la vista. También es un programa que has escrito tú, funcionando en un motor de juegos de verdad, y todo lo demás de este libro se construye sobre las cinco líneas que lo hicieron. [#_set_up_your_work_folder] === Prepara tu carpeta de trabajo Crea una carpeta para guardarlo todo, llamada `singe` o como quieras, y pon dentro tu copia de Singe. Esta es tu *carpeta de trabajo*, y cada lección de este libro pone una carpeta nueva dentro de ella. La crearás una vez y no volverás a pensar en ella. Dentro de la carpeta de trabajo, crea una carpeta llamada `hello`, y dentro de ella un archivo llamado `hello.singe`. [literal] ---- singe/ <- tu carpeta de trabajo, con Singe dentro hello/ hello.singe ---- Tanto anidamiento no es una manía. Singe trata la carpeta desde la que lo ejecutas como el sitio donde viven los juegos, una carpeta por juego, y también guarda allí sus propios archivos. Tu juego va en su propia carpeta, un nivel más abajo. De la lección dos en adelante, cada lección es otra carpeta junto a `hello`. Dos cosas sobre los nombres. La parte que va después del punto, `.singe`, es como Singe sabe que esto es un script. Y en la mayoría de los ordenadores que no son Windows, las mayúsculas cuentan: `Hello.singe` y `hello.singe` son dos archivos distintos. Acostúmbrate desde ya a escribir los nombres exactamente. Que la carpeta y el script tengan el mismo nombre también importa, y enseguida verás por qué. Abre `hello.singe` en tu editor de texto. Está vacío. Es lo correcto. [#_type_this_in] === Escribe esto [source,lua] ---- function onOverlayUpdate() overlayClear() overlayPrint(2, 2, "Hello!") return OVERLAY_UPDATED end ---- Guárdalo. No te preocupes todavía por lo que significa nada de esto. Vale la pena fijarse en dos cosas antes de ejecutarlo, porque se cumplirán en todos los programas que escribas. La primera es que los espacios al principio de las tres líneas del medio están ahí a propósito. No le hacen nada en absoluto al programa -- Singe lo ejecutaría exactamente igual sin ellos -- pero te muestran de un vistazo que esas tres líneas van *dentro* de la cosa que empieza con `function` y termina con `end`. Todos los programadores lo hacen. Hazlo desde el primer día y nunca tendrás que aprenderlo más tarde. La segunda es el orden de las líneas. Ocurren de arriba abajo, una tras otra, como los pasos de una receta. Es lo más importante de un programa, y casi todo lo que confunde a un principiante viene de olvidarlo. [#_run_it] === Ejecútalo Abre una terminal, ve a tu *carpeta de trabajo* -- no a la carpeta `hello` que hay dentro -- y escribe el nombre de la carpeta que quieres ejecutar: ---- Singe hello ---- En Windows es `Singe.exe hello`. Si tu copia de Singe está en otro sitio, escribe la ruta hasta ella, por ejemplo `../Singe hello`. Por eso la carpeta y el script comparten nombre. Cuando le das una carpeta, Singe busca dentro un script que se llame igual. Ponles nombres distintos y obtendrás `Error: Unable to locate the game.`, que es el motor diciendo que ha buscado y no ha encontrado nada que reconozca. Siempre puedes ser explícito y escribir `Singe hello/hello.singe`, que hace lo mismo. Se abre una ventana negra con la palabra `Hello!` cerca de la esquina superior izquierda. Pulsa *Esc* o *Q* para salir. Habrán pasado dos cosas que no has pedido, y las dos son normales. En tu carpeta de trabajo han aparecido unas carpetas llamadas `Singe` y `data`, junto a `hello`: la primera es el motor desempaquetando los archivos que necesita, y la segunda es donde irá todo lo que guarden tus juegos. Deja las dos en paz. Y la ventana es casi toda negra, porque no has dibujado nada aparte de seis caracteres. [#_what_just_happened] === Qué acaba de pasar Ahora las cinco líneas, de una en una. [source,lua] ---- function onOverlayUpdate() ---- `function` empieza un grupo de instrucciones y le da un nombre. Todo lo que hay desde aquí hasta el `end` que le corresponde le pertenece. Esta se llama `onOverlayUpdate`, y los paréntesis vacíos después del nombre tendrán sentido en la lección cinco. Ese nombre no lo eliges tú. Singe busca una función con exactamente ese nombre y la llama unas sesenta veces por segundo, para siempre, para que tengas ocasión de dibujar. Si lo escribes `onoverlayupdate` u `onOverlayUpdated`, Singe no la encontrará, tu ventana se quedará negra y nada te dirá que te has equivocado. Esa es la primera lección de verdad: el ordenador hace lo que escribiste, no lo que querías decir. Una función que escribes tú y que llama el motor es un *callback*. No la llamas tú, y no puedes decidir cuándo se ejecuta; la escribes, y Singe te devuelve la llamada cuando hay algo que hacer. Todos los nombres de este libro que empiezan por `on` son callbacks, y hay uno para casi todo lo que puede pasar: un botón pulsado, una tecla escrita, un sonido que termina, el disco que llega a un fotograma. `onOverlayUpdate` es el de dibujar, y es el único sitio donde se permite dibujar. [source,lua] ---- overlayClear() ---- Esto también es una función, pero no una que tengas que escribir tú: la proporciona Singe, junto con varios cientos más, y tú la estás *llamando*. Llamar a una función significa decir su nombre seguido de paréntesis. Esta deja la pantalla limpia. Va primero porque dibujar no sustituye lo que había antes, sino que dibuja encima. Primero limpias, luego dibujas, siempre. [source,lua] ---- overlayPrint(2, 2, "Hello!") ---- Otra llamada, y a esta hay que decirle tres cosas, que van dentro de los paréntesis separadas por comas. Las cosas que le das así a una función se llaman *argumentos*. Las dos primeras son números: cuánto hacia la derecha y cuánto hacia abajo. La tercera es el texto que hay que imprimir, y va entre comillas dobles porque así es como le dices al ordenador que `Hello!` es un trozo de texto y no el nombre de algo. Al texto entre comillas se le llama *cadena*, y usarás cadenas constantemente. Tarde o temprano querrás poner unas comillas dobles dentro de una cadena, y la forma obvia no funciona: las segundas comillas terminan la cadena antes de tiempo, y te sale el mismo error `unfinished string` que verás al final de esta lección. Hay dos formas de evitarlo, y vale la pena conocer las dos. [source,lua] ---- overlayPrint(2, 2, "She said \"hello\" to me.") overlayPrint(2, 4, 'She said "hello" to me.') ---- La primera pone una barra invertida delante de cada comilla que forma parte del texto. La barra invertida dice «el siguiente carácter es parte de la cadena, no su final», y las dos juntas se llaman *secuencia de escape*. La segunda usa comillas simples para marcar los extremos de la cadena, lo que deja las comillas dobles libres para ser texto normal. Lua acepta cualquiera de los dos tipos de comillas, siempre que la cadena termine con el mismo tipo con el que empezó. Esas dos líneas imprimen exactamente lo mismo. Usa la que se lea mejor, que suele ser la de comillas simples cuando el texto está lleno de comillas dobles. Los dos números no son píxeles. `overlayPrint` es el texto sencillo del propio motor, y cuenta en celdas de carácter: `(0, 0)` es la esquina superior izquierda del todo, `(1, 0)` es una letra a la derecha, y `(0, 1)` es una línea más abajo. Así que `(2, 2)` está dos letras hacia dentro y dos líneas hacia abajo. Otras formas de dibujar texto sí cuentan en píxeles, y las verás en la lección diecinueve. [source,lua] ---- return OVERLAY_UPDATED ---- `return` devuelve una respuesta a quien haya llamado a la función. Singe le hace a tu `onOverlayUpdate` una pregunta cada vez que la llama: ¿has cambiado algo? `OVERLAY_UPDATED` significa que sí, así que ponlo en pantalla. `OVERLAY_UPDATED` no lleva comillas porque no es texto. Es un nombre que Singe ya le ha dado a un valor, para que puedas escribir algo que se pueda leer en lugar de un número que tendrías que recordar. [source,lua] ---- end ---- El final que corresponde a la `function`. Cada `function` tiene exactamente uno, y olvidarlo es el error más común que existe. [#_try_it] === Pruébalo Cambia una cosa cada vez, guarda y vuelve a ejecutarlo. Ese ciclo -- cambiar, ejecutar, mirar -- es todo el trabajo. . *Mueve el texto.* Cambia `overlayPrint(2, 2, "Hello!")` por `overlayPrint(10, 5, "Hello!")`. Luego prueba `(0, 0)`. Luego prueba `(200, 2)`, y averigua por qué ha desaparecido. . *Di otra cosa.* Pon tu nombre entre las comillas. . *Di dos cosas.* Añade una segunda línea `overlayPrint` debajo de la primera, con otro número de fila y otro texto. Nada te impide tener tantas como quieras. . *Quita la limpieza.* Borra la línea `overlayClear()` y ejecútalo. No cambia nada, porque todavía no se mueve nada en tu pantalla. Vuelve a ponerla de todos modos. En la lección dos importará muchísimo, y este es un buen momento para ver que algunos errores esperan antes de morder. [#_break_it_on_purpose] === Rómpelo a propósito Los principiantes pasan más tiempo leyendo mensajes de error que leyendo libros de programación, así que quitémonos ya el primero de encima. Borra las comillas de cierre después de `Hello!`, para que la línea quede `overlayPrint(2, 2, "Hello!)`, y ejecútalo. Singe se niega a arrancar y dice: ---- Error running script: hello/hello.singe:3: unfinished string near '"Hello!)' ---- Léelo desde la izquierda. `hello/hello.singe` es qué archivo: la carpeta y luego el script que hay dentro. `3` es qué línea. El resto es lo que ha ido mal, en este caso un trozo de texto que se abrió y nunca se cerró. Ve a la línea tres, vuelve a poner las comillas y funciona. Casi todos los errores que verás tienen esa forma: un archivo, una línea y una queja. La queja a veces está escrita para alguien que ya sabe Lua, pero el archivo y la línea siempre son correctos, y nueve de cada diez veces la línea basta. [#_stop_restarting_it] === Deja de reiniciarlo Ya has arrancado Singe a mano cinco o seis veces. Deja de hacerlo. Ejecútalo así: ---- Singe -R hello ---- `-R` le dice a Singe que vigile tu script. Guarda un cambio en tu editor y el juego se reinicia solo un momento después con tu cambio dentro, sin cerrar la ventana. Si guardas un error, se imprime el error y la ventana se queda vacía hasta que guardes el arreglo. Usa `-R` durante el resto de este libro. [#_what_you_learned] === Lo que has aprendido * Un programa es un archivo de instrucciones que ocurren en orden, de arriba abajo. * Una `function` agrupa instrucciones bajo un nombre y se detiene en su `end`. * `onOverlayUpdate` es un nombre que Singe busca y llama muchas veces por segundo, y es donde va todo lo que dibujas. * Llamar a una función significa escribir su nombre y unos paréntesis. Lo que va dentro de los paréntesis es un argumento. * Una función que el motor llama por ti, en lugar de una que llamas tú, es un callback. `onOverlayUpdate` es uno. * El texto entre comillas dobles es una cadena. * Limpia la pantalla antes de dibujar en ella. * Un error te dice el archivo y la línea. Empieza por ahí. [#_next_time] === La próxima vez Tu `Hello!` se queda donde lo pusiste y nunca se mueve. Para que se mueva, necesitas un sitio donde guardar un número que cambia -- una *variable* -- y de eso trata toda la lección dos.