Primo gioco con GameMaker - Space Rocks - GML Visual e GML Code
Questo è il tutorial n°1 del percorso per iniziare a sviluppare con GameMaker.
Introduzione
Se stai leggendo questo tutorial, probabilmente vorresti imparare a programmare videogiochi utilizzando GameMaker, un fantastico programma creato a tale scopo.
GameMaker ha due possibilità per creare videogiochi:
- GML Visual
- GML Code
Il GML Visual (GameMaker Language Visual) è un sistema visuale ad icone e permette di programmare senza conoscere nulla di codice.
È adatto come primo approccio se non hai mai programmato prima.
Una volta capito le logiche di base, resta comunque caldamente consigliato cominciare a muovere i primi passi anche con il GML Code.
Il GML Code è un potente e flessibile linguaggio di programmazione ed è il metodo consigliato se programmi già in altri linguaggi o comunque se vuoi imparare un linguaggio di programmazione.
In questo tutorial ci saranno entrambi i metodi e potrai decidere se seguire il GML Visual (e dopo il GML Code rifacendo il progetto) oppure direttamente il GML Code.
Questa è una rivisitazione/traduzione dell'articolo originale, che trovi qui.
Il primo gioco che creeremo è Space Rocks (un clone di Asteroids), un gioco dove comandi una navicella spaziale e devi sparare agli asteroidi prima di venir colpito.
Partiremo con questo semplice progetto ma con Game Maker potrai sviluppare moltissimi generi di videogiochi, anche in 3D.
Iniziamo!
Dopo aver scaricato ed installato GameMaker, potresti voler mettere la lingua italiana; in tal caso vai in:
File > Preferenze > Impostazioni generali > Linguaggio IDE
Apri un nuovo progetto cliccando sul tasto "Nuovo"
Visto che perlomeno per questo primo videogioco, utilizzeremo un tutorial ufficiale di GameMaker, invece del tasto "Nuovo vuoto", clicca sul template "Space Rocks".
Scrivi il nome del progetto e dai l'ok.
Per prima cosa cambia la piattaforma di destinazione, in alto a destra clicca su GX.games (Giochi per Opera GX) e nella schermata che si apre clicca o su Windows o su macOS (a seconda di quello che hai).
Sulla destra, nel Browser delle risorse, aggiungeremo tutte le risorse necessarie (oggetti, immagini, audio...); noterai che esiste già una stanza creata per te da GameMaker. Almeno una stanza è obbligatorio che ci sia in quanto gli oggetti che animano il videogioco dovranno necessariamente esistere all'interno delle stanze.
Essendo il template di Space Rocks troverai nella cartella Sprite tutte le immagini che andrai ad utilizzare nel videogioco (se vuoi puoi anche modificarle nell'apposito editor). Doppio click sull'immagine e clicca sul tasto "Modifica immagine".
Fai partire il gioco cliccando sull'apposito pulsante (o premendo F5) e si aprirà una schermata nera... è la nostra stanza completamente vuota. Ora chiudila.
Da questo momento utilizzerò le immagini del tutorial ufficiale, che avrà l'interfaccia in inglese; è bene prendere confidenza anche con i nomi in inglese in quanto è in questa lingua che si troverà la maggior parte dei tutorial.
Il prossimo tutorial avrà l'interfaccia in italiano.
Come utilizzare il browser delle risorse
Nel Browser delle risorse creeremo alcuni oggetti.
Un oggetto è il modo in cui dai vita a un'immagine, programmandola per muoversi, sparare o fare qualsiasi cosa ti serva.
La tua navicella spaziale, le rocce e persino i proiettili che spari vengono creati come oggetti. Li inseriremo nel gruppo "Object" nel Browser risorse, che al momento è vuoto.
Fai click con il tasto destro del mouse sul gruppo "Object" e seleziona "Crea > Oggetto". Cambia il suo nome da "Object1" a "obj_player"
Premi F2 per rinominare l'oggetto selezionato, oppure fai click destro sull'oggetto e seleziona la voce per rinominare.
Quando attribuisci un nome ad una risorsa metti sempre un prefisso od un suffisso che ti faccia capire in maniera univoca di che tipo di risorsa si tratta (Oggetto, Sprite, Suono...). Non utilizzare spazi ma "_".
Come modificare un oggetto
L'oggetto appena creato ha un editor. Qui puoi cambiarne le proprietà e programmarlo, cosa che faremo molto presto.
Solitamente vorrai vedere un oggetto, di conseguenza dovrai abbinargli uno sprite.
Fai clic su "No Sprite" e dalla cartella "Sprites", seleziona spr_player.
Ora abbiamo bisogno di altri tre oggetti che creerai utilizzando la stessa procedura che hai appena fatto.
- obj_bullet: questo è il proiettile che la tua navicella sparerà.
- obj_rock: questa è la roccia che distruggerai.
Imposta lo sprite su spr_rock_big, poiché ogni roccia inizierà grande e si dividerà in due più piccole una volta colpita. - obj_game: questo è un oggetto "silenzioso" che gestirà il tuo gioco.
Non ha bisogno di uno sprite.
Questi sono tutti gli oggetti di cui hai bisogno! Mettiamoli ora all'interno di un livello.
Come ridimensionare una room
Fai doppio click sulla room. Si aprirà il "Room Editor", dove costruirai il tuo livello.
Prima di fare qualsiasi cosa, ridimensiona la room per renderla un quadrato 1000x1000.
Guarda nell'angolo in basso a sinistra della finestra: vedrai una finestra "Inspector".
Qui, imposta la larghezza e l'altezza della stanza su 1000. Puoi anche usare una dimensione diversa.
Se non vedi queste opzioni, vai nel tuo Asset Browser e fai clic su Room1 . Dovrebbero essere visibili mentre la stanza è selezionata.
Come posizionare oggetti in una room
Guarda il pannello di sinistra nel Room Editor: ci sono due livelli creati per impostazione predefinita, "Instances" e "Background".
- Instances: questo è un livello di istanza. I tuoi oggetti vanno qui.
- Background: questo è un livello di sfondo. Cambia il colore di sfondo o applica un'immagine.
Fai clic sul livello "Instances" per selezionarlo. Ora inseriremo gli oggetti.
Dal browser delle risorse, trascina obj_player e posizionalo nella stanza. Alternativamente puoi inserirlo selezionando obj_player e cliccando con il tasto sinistro del mouse mentre tieni premuto il tasto Alt.
La tua navicella spaziale è ora nella room, come "istanza" - puoi posizionare più "istanze" di qualsiasi oggetto nella room!
Fallo con le rocce: inserisci obj_rock nella room più volte, finché non avrai circa sei istanze.
Il palcoscenico è pronto per lo spettacolo. Dobbiamo solo insegnare agli attori i loro ruoli.
Come usare gli eventi
Se esegui il gioco in questo momento, sarà tutto immobile.
I tuoi oggetti sono lì, la tua stanza è lì, ma niente è programmato per muoversi o fare qualcosa.
Lavoriamo su questo.
Premendo il tasto "freccia su", vogliamo spingere in avanti la navicella del giocatore.
Nel Browser delle risorse, fai doppio clic su obj_player.
Guarda l'editor dell'oggetto, in particolare la finestra "Events".
Fai click su "Add event" e seleziona "Step".
Ti potrebbe essere chiesto di scegliere tra GML Code e GML Visual.
Scegli GML Code se hai già programmato in precedenza o GML Visual se sei nuovo.
Fai la tua scelta e abilita "Non chiedere più per questo progetto".
Cos'è l'evento step?
Dopo aver effettuato la tua scelta sopra, vedrai aprirsi la finestra per l'evento Step.
L'immagine sopra è la finestra GML Code per l'evento Step.
Un oggetto ha molti eventi. Ogni evento ha il suo momento unico in cui viene eseguito.
Ad esempio, ti lavi i denti al mattino. Quindi respiri praticamente tutto il giorno, ogni secondo.
Se tu fossi un oggetto in GameMaker, ti laveresti i denti nell'evento "Create" e respireresti nell'evento "Step".
Questo perché l'evento "Create" è il primo evento che viene eseguito per un'istanza e viene eseguito solo una volta. L'evento "Step" viene quindi eseguito continuamente in ogni singolo frame mentre esiste l'istanza (solitamente 60 volte al secondo).
Programmeremo questo evento "Step" per muovere la navicella, poiché è una cosa continua che deve accadere, simile al respiro.
Come programmare un evento
A breve vedremo alcune cose da aggiungere all'evento “Step”. Il modo in cui li aggiungi differisce in GML Code e GML Visual.
Se utilizzi GML Visual, cerca le azioni pertinenti nella casella degli strumenti e trascinale nell'area dell'evento.
Se stai usando il GML Code, scrivi semplicemente il tuo codice nella finestra dell'evento.
Come aggiungere movimento
Ok, dobbiamo spostare la navicella spaziale.
Nel tuo evento Step, aggiungi il seguente codice/azioni:
Qui stiamo controllando se il tasto "freccia su" è tenuto premuto.
Se tieni premuto il tasto "freccia su", questo aggiunge movimento all'istanza che quindi si sposta in una direzione particolare.
In GML Visual, la seconda azione è "attaccata" alla prima azione. La seconda azione verrà eseguita solo se la condizione della prima azione è vera.
Per allegare "Add Motion" a "If Key Down", rilascialo sul bordo destro dell'azione condizionale, come mostrato sopra.
Puoi allegare azioni solo ad azioni "condizionali" verdi.
Quindi, stiamo aggiungendo movimento in una direzione. Che direzione è?
Quella direzione è "image_angle" dell'istanza, che è dove è rivolta la navicella.
La quantità di movimento che stiamo aggiungendo è 0,1. Puoi cambiarle questo valore per rendere la tua navicella più veloce o più lenta.
Esegui il gioco ed una volta avviato premi il tasto "freccia su".
La navicella si sposta a destra, poiché è l'angolo predefinito di un'istanza.
Però non gira...
Come ruotare un'istanza
Per ruotare la navicella, dobbiamo modificare il valore di "image_angle". Questa variabile memorizza l'angolo di rotazione dell'istanza.
Per ruotare l'istanza, devi semplicemente cambiare questa variabile.
Nello stesso evento "Step", aggiungi questo:
La logica qui è semplice:
- Se si tiene premuto il tasto "freccia sinistra", si sottrae 4 da "image_angle"
- Se si tiene premuto il tasto "freccia destra", si aggiunge 4 da "image_angle"
Esegui il gioco e ora puoi muoverti e girarti!
Questo è fantastico, ma c'è un piccolo problema.
Se la tua navicella esce dalla room, molto probabilmente sarà persa per sempre.
Per risolvere questo problema, creeremo un movimento vincolato per la navicella intorno alla room: ad esempio se esce dall'alto, ritorna dal basso.
Movimento vincolato di un'istanza
Nello stesso evento "Step", aggiungi questo:
Assicurati di aggiungerlo al di fuori di qualsiasi condizione.
Questo fa muovere la navicella in maniera particolare, se esce dal lato destro della room, ricompare da sinistra e così via. Questo è abilitato sia sul lato orizzontale che sul verticale e il margine è impostato su 0.
Il margine controlla fino a che punto l'istanza deve spingersi fuori dalla stanza prima che venga eseguito questo movimento vincolato. Non lo stiamo usando per ora, ma tornerà utile in seguito.
Il movimento della navicella è terminato! Ora puoi muoverti, girare senza rischiare di uscire la room. Avvia il gioco e provalo.
Come creare un'istanza
È arrivata l'ora di sparare!
In precedenza abbiamo creato un oggetto chiamato obj_bullet. Per sparare, creeremo una nuova istanza di questo oggetto nella posizione della navicella.
Il proiettile si muoverà velocemente, nella stessa direzione della navicella.
Quando il proiettile sarà fuori dalla room, lo distruggeremo. Ciò impedirà una perdita di memoria che si verificherebbe se tutti i proiettili sparati continuassero ad esistere per sempre.
Nell'evento Step di obj_player, aggiungi questo:
Questo controlla se il pulsante sinistro del mouse è "premuto". Questo è diverso dal controllare se è "tenuto premuto", in quanto controlla solo se hai appena premuto il pulsante.
Se premi il pulsante sinistro del mouse, crea un'istanza di obj_bullet. Oltre all'oggetto da creare, sono necessari altri tre parametri:
- x: la posizione x (orizzontale) in cui verrà creata l'istanza
- y: la posizione y (verticale) in cui verrà creata l'istanza
- layer: il layer della stanza in cui verrà creata l'istanza
Per x e y, stiamo passando le variabili x e y del giocatore, quindi il proiettile viene creato nella stessa posizione. Stiamo impostando il livello su "Instances".
Se dovessi preferire ad esempio il tasto spazio per sparare i proiettili, dovresti già aver capito che modifiche fare. Potresti utilizzare keyboard_check_pressed(vk_space) o la relativa icona. Personalmente lo trovo molto più comodo.
Avvia il gioco. Ora puoi sparare! Il fatto è che... i proiettili non si muovono affatto.
NB. se crei i proiettili con il click del mouse, assicurati di avere il cursore dentro la schermata di gioco, altrimenti la finestra perderà il focus.
Come spostare costantemente un'istanza
Per il proiettile, imposteremo la sua velocità una volta creato. Dopodiché, continuerà a muoversi per sempre finché non sarà fuori dalla room.
Fai doppio clic su obj_bullet. Nella finestra Eventi, aggiungi l'evento "Create".
Questo evento è il primo a essere eseguito in un'istanza e viene eseguito solo una volta. Ecco perché si chiama "Create", perché viene eseguito non appena viene creata l'istanza.
Qui aggiungi questo:
Diciamo al proiettile di muoversi ad una velocità di 10, ovvero 10 pixel per fotogramma. Cambia questo valore per rendere il tuo proiettile più veloce o più lento.
Quindi questa è la velocità con cui si muove il tuo proiettile, ma dove si muove?
Questo è ciò che controlla la direction. La stiamo impostando su obj_player.image_angle - il che significa che stiamo estraendo image_angle da obj_player - dicendo al proiettile di muoversi dove è rivolta la navicella.
Come distruggere un'istanza
I nostri proiettili ora dovrebbero muoversi, ma come detto prima, dovrebbero essere distrutti quando usciranno dalla room.
Nella finestra Eventi, fai click su "Add event". Passa il mouse su "Other" e seleziona "Outside room".
Questo evento verrà eseguito non appena l'istanza sarà completamente uscita dall'area della room. Qui aggiungi questo:
Qui l'istanza è distrutta, quindi non esiste più nella room.
Naturalmente, l'oggetto stesso continua ad esistere nel Browser delle risorse e da esso è possibile creare nuove istanze in qualsiasi momento.
Avvia il gioco. Ora possiamo sparare!
Come muovere un'istanza in una direzione casuale
Tutte le rocce dovrebbero muoversi in direzioni casuali, ma a bassa velocità, quindi non dovrebbero essere troppo difficili da colpire.
Fai doppio click su obj_rock. Aggiungi l'evento Create e aggiungi questo:
Per prima cosa impostiamo la velocità su 1. Questo valore è molto basso rispetto alla velocità del proiettile di 10.
Quindi impostiamo la direction su random(360). Questo può essere qualsiasi numero casuale compreso tra 0 e 360 (un cerchio completo).
Ciò imposta la direzione in cui si muove la roccia, ma non ruota lo sprite, quindi applichiamo anche un numero casuale ad image_angle.
Avvia il gioco.
Le rocce ora si stanno muovendo! Ma ci sono due problemi:
- quando una roccia esce dalla room, andrà persa e non tornerà più
- le rocce sembrano molto immobili e noiose
Movimento vincolato delle rocce
Nello stesso oggetto obj_rock, aggiungi l'evento Step e aggiungici questo:
Abilitiamo il movimento vincolato per la roccia, con un margine di 100. Ciò significa che una roccia passerà da un lato all'altro solo quando si troverà a più di 100 pixel fuori dalla room.
Se avessimo usato un margine di 0, vedresti la roccia saltare da un punto all'altro sullo schermo, ma ora questo succederà all'esterno.
Infine, aggiungiamo 1 a image_angle, quindi la roccia continua a ruotare costantemente. Sembra un po' più realistico.
Avvia il gioco.
Ora anche le rocce passano da un parte all'altra della room e ruotano, dando al gioco una sensazione più spaziale.
Come entrare in collisione
Distruggiamo le rocce?
È la battaglia che stavamo aspettando: proiettili contro rocce!
Quando si scontrano, vogliamo distruggere sia il proiettile che la roccia.
Ormai, probabilmente sei a conoscenza del fatto che un'istanza può essere distrutta con instance_destroy() (o "Destroy Instance"). Ma non è tutto.
Quando una roccia viene distrutta, dovrebbe:
- creare un effetto particellare
- se è una roccia grande, diventare una roccia piccola
- se è una roccia piccola, "reincarnarsi" in una roccia grande
In questo modo, il gioco non esaurisce mai le rocce: quando distruggi una roccia piccola, diventa una roccia grande e viene posizionata fuori dallo schermo in modo che possa entrare di nuovo nella room.
Quando un'istanza ne tocca un'altra, si parla di "collisione".
Programmiamo la collisione tra un proiettile ed una roccia. Lo faremo dal punto di vista della roccia, poiché è l'oggetto che ne risentirà maggiormente.
Ciò significa che stiamo lavorando in obj_rock, non nell'oggetto proiettile.
Apri obj_rock. Fai clic su "Add event", vai in "Collision" e seleziona obj_bullet.
Questo evento verrà eseguito quando una roccia si scontra con un proiettile.
Qui aggiungi questo:
Questo fa tre cose:
- distrugge l'istanza "other", che è il proiettile.
In GML Visual, utilizza la freccia del menu a discesa per assegnare questa azione all'istanza "Other", in modo che il proiettile venga distrutto. - crea un effetto di esplosione nella posizione della roccia. La sua taglia è media (1) ed il suo colore è bianco.
- imposta la direzione su un valore casuale. Quando la roccia alla fine diventerà una roccia piccola, o si rigenererà, si muoverà in una nuova direzione.
Avvia il gioco.
L'evento non è ancora finito, ma puoi vedere che la nostra logica funziona. Puoi sparare ad una roccia e cambiarne la direzione. Viene creato anche un effetto particellare.
Come utilizzare le condizioni di confronto
Ora programmeremo una roccia grande per trasformarsi in una roccia piccola ed una roccia piccola per rigenerarsi.
Per controllare il numero di rocce nella room, rigenereremo una roccia solo se ci sono meno di 12 rocce nella room. Questo sarà fatto utilizzando una "condizione di confronto".
Vogliamo utilizzare le condizioni per porre domande e fare questo:
Nello stesso evento di collisione, aggiungi questo:
È un sacco di roba, quindi analizziamola blocco per blocco.
- Il primo blocco controlla se la roccia è grande, controllando il suo sprite.
Se è grande, viene trasformata in una roccia piccola e l'istanza viene quindi copiata in modo da ottenere due rocce piccole. - Il secondo blocco inizia con "else", quindi viene eseguito solo se la condizione precedente è falsa, ovvero se la roccia è piccola.
Quindi controlla se ci sono meno di 12 rocce nella room e, se è vero, trasforma la roccia in una roccia grande.
Imposta anche la posizione x (orizzontale) della roccia a -100 in modo che la roccia esca dalla room e possa rientrare. - Il blocco finale funziona solo se entrambe le condizioni precedenti sono false, il che significa che se la roccia è piccola e ci sono già 12 o più rocce nella stanza, allora la roccia viene distrutta.
Esegui il gioco!
Ora puoi distruggere le rocce, che si rigenereranno all'infinito.
Puoi muoverti e sparare quanto vuoi ma non ha senso giocare se non c'è un pericolo.
Quando la tua navicella va a sbattere contro una roccia, dovrebbe esplodere immediatamente e il gioco dovrebbe ricominciare dopo due secondi.
Per riavviare il gioco dopo due secondi dalla sconfitta del giocatore, useremo gli "Alarm".
Come usare gli allarmi
Vai su obj_player e aggiungi un evento Collision con obj_rock.
In questo evento, programmeremo cosa succede quando il giocatore si scontra con una roccia:
Qui stiamo facendo tre cose:
- creando un effetto “fuoco d'artificio”, con una dimensione media e colore bianco
- distruggendo l'istanza del giocatore
- impostando l'allarme 0 in obj_game su 120
Aspetta... cosa significa impostare l'allarme 0 in obj_game su 120?
Come funzionano gli allarmi?
Hai presente quando metti la sveglia alle 7 del mattino e poi vai a dormire? La sveglia suona esattamente alle 7 del mattino.
GameMaker ha anche gli allarmi. È possibile impostare un evento di allarme in modo che venga eseguito dopo un certo numero di frame. Dopo che è trascorso quel numero di frame, quell'evento verrà eseguito.
Nel codice sopra, stiamo dicendo a obj_game di eseguire il suo primo allarme (Alarm 0) dopo 120 frame (due secondi). In tal caso, riavvieremo la room.
Perché non abbiamo creato l'allarme nell'oggetto giocatore?
Perché stiamo distruggendo l'istanza del giocatore. Non puoi eseguire allarmi in un'istanza che non esiste.
Come riavviare una room
Apri obj_game. Fare clic su "Add event" e aggiungi l'evento "Alarm 0".
Qui aggiungi questo:
Questo riavvierà semplicemente la room, così potrai giocare di nuovo.
Tuttavia, affinché obj_game funzioni, deve essere nella nostra room. In questo momento non lo è!
Apri Room1 dal Browser delle risorse. Seleziona il livello "Instances" e, dal Browser delle risorse, trascina obj_game nella room.
Dal momento che non ha uno sprite, apparirà con un punto interrogativo. Puoi posizionarlo ovunque: la sua posizione non ha importanza, l'importante è che esista.
Avvia il gioco.
Ora puoi colpire una roccia e perdere! Due secondi dopo puoi giocare di nuovo.
Come aggiungere un punteggio
Hai un videogioco giocabile ora. Ma come mostrerai ai tuoi amici quanto sei bravo senza un contatore di punteggio?
Creeremo la nostra variabile per memorizzare il punteggio. Quella variabile apparirà sullo schermo. Quando una roccia viene distrutta, aggiungeremo 50 a quella variabile, aumentando il punteggio del giocatore.
Apri obj_game e aggiungi l'evento Create. Aggiungici questo:
Abbiamo creato una variabile chiamata "points" e impostato il suo valore su 0.
Potresti chiamarla come preferisci (ovviamente senza usare spazi ma "_").
Prima di programmare come cambia il punteggio, disegniamolo sullo schermo.
Aggiungi l'evento "Draw GUI" all'oggetto obj_game. Aggiungici questo:
L'evento "Draw GUI" esegue ogni fotogramma. Qui puoi disegnare qualsiasi cosa sullo schermo e apparirà sopra il gioco.
Stiamo disegnando il valore del punteggio alle coordinate x = 10, y = 10 della schermata di gioco. Lo vedrai se esegui il gioco:
Comunque è fermo a 0. Facciamolo aumentare quando distruggi una roccia.
Apri obj_rock e apri il suo evento Collision esistente con obj_bullet.
Aggiungi questo lì, al di fuori di qualsiasi condizione:
Qui stiamo aggiungendo 50 alla variabile points in obj_game.
Abbiamo creato la variabile points in obj_game, ma stiamo provando a modificarla nell'oggetto obj_rock, quindi dobbiamo prima rivolgerci al proprietario della variabile. Ecco perché scriviamo "obj_game.points".
Esegui il gioco e vedrai aumentare il tuo punteggio mentre spari alle rocce!
Il tuo gioco è finito!
Se vuoi puoi anche pubblicare il tuo gioco su Opera GX: clicca questo link per sapere come fare.
Se vuoi spulciare il manuale, c'è la versione inglese qui e la versione italiana qui.
ISCRIVITI al canale DISCORD di GameMaker Italia per avere supporto, imparare a programmare videogiochi e partecipare alla Competizione annuale!
Ci vediamo al prossimo tutorial!
BUON DIVERTIMENTO!