289 lines
11 KiB
Text
289 lines
11 KiB
Text
[#_lesson_1_hello]
|
|
== Lezione 1: Ciao
|
|
|
|
image::learn/01-hello.png[La lezione finita, 480]
|
|
|
|
Ecco che cosa avrai alla fine di questa lezione. Non è granché da vedere. È
|
|
anche un programma scritto da te, che gira su un vero motore di gioco, e tutto
|
|
il resto di questo libro è costruito sulle cinque righe che l'hanno creato.
|
|
|
|
[#_set_up_your_work_folder]
|
|
=== Prepara la cartella di lavoro
|
|
|
|
Crea una cartella in cui tenere tutto, chiamata `singe` o come preferisci, e
|
|
mettici dentro la tua copia di Singe. Questa è la tua *cartella di lavoro*, e
|
|
ogni lezione di questo libro ci mette dentro una nuova cartella. La crei una
|
|
volta e non ci pensi più.
|
|
|
|
Dentro la cartella di lavoro crea una cartella chiamata `hello`, e dentro
|
|
quella un file chiamato `hello.singe`.
|
|
|
|
[literal]
|
|
----
|
|
singe/ <- la tua cartella di lavoro, con dentro Singe
|
|
hello/
|
|
hello.singe
|
|
----
|
|
|
|
Questo annidamento non è pignoleria. Singe considera la cartella da cui lo
|
|
esegui come il posto in cui vivono i giochi, una cartella per gioco, e ci tiene
|
|
anche i propri file. Il tuo gioco va nella sua cartella, un livello più giù.
|
|
Dalla seconda lezione in poi ogni lezione è un'altra cartella accanto a
|
|
`hello`.
|
|
|
|
Due cose sui nomi. La parte dopo il punto, `.singe`, è il modo in cui Singe sa
|
|
che questo è uno script. E sulla maggior parte dei computer che non usano
|
|
Windows le maiuscole contano: `Hello.singe` e `hello.singe` sono due file
|
|
diversi. Prendi fin da ora l'abitudine di scrivere i nomi esattamente.
|
|
|
|
Conta anche dare alla cartella e allo script lo stesso nome, e tra un momento
|
|
vedrai perché.
|
|
|
|
Apri `hello.singe` nel tuo editor di testo. È vuoto. È giusto così.
|
|
|
|
[#_type_this_in]
|
|
=== Scrivi questo
|
|
|
|
[source,lua]
|
|
----
|
|
function onOverlayUpdate()
|
|
overlayClear()
|
|
overlayPrint(2, 2, "Hello!")
|
|
return OVERLAY_UPDATED
|
|
end
|
|
----
|
|
|
|
Salvalo.
|
|
|
|
Non preoccuparti ancora di che cosa voglia dire. Prima di eseguirlo vale la
|
|
pena notare due cose, perché varranno per ogni programma che scriverai.
|
|
|
|
La prima è che gli spazi all'inizio delle tre righe centrali sono lì apposta.
|
|
Al programma non fanno proprio niente -- Singe lo eseguirebbe esattamente allo
|
|
stesso modo anche senza -- ma ti mostrano a colpo d'occhio che quelle tre righe
|
|
stanno *dentro* la cosa che comincia con `function` e finisce con `end`. Lo
|
|
fanno tutti i programmatori. Fallo dal primo giorno e non dovrai mai impararlo
|
|
dopo.
|
|
|
|
La seconda è l'ordine delle righe. Avvengono dall'alto in basso, una dopo
|
|
l'altra, come i passi di una ricetta. È la cosa più importante in assoluto di
|
|
un programma, e quasi tutto ciò che confonde un principiante nasce dal
|
|
dimenticarlo.
|
|
|
|
[#_run_it]
|
|
=== Avvialo
|
|
|
|
Apri un terminale, vai nella tua *cartella di lavoro* -- non nella cartella
|
|
`hello` che c'è dentro -- e indica la cartella che vuoi eseguire:
|
|
|
|
----
|
|
Singe hello
|
|
----
|
|
|
|
Su Windows è `Singe.exe hello`. Se la tua copia di Singe sta da un'altra parte,
|
|
scrivi il percorso per arrivarci, come `../Singe hello`.
|
|
|
|
Ecco perché la cartella e lo script hanno lo stesso nome. Quando gli dai una
|
|
cartella, Singe ci cerca dentro uno script che si chiama allo stesso modo. Dagli
|
|
nomi diversi e ottieni `Error: Unable to locate the game.`, che è il motore che
|
|
ti dice di aver cercato senza trovare niente che riconoscesse. In alternativa
|
|
puoi sempre essere esplicito e scrivere `Singe hello/hello.singe`, che fa lo
|
|
stesso lavoro.
|
|
|
|
Si apre una finestra nera con la parola `Hello!` vicino all'angolo in alto a
|
|
sinistra. Premi *Esc* o *Q* per uscire.
|
|
|
|
Saranno successe due cose che non hai chiesto, ed entrambe sono normali. Nella
|
|
tua cartella di lavoro, accanto a `hello`, sono comparse le cartelle `Singe` e
|
|
`data`: la prima è il motore che estrae i file che gli servono, la seconda è
|
|
dove finirà tutto ciò che i tuoi giochi salvano. Lasciale stare tutte e due. E
|
|
la finestra è quasi tutta nera, perché non hai disegnato niente a parte sei
|
|
caratteri.
|
|
|
|
[#_what_just_happened]
|
|
=== Cos'è appena successo
|
|
|
|
Ora le cinque righe, una alla volta.
|
|
|
|
[source,lua]
|
|
----
|
|
function onOverlayUpdate()
|
|
----
|
|
|
|
`function` comincia un gruppo di istruzioni e gli dà un nome. Tutto ciò che c'è
|
|
da qui fino al suo `end` gli appartiene. Questa si chiama
|
|
`onOverlayUpdate`, e le parentesi vuote dopo il nome avranno senso nella quinta
|
|
lezione.
|
|
|
|
Quel nome non lo scegli tu. Singe cerca una funzione con esattamente quel nome
|
|
e la chiama circa sessanta volte al secondo, per sempre, così hai l'occasione di
|
|
disegnare. Se la scrivi `onoverlayupdate` o `onOverlayUpdated`, Singe non la
|
|
trova, la finestra resta nera e niente ti dirà che hai sbagliato. Ecco la prima
|
|
vera lezione: il computer fa quello che hai scritto, non quello che intendevi.
|
|
|
|
Una funzione che scrivi tu e che chiama il motore è una *callback*. Non la
|
|
chiami tu, e non puoi decidere quando viene eseguita: tu la scrivi, e Singe ti
|
|
richiama quando c'è qualcosa da fare. Ogni nome di questo libro che comincia con
|
|
`on` è una callback, e ce n'è una per quasi tutto ciò che può succedere: un
|
|
pulsante premuto, un tasto digitato, un suono che finisce, il disco che
|
|
raggiunge un fotogramma. `onOverlayUpdate` è quella per disegnare, ed è l'unico
|
|
posto in cui è permesso disegnare.
|
|
|
|
[source,lua]
|
|
----
|
|
overlayClear()
|
|
----
|
|
|
|
Anche questa è una funzione, ma non una che devi scrivere tu: la fornisce Singe,
|
|
insieme a diverse centinaia di altre, e tu la stai *chiamando*. Chiamare una
|
|
funzione vuol dire dire il suo nome seguito dalle parentesi. Questa pulisce lo
|
|
schermo.
|
|
|
|
Viene per prima perché disegnare non sostituisce quello che c'era prima: ci
|
|
disegna sopra. Pulisci, poi disegna, ogni volta.
|
|
|
|
[source,lua]
|
|
----
|
|
overlayPrint(2, 2, "Hello!")
|
|
----
|
|
|
|
Un'altra chiamata, e a questa bisogna dire tre cose, che vanno dentro le
|
|
parentesi separate da virgole. Le cose che passi così a una funzione si chiamano
|
|
*argomenti*.
|
|
|
|
I primi due sono numeri: quanto più a destra e quanto più in basso. Il terzo è
|
|
il testo da stampare, ed è tra virgolette doppie perché è così che dici al
|
|
computer che `Hello!` è un pezzo di testo e non il nome di qualcosa. Il testo
|
|
tra virgolette si chiama *stringa*, e userai le stringhe di continuo.
|
|
|
|
Prima o poi vorrai delle virgolette doppie dentro una stringa, e il modo ovvio
|
|
non funziona: la seconda virgoletta chiude la stringa troppo presto, e ottieni
|
|
lo stesso errore `unfinished string` che incontrerai alla fine di questa
|
|
lezione. Ci sono due modi per aggirarlo, e conviene conoscerli entrambi.
|
|
|
|
[source,lua]
|
|
----
|
|
overlayPrint(2, 2, "She said \"hello\" to me.")
|
|
overlayPrint(2, 4, 'She said "hello" to me.')
|
|
----
|
|
|
|
Il primo mette una barra rovesciata davanti a ogni virgoletta che fa parte del
|
|
testo. La barra rovesciata dice «il carattere successivo fa parte della
|
|
stringa, non ne è la fine», e la coppia si chiama *sequenza di escape*. Il
|
|
secondo usa le virgolette singole per segnare i due capi della stringa, e così
|
|
le virgolette doppie restano libere di essere testo normale. Lua accetta tutti e
|
|
due i tipi di virgolette, purché la stringa finisca con lo stesso tipo con cui
|
|
è cominciata.
|
|
|
|
Quelle due righe stampano esattamente la stessa cosa. Usa quella più facile da
|
|
leggere, che di solito è quella con le virgolette singole quando il testo è
|
|
pieno di virgolette doppie.
|
|
|
|
I due numeri non sono pixel. `overlayPrint` è il testo semplice del motore, e
|
|
conta in celle di carattere: `(0, 0)` è proprio l'angolo in alto a sinistra,
|
|
`(1, 0)` è una lettera più a destra e `(0, 1)` è una riga più in basso. Quindi
|
|
`(2, 2)` è due lettere verso destra e due righe verso il basso. Altri modi di
|
|
disegnare il testo contano invece in pixel, e li incontrerai nella
|
|
diciannovesima lezione.
|
|
|
|
[source,lua]
|
|
----
|
|
return OVERLAY_UPDATED
|
|
----
|
|
|
|
`return` restituisce una risposta a chi ha chiamato la funzione. Ogni volta che
|
|
chiama la tua `onOverlayUpdate`, Singe le fa una domanda: hai cambiato qualcosa?
|
|
`OVERLAY_UPDATED` vuol dire sì, quindi mettilo sullo schermo.
|
|
|
|
`OVERLAY_UPDATED` non ha virgolette intorno perché non è testo. È un nome che
|
|
Singe ha già dato a un valore, così puoi scrivere qualcosa che sai leggere
|
|
invece di un numero che dovresti ricordare.
|
|
|
|
[source,lua]
|
|
----
|
|
end
|
|
----
|
|
|
|
La fine corrispondente della `function`. Ogni `function` ne ha esattamente una,
|
|
e dimenticarla è in assoluto l'errore più comune che ci sia.
|
|
|
|
[#_try_it]
|
|
=== Prova tu
|
|
|
|
Cambia una cosa alla volta, salva ed eseguilo di nuovo. Quel ciclo -- cambia,
|
|
esegui, guarda -- è tutto il lavoro.
|
|
|
|
. *Sposta il testo.* Cambia `overlayPrint(2, 2, "Hello!")` in
|
|
`overlayPrint(10, 5, "Hello!")`. Poi prova `(0, 0)`. Poi prova `(200, 2)`, e
|
|
scopri perché è sparito.
|
|
. *Di' qualcos'altro.* Metti il tuo nome tra le virgolette.
|
|
. *Di' due cose.* Aggiungi una seconda riga `overlayPrint` sotto la prima, con
|
|
un numero di riga diverso e un testo diverso. Niente ti impedisce di averne
|
|
quante ne vuoi.
|
|
. *Togli la pulizia.* Cancella la riga `overlayClear()` ed eseguilo. Non cambia
|
|
niente, perché sullo schermo ancora non si muove niente. Rimettila comunque.
|
|
Nella seconda lezione conterà moltissimo, ed è un buon momento per vedere che
|
|
certi errori aspettano prima di mordere.
|
|
|
|
[#_break_it_on_purpose]
|
|
=== Rompilo apposta
|
|
|
|
I principianti passano più tempo a leggere messaggi di errore che libri di
|
|
programmazione, quindi togliamoci subito il pensiero del primo.
|
|
|
|
Cancella la virgoletta di chiusura dopo `Hello!`, così la riga diventa
|
|
`overlayPrint(2, 2, "Hello!)`, ed eseguilo. Singe si rifiuta di partire e dice:
|
|
|
|
----
|
|
Error running script: hello/hello.singe:3: unfinished string near '"Hello!)'
|
|
----
|
|
|
|
Leggilo da sinistra. `hello/hello.singe` è il file: la cartella, poi lo script
|
|
che contiene. `3` è la riga. Il resto è che cosa
|
|
è andato storto, in questo caso un pezzo di testo aperto e mai chiuso. Vai alla
|
|
riga tre, rimetti la virgoletta, e parte.
|
|
|
|
Quasi ogni errore che vedrai ha questa forma: un file, una riga e una
|
|
lamentela. La lamentela a volte è scritta per qualcuno che conosce già Lua, ma
|
|
il file e la riga sono sempre giusti, e nove volte su dieci basta la riga.
|
|
|
|
[#_stop_restarting_it]
|
|
=== Smetti di riavviarlo
|
|
|
|
Ormai hai avviato Singe a mano cinque o sei volte. Smetti di farlo. Avvialo
|
|
invece così:
|
|
|
|
----
|
|
Singe -R hello
|
|
----
|
|
|
|
`-R` dice a Singe di tenere d'occhio il tuo script. Salva una modifica nel tuo
|
|
editor, e un attimo dopo il gioco riparte da solo con la modifica dentro, senza
|
|
chiudere la finestra. Se salvi un errore, l'errore viene stampato e la finestra
|
|
resta vuota finché non salvi una correzione.
|
|
|
|
Usa `-R` per il resto di questo libro.
|
|
|
|
[#_what_you_learned]
|
|
=== Cosa hai imparato
|
|
|
|
* Un programma è un file di istruzioni che avvengono in ordine, dall'alto in
|
|
basso.
|
|
* Una `function` raggruppa delle istruzioni sotto un nome e si ferma al suo
|
|
`end`.
|
|
* `onOverlayUpdate` è un nome che Singe cerca e chiama molte volte al secondo,
|
|
ed è lì che va tutto ciò che disegni.
|
|
* Chiamare una funzione vuol dire scriverne il nome e le parentesi. Tutto ciò
|
|
che sta dentro le parentesi è un argomento.
|
|
* Una funzione che il motore chiama per te, invece di una che chiami tu, è una
|
|
callback. `onOverlayUpdate` è una di queste.
|
|
* Il testo tra virgolette doppie è una stringa.
|
|
* Pulisci lo schermo prima di disegnarci sopra.
|
|
* Un errore ti dice il file e la riga. Comincia da lì.
|
|
|
|
[#_next_time]
|
|
=== La prossima volta
|
|
|
|
Il tuo `Hello!` sta dove l'hai messo e non si muove mai. Per farlo muovere ti
|
|
serve un posto dove tenere un numero che cambia -- una *variabile* -- ed è di
|
|
questo che parla tutta la seconda lezione.
|