501 lines
21 KiB
Text
501 lines
21 KiB
Text
[#_lesson_30_shipping_it]
|
||
== Lezione 30: Distribuirlo
|
||
|
||
image::learn/30-shipping.png[La lezione finita, 480]
|
||
|
||
Hai una cartella. Dentro ci sono uno script, qualche immagine, un paio di suoni
|
||
e il `games.dat` che hai scritto nella tredicesima lezione. Funziona, perché
|
||
tutto quello che le serve è dove l'hai lasciato e tu sai dov'è.
|
||
|
||
Questa lezione trasforma quella cartella in un unico file che qualcuno che non
|
||
ti ha mai conosciuto può copiare sulla sua macchina e giocare. Quasi tutto si
|
||
riduce a due righe di comando. Il resto è la parte che nessuno insegna: che
|
||
cosa va nel file, il lavoro di chi c'è dentro oltre al tuo, e come scoprire se
|
||
funziona anche da qualche altra parte oltre che qui.
|
||
|
||
[#_one_file]
|
||
=== Un solo file
|
||
|
||
Un gioco Singe finito si distribuisce come un unico file `.game`. Per
|
||
impacchettarne uno:
|
||
|
||
----
|
||
Singe --pack MyGame MyGame.game
|
||
----
|
||
|
||
Il primo nome è la cartella del tuo gioco, il secondo è il file da scrivere.
|
||
Singe legge ogni file della cartella dentro un database e dice che cosa ha
|
||
fatto:
|
||
|
||
----
|
||
>>> Packed 42 files (3819204 bytes) from MyGame into MyGame.game
|
||
----
|
||
|
||
Lo avvii come avvii qualsiasi altra cosa:
|
||
|
||
----
|
||
Singe MyGame.game
|
||
----
|
||
|
||
Così parte la prima voce del `games.dat` che contiene; `--entry=2` avvia la
|
||
seconda, per un file che contiene più di un gioco. Per installarlo, il
|
||
giocatore copia `MyGame.game` accanto al programma Singe. Il menu incluso lo
|
||
trova e lo elenca. Non c'è altro: niente programma di installazione, niente
|
||
archivio da estrarre, niente cartella da mettere nel posto giusto.
|
||
|
||
[#_what_packing_does_to_every_file_name]
|
||
=== Che cosa fa l'impacchettamento a ogni nome di file
|
||
|
||
Per essere impacchettato, nel tuo gioco non deve cambiare niente, e vale la
|
||
pena sapere perché, perché è la cosa che ha più probabilità di sorprenderti.
|
||
|
||
Ogni nome che il tuo gioco usa -- `dofile`, `require`, `io.open`, `spriteLoad`,
|
||
`soundLoad`, `fontLoad`, `videoLoad`, un framefile, un `controls.cfg` -- passa
|
||
per un'unica ricerca. Per una cartella sciolta, quella ricerca è il normale
|
||
file system. Per un gioco impacchettato, il nome viene cercato in tre posti e
|
||
vince il primo che lo trova:
|
||
|
||
. una cartella sciolta con il nome del file senza estensione -- `MyGame/`
|
||
accanto a `MyGame.game`;
|
||
. la cartella dei dati del gioco, sotto `files/`, che è dove è finito tutto ciò
|
||
che il gioco scrive;
|
||
. il database stesso.
|
||
|
||
Dentro il database, i nomi vengono confrontati senza badare alle maiuscole, con
|
||
l'uno o l'altro tipo di barra, e a partire dalla radice del gioco. Un nome di
|
||
cartella iniziale uguale a quello del gioco viene ignorato, quindi
|
||
`MyGame/art/spaceship.png`, `art/spaceship.png` e `DIR .. "art/spaceship.png"`
|
||
trovano tutti lo stesso file.
|
||
|
||
Ne derivano due regole, e se hai seguito il libro le rispetti già tutte e due.
|
||
Usa `DIR` per tutto quello che carichi, così un nome non dipende mai da dove è
|
||
stato avviato Singe. E scrivi solo sotto `singeGetDataPath()`, che è dove
|
||
`saveSet` mette già le cose -- un gioco impacchettato viene aperto in sola
|
||
lettura e non ci si scrive mai, quindi un gioco che salva accanto a sé funziona
|
||
da sciolto e fallisce da impacchettato.
|
||
|
||
Due nomi vanno altrove di proposito. Tutto ciò che comincia con `Singe/` resta
|
||
sul file system vero, così `dofile("Singe/Framework.singe")` continua a
|
||
funzionare, e lo stesso vale per la cartella dei dati. E un nome con dentro
|
||
`..` che cerca di arrampicarsi fuori dal gioco non porta da nessuna parte:
|
||
`io.open` restituisce `nil` e un messaggio che dice che il nome esce dal gioco,
|
||
e `spriteLoad` e i suoi parenti segnalano il file come mancante.
|
||
|
||
[#_the_loose_folder_still_wins]
|
||
=== La cartella sciolta vince ancora
|
||
|
||
Il primo posto dell'elenco è quello che userai tutti i giorni. Una cartella con
|
||
il nome del file impacchettato, che gli sta accanto, ha la meglio sulle copie
|
||
impacchettate, file per file.
|
||
|
||
----
|
||
MyGame.game il gioco impacchettato
|
||
MyGame/ una cartella con dentro un file modificato
|
||
----
|
||
|
||
Mettici dentro un solo `art/spaceship.png` corretto e il gioco impacchettato
|
||
parte con la tua nuova immagine e con tutto il resto preso dal database. Per
|
||
provare una modifica non bisogna reimpacchettare niente, e puoi tenere lì tutta
|
||
la tua cartella di lavoro mentre finisci il gioco. È anche il modo in cui un
|
||
giocatore ci fa una mod, e tu puoi considerarla o no una funzionalità.
|
||
|
||
Ne seguono due cose. Prova il gioco almeno una volta con quella cartella
|
||
rinominata, o distribuirai un file che funziona solo sulla macchina che ha la
|
||
cartella. E sappi che impacchettare non nasconde niente: `--unpack` è
|
||
un'opzione documentata e chiunque può usarla. Impacchetta il gioco perché
|
||
diventa un solo file, non perché diventa un file chiuso a chiave.
|
||
|
||
[#_patching_a_released_game]
|
||
=== Applicare una patch a un gioco pubblicato
|
||
|
||
Qualcuno ha il tuo gioco, c'è un bug in uno script, e non vuoi mandargli di
|
||
nuovo quaranta megabyte.
|
||
|
||
----
|
||
Singe --patch MyGame.game fixes
|
||
----
|
||
|
||
`fixes` è una cartella organizzata come il gioco -- gli stessi nomi negli
|
||
stessi posti -- che contiene solo i file cambiati. I file che la patch non
|
||
nomina restano come sono. L'intera modifica è un'unica transazione, quindi una
|
||
patch interrotta lascia il gioco esattamente com'era invece che sostituito a
|
||
metà.
|
||
|
||
Una patch può viaggiare come file a sé, creato con l'impacchettatore:
|
||
|
||
----
|
||
Singe --pack fixes MyGame-1.0.2.patch
|
||
Singe --patch MyGame.game MyGame-1.0.2.patch
|
||
----
|
||
|
||
Un `.patch` non ha bisogno di un `games.dat`, non si può avviare, e il menu lo
|
||
ignora. Può anche portare una tabella `removed(path)` che nomina i file da
|
||
cancellare, per la grafica che hai sostituito con qualcosa che ha un nome
|
||
diverso. In un caso o nell'altro, dopo Singe controlla il gioco aggiornato
|
||
nello stesso modo in cui controlla un gioco nuovo, quindi una patch non può
|
||
lasciare il tuo `games.dat` a puntare a un file che non c'è più.
|
||
|
||
E per tirare fuori di nuovo tutto:
|
||
|
||
----
|
||
Singe --unpack MyGame.game MyGameUnpacked
|
||
----
|
||
|
||
[#_what_the_packer_refuses]
|
||
=== Che cosa rifiuta l'impacchettatore
|
||
|
||
L'impacchettatore non costruisce un gioco con qualunque cosa, e ogni rifiuto
|
||
riguarda qualcosa che più avanti si romperebbe. Rifiuta una cartella senza un
|
||
`games.dat` alla radice. Rifiuta un `Framework.singe`, un `controls.dat`,
|
||
qualunque cosa finisca in `exe`, `sh`, `bat` o `cmd`, e un file senza
|
||
estensione il cui nome comincia con `singe` -- in altre parole, una copia del
|
||
motore o dei suoi file di supporto finita per sbaglio nella cartella del gioco.
|
||
Rifiuta due file i cui nomi differiscono solo per le maiuscole, perché la
|
||
ricerca non sa distinguerli. Rifiuta una voce al primo livello con lo stesso
|
||
nome della cartella. E controlla il tuo `games.dat` prima di confermare: ogni
|
||
voce ha bisogno di uno `SCRIPT`, e ogni `SCRIPT`, `VIDEO`, `CABINET`, `MARQUEE`
|
||
e `ATTRACT` che nomina deve essere un file che c'è davvero. Un percorso
|
||
sbagliato viene segnalato con il titolo della voce, e non viene scritto niente.
|
||
|
||
Ogni lamentela nomina il file, e ricevi l'elenco di tutte invece che solo della
|
||
prima, così un solo tentativo ti dice tutto quello che c'è da correggere.
|
||
|
||
[#_what_to_include_and_what_to_leave_out]
|
||
=== Che cosa includere e che cosa lasciare fuori
|
||
|
||
Guarda nella cartella del gioco. Una parte di quello che c'è dentro è il gioco,
|
||
e un'altra parte è il modo in cui il gioco è stato fatto.
|
||
|
||
Da distribuire: lo script e tutto quello che carica, il `games.dat`, la grafica
|
||
che mostra il menu (`CABINET`, `MARQUEE` e la clip `ATTRACT`), i tuoi file dei
|
||
crediti e delle licenze, e un leggimi se ne hai uno.
|
||
|
||
Da lasciare fuori: i disegni da cui hai esportato la grafica, le registrazioni
|
||
dei suoni che non hai usato, i tuoi appunti, gli script di prova, gli
|
||
screenshot, qualunque cosa si chiami `old` o `backup`, la cartella `data` con
|
||
dentro i tuoi salvataggi e i tuoi punteggi record, e qualunque cosa non
|
||
vorresti far leggere a uno sconosciuto. Si impacchetta tutto benissimo, ed è
|
||
proprio questo il problema: esce insieme al gioco, e chiunque ci arriva con un
|
||
`--unpack`.
|
||
|
||
Il modo affidabile per scoprire che cosa hai distribuito davvero è estrarlo in
|
||
una cartella vuota e guardare. Fallo una volta per ogni versione che pubblichi.
|
||
Ci vuole un minuto, ed è l'unico controllo che vede quello che hai dimenticato
|
||
invece di quello che ricordi.
|
||
|
||
[#_credits_and_licenses]
|
||
=== Crediti e licenze
|
||
|
||
Se una qualunque immagine, suono, musica o font del tuo gioco l'ha fatta
|
||
qualcun altro, stai distribuendo il suo lavoro, e le condizioni a cui te l'ha
|
||
dato sono un obbligo, non una cortesia. Non è una formalità e non è una
|
||
questione di avvocati: una persona ha fatto quella cosa e in cambio ha chiesto
|
||
una cosa precisa, di solito il suo nome.
|
||
|
||
Tieni un registro mentre lavori, non alla fine. Un file di testo semplice nella
|
||
cartella del gioco con una riga per ogni elemento: che file è, da dove viene,
|
||
chi l'ha fatto, quale licenza e che cosa richiede quella licenza. Scriverlo man
|
||
mano richiede pochi secondi. Ricostruirlo la sera prima dell'uscita, dalla
|
||
cronologia del browser, è il modo in cui i crediti vengono dimenticati.
|
||
|
||
Alcune cose che vale la pena sapere prima che ti servano. «Scaricabile
|
||
gratuitamente» non è una licenza: cerca le condizioni vere. Creative Commons
|
||
`BY` vuol dire che devi dare il credito indicato, e non c'è nessuna eccezione
|
||
per i giochi. `CC0` e il pubblico dominio non chiedono niente, e citare
|
||
l'autore comunque ti costa una riga. I font hanno le loro licenze, e alcune ne
|
||
permettono l'incorporazione mentre altre no. La musica presa da un video non è
|
||
quasi mai tua da usare. Tutto ciò che è generato da uno strumento è pulito solo
|
||
quanto le condizioni di quello strumento.
|
||
|
||
Poi metti i crediti in un posto dove un giocatore possa raggiungerli, dentro il
|
||
gioco. Non solo in un file di testo lì accanto -- un gioco impacchettato è un
|
||
solo file e il file di testo è là dentro, dove nessuno guarderà. Lo script alla
|
||
fine di questa lezione è quella schermata.
|
||
|
||
Il `Singe/LICENSES` di Singe stesso è il modello da copiare: una riga per ogni
|
||
libreria, con la sua versione, la sua licenza e da dove viene. L'elenco del tuo
|
||
gioco sarà più corto, e il lavoro è lo stesso.
|
||
|
||
[#_a_version_number_that_means_something]
|
||
=== Un numero di versione che significa qualcosa
|
||
|
||
Il tuo gioco avrà una seconda versione. La prima resterà in giro finché durerà
|
||
internet, e qualcuno ti manderà una segnalazione di bug su di essa senza avere
|
||
idea di quale versione abbia.
|
||
|
||
Quindi scegli un numero, mettilo dove un giocatore possa leggerlo, e non
|
||
riusarne mai uno. La forma comune è in tre parti -- `1.0.2` -- e che cosa
|
||
significano le parti conta meno del fatto che salgano sempre e soltanto. Alza
|
||
l'ultima per una correzione, quella in mezzo per qualcosa di nuovo, la prima
|
||
quando hai fatto un gioco diverso. Qualunque cosa tu scelga, scrivila nel tuo
|
||
leggimi, così la rispetterà anche il te del futuro.
|
||
|
||
`games.dat` non ha una chiave per la versione, quindi il numero te lo devi
|
||
portare dietro tu. Mettilo nello script come costante, mostralo nella
|
||
schermata dei crediti, e mettilo nel nome di quello che spedisci
|
||
(`MyGame-1.0.2.game`, `MyGame-1.0.2.patch`). Così la segnalazione del bug
|
||
riporta la versione sullo schermo, e tu sai di quali file si parla.
|
||
|
||
[#_testing_on_a_machine_that_is_not_yours]
|
||
=== Provarlo su una macchina che non è la tua
|
||
|
||
La tua macchina è il posto peggiore in assoluto per provare una versione da
|
||
pubblicare. Ha i font che hai installato, la cartella che stavi modificando, il
|
||
file di salvataggio con dentro le tue impostazioni, e il motore nello stato in
|
||
cui l'ha lasciato un mese di lavoro.
|
||
|
||
La prova minima, in ordine:
|
||
|
||
. Estrai la versione in una cartella vuota e leggi l'elenco dei file.
|
||
. Copia *solo* il file `.game` in un'altra cartella, con una copia nuova di
|
||
Singe e nient'altro, e avvialo dal menu come farà un giocatore.
|
||
. Cancella la cartella `data` di quella cartella e avvialo di nuovo. È un primo
|
||
avvio su una macchina nuova: niente impostazioni salvate, niente punteggi
|
||
record, nessun account connesso. Un gioco che funziona solo al secondo avvio
|
||
è un bug comune, ed è così che lo trovi.
|
||
. Dallo a una persona che non l'ha mai visto, e guarda senza aiutare.
|
||
|
||
Poi prova la macchina oltre al gioco. Avrà uno schermo con proporzioni diverse,
|
||
quindi guarda il gioco in finestra e a schermo intero. Potrebbe non avere
|
||
nessun dispositivo 3D, ed è per questo che il menu ha un secondo renderer. La
|
||
pagina *System Information* degli strumenti di servizio elenca su una sola
|
||
schermata la versione del motore, il sistema operativo, il processore, il
|
||
renderer, i decoder e la cartella dei dati; una foto di quella pagina risponde
|
||
a quasi tutta una segnalazione di bug, e dirlo ai tuoi giocatori nel leggimi ti
|
||
risparmierà una settimana di congetture.
|
||
|
||
[#_the_script_2]
|
||
=== Lo script
|
||
|
||
Una schermata dei crediti e della versione. È una cosa piccola da scrivere, ed
|
||
è la parte della distribuzione che la maggior parte dei giochi sbaglia.
|
||
|
||
[source,lua]
|
||
----
|
||
dofile("Singe/Framework.singe")
|
||
|
||
local GAME_NAME = "Rock Dodger"
|
||
local GAME_VERSION = "1.0.2"
|
||
|
||
local CREDITS = {
|
||
"Written and drawn by <your name here>",
|
||
"",
|
||
"Music \"Night Drive\" by A. Composer",
|
||
" Creative Commons BY 4.0",
|
||
" example.org/night-drive",
|
||
"",
|
||
"Explosion freesound.org user \"thud\"",
|
||
" Creative Commons CC0",
|
||
"",
|
||
"Font FreeSansBold",
|
||
" GPL with the font exception",
|
||
"",
|
||
"Engine Singe " .. SINGE_VERSION_STRING,
|
||
" GPL version 3",
|
||
" See Singe/LICENSES for the",
|
||
" libraries Singe is built on.",
|
||
"",
|
||
"Thank you for playing.",
|
||
}
|
||
|
||
local FIRST_ROW = 4
|
||
local ROWS = 10
|
||
|
||
local scroll = 0
|
||
|
||
|
||
local function scrollBy(lines)
|
||
local most = #CREDITS - ROWS
|
||
|
||
if most < 0 then
|
||
most = 0
|
||
end
|
||
scroll = scroll + lines
|
||
if scroll < 0 then
|
||
scroll = 0
|
||
end
|
||
if scroll > most then
|
||
scroll = most
|
||
end
|
||
end
|
||
|
||
|
||
function onInputPressed(what)
|
||
if what == SWITCH_UP then
|
||
scrollBy(-1)
|
||
elseif what == SWITCH_DOWN then
|
||
scrollBy(1)
|
||
elseif what == SWITCH_BUTTON1 then
|
||
scroll = 0
|
||
end
|
||
end
|
||
|
||
|
||
function onOverlayUpdate()
|
||
local line = nil
|
||
|
||
overlayClear()
|
||
overlayPrint(2, 0, GAME_NAME .. " version " .. GAME_VERSION)
|
||
overlayPrint(2, 1, "Singe " .. SINGE_VERSION_STRING .. " id " .. (singeGetGameId() or "none"))
|
||
|
||
for row = 0, ROWS - 1 do
|
||
line = CREDITS[scroll + row + 1]
|
||
if line then
|
||
overlayPrint(2, FIRST_ROW + row, line)
|
||
end
|
||
end
|
||
|
||
overlayPrint(2, FIRST_ROW + ROWS + 1, "Saves go to:")
|
||
overlayPrint(2, FIRST_ROW + ROWS + 2, singeGetDataPath())
|
||
overlayPrint(2, 17, "Up and down scroll. Button 1 goes back to the top.")
|
||
|
||
return OVERLAY_UPDATED
|
||
end
|
||
----
|
||
|
||
Sostituisci ogni riga di `CREDITS` con la verità sul tuo gioco. I segnaposto
|
||
sono lì per mostrare la forma: che cos'è, chi l'ha fatto, quale licenza e da
|
||
dove viene.
|
||
|
||
[#_what_just_happened_25]
|
||
=== Cos'è appena successo
|
||
|
||
[source,lua]
|
||
----
|
||
local GAME_VERSION = "1.0.2"
|
||
----
|
||
|
||
Un solo posto, in cima, in maiuscolo perché non cambia mai mentre il gioco
|
||
gira. Tutto ciò che mostra la versione legge questo, quindi alzarla è una
|
||
modifica sola invece di una ricerca.
|
||
|
||
[source,lua]
|
||
----
|
||
"Music \"Night Drive\" by A. Composer",
|
||
----
|
||
|
||
Quelle barre rovesciate sono la sequenza di escape che hai incontrato nella
|
||
prima lezione: una virgoletta doppia che fa parte del testo invece di chiudere
|
||
la stringa. I titoli contengono virgolette, ed è per questo che un elenco di
|
||
crediti ci si imbatte già alla prima riga.
|
||
|
||
[source,lua]
|
||
----
|
||
for row = 0, ROWS - 1 do
|
||
line = CREDITS[scroll + row + 1]
|
||
if line then
|
||
----
|
||
|
||
Dieci righe di schermo che mostrano dieci righe di un elenco più lungo di
|
||
dieci. `scroll` dice quanto è scesa la finestra lungo l'elenco. Il `+ 1` c'è
|
||
perché Lua conta un elenco a partire da uno e le righe dello schermo contano da
|
||
zero, e l’`if line then` c'è perché la fine dell'elenco è `nil` -- leggere oltre
|
||
la fine di una tabella in Lua non è un errore, ti dà semplicemente niente, e
|
||
stampare niente lo sarebbe.
|
||
|
||
[source,lua]
|
||
----
|
||
overlayPrint(2, 1, "Singe " .. SINGE_VERSION_STRING .. " id " .. (singeGetGameId() or "none"))
|
||
----
|
||
|
||
Tre fatti di cui una segnalazione di bug ha bisogno e che un giocatore non può
|
||
trovare altrimenti: la tua versione sulla riga sopra, la versione del motore e
|
||
l'id del gioco. `SINGE_VERSION_STRING` è una variabile globale che il motore
|
||
imposta prima che il tuo script parta. `or "none"` copre il caso in cui il
|
||
gioco non ha una voce in `games.dat`, così la riga viene stampata invece di
|
||
andare in crash su un `nil`.
|
||
|
||
[source,lua]
|
||
----
|
||
overlayPrint(2, FIRST_ROW + ROWS + 2, singeGetDataPath())
|
||
----
|
||
|
||
Dove scrive questo gioco. In un gioco impacchettato è l'unico posto in cui
|
||
viene scritto qualcosa, ed è la cartella che un giocatore cancella per ripartire
|
||
da zero. Mostrarla trasforma «dove sono i miei salvataggi» in una frase a cui
|
||
non devi mai rispondere.
|
||
|
||
Se quel percorso esce dal bordo destro dello schermo, non è rotto:
|
||
`overlayPrint` scarta i caratteri che andrebbero oltre il bordo. L'overlay
|
||
predefinito è largo sessanta celle di carattere.
|
||
|
||
[#_try_it_30]
|
||
=== Prova tu
|
||
|
||
. *Impacchettalo.* Metti questo script nella cartella del tuo gioco, esegui
|
||
`--pack` e avvia il file `.game`. Poi estrailo in una cartella vuota e leggi
|
||
l'elenco di quello che è uscito.
|
||
. *Sostituisci un file.* Accanto al file impacchettato, crea una cartella con
|
||
il suo nome senza l'estensione, e mettici dentro un file modificato. Avvia il
|
||
gioco impacchettato e guarda il tuo file sciolto vincere.
|
||
. *Crea una patch.* Cambia la versione in `1.0.3`, metti solo lo script in una
|
||
cartella `fixes`, impacchettala come `.patch` e applicala al gioco che hai
|
||
già creato. Controlla la versione sullo schermo.
|
||
. *Rompi l'impacchettatore.* Rinomina per un momento il tuo `games.dat` e prova
|
||
a impacchettare. Poi rimettilo a posto, fai puntare uno dei suoi nomi
|
||
`SCRIPT` a un file che non c'è, e riprova. Due rifiuti diversi, entrambi
|
||
prima che venga scritto qualunque cosa.
|
||
. *Scrivi i crediti veri.* Passa la cartella del gioco file per file e scrivi
|
||
una riga per ognuno che non hai fatto tu. Se non riesci a ricordare da dove
|
||
viene qualcosa, quella è la risposta alla domanda se dovresti distribuirlo.
|
||
|
||
[#_break_it_on_purpose_29]
|
||
=== Rompilo apposta
|
||
|
||
Avvia Singe una volta da *dentro* la cartella del gioco, così il motore ci
|
||
estrae i suoi file di supporto, e poi impacchettala:
|
||
|
||
----
|
||
Singe --pack MyGame MyGame.game
|
||
----
|
||
|
||
----
|
||
!!! MyGame has Framework.singe: Singe/Framework.singe
|
||
!!! MyGame has sh file: Menu.sh
|
||
----
|
||
|
||
Non viene scritto niente. Ogni riga è un file che non accetta e il perché, e
|
||
potresti riceverle nell'altro ordine o riceverne anche altre. Dentro il tuo
|
||
gioco c'è una copia della cartella di supporto del motore, e lo script launcher
|
||
che il motore ha scritto lì accanto, perché a un certo punto hai avviato Singe
|
||
da lì dentro. Un gioco non deve mai portarsi dietro né l'una né l'altro: i file
|
||
di supporto appartengono al Singe che sta usando il giocatore, qualunque sia,
|
||
non al tuo gioco, e un `Framework.singe` impacchettato verrebbe caricato al
|
||
posto del suo. Su Windows la seconda riga nomina invece `Menu.bat`.
|
||
|
||
Cancella la cartella `Singe` e `Menu.sh` (o `Menu.bat`) da dentro il gioco,
|
||
tieni la cartella del gioco
|
||
come una cartella accanto al programma Singe invece che attorno a esso, e
|
||
impacchetta di nuovo. È la stessa struttura descritta nella tredicesima
|
||
lezione, e questo errore è quello che succede quando la si perde di vista.
|
||
|
||
[#_what_you_learned_30]
|
||
=== Cosa hai imparato
|
||
|
||
* `Singe --pack folder name.game` trasforma la cartella del gioco in un solo
|
||
file, e copiare quel file accanto al programma Singe lo installa.
|
||
* Ogni nome di file dentro un gioco impacchettato viene cercato prima in una
|
||
cartella sciolta, poi nella cartella dei dati, poi nel database.
|
||
* Una cartella sciolta con il nome del file impacchettato lo sostituisce file
|
||
per file, ed è così che continui a lavorare -- e così che pubblichi una
|
||
versione rotta se ti dimentichi che è lì.
|
||
* Carica con `DIR` e scrivi solo sotto `singeGetDataPath()`, o il tuo gioco
|
||
funzionerà da sciolto e fallirà da impacchettato.
|
||
* `--patch` sostituisce dei file in un gioco pubblicato con un'unica
|
||
transazione; `--unpack` riscrive fuori tutto quanto.
|
||
* L'impacchettatore rifiuta i file del motore, i nomi in conflitto e un
|
||
`games.dat` che punta a file che non ha.
|
||
* Estrai la tua versione e leggi che cosa c'è dentro prima di mandarla da
|
||
qualunque parte.
|
||
* La grafica e i suoni di qualcun altro arrivano con delle condizioni, e
|
||
rispettarle vuol dire avere una schermata dei crediti dentro il gioco.
|
||
* Un numero di versione sale sempre e soltanto, e il suo posto è sullo schermo.
|
||
* Prova su una macchina che non è la tua, partendo senza nessuna cartella
|
||
`data`.
|
||
|
||
[#_next_time_30]
|
||
=== La prossima volta
|
||
|
||
Un solo file, installato, con i crediti e con il suo numero. L'ultima lezione
|
||
lo mette in una cassa di legno con una fessura per i gettoni e senza tastiera,
|
||
il che cambia del tuo gioco più di quanto penseresti.
|