
Whac-a-block
Il gioco che stai per creare con Minecraft si chiama “Whac-a-Block”, e si ispira al famoso videogioco “Whac-a-Mole”. L’obiettivo è quello di colpire con la spada i blocchi di luminite (ndr: chiamiamo così la pietra che si è illuminata), per farli ritornare normali blocchi di pietra.
Guadagnerai punti per ogni blocco che fai ritornare e il gioco si concluderà quando i blocchi saranno tutti di luminite.
Dividiamo il progetto in 5 parti
- Creare il programma: lanceremo Minecraft Python e ci assicureremo che tutto funzioni a
dovere. - Creare l’interfaccia del gioco: scriveremo il codice che farà comparire il gioco di fronte al
giocatore di Minecraft. - Creare i blocchi di luminite: scriveremo le funzioni che trasformano in maniera casuale
alcuni blocchi di pietra in luminite. - Colpire i blocchi: faremo in modo che i blocchi ritornino di pietra quando vengono colpiti.
- Game over: quanti punti hai fatto?
Creare il programma
- Lancia Minecraft e crea un mondo.
- Dal menù di avvio, vai alla sezione Coding e seleziona Geany dal menù a tendina.
- Dalla finestra di Geany crea un nuovo programma selezionando File/New Window e salvalo con File/Save.
- Importa tutte le librerie di Python di cui avrai bisogno:
import mcpi.minecraft as minecraft from mcpi import block import random from time import sleep
Il modulo
mcpi.minecraft
serve per interagire il programma che scriviamo con Minecraft Pi
block
serve per richiamare i blocchi di Minecraft usando i loro nomi
random
serve per generare numeri in maniera casuale
sleep
serve per inserire ritardi nell’esecuzione del programma - Crea un collegamento a Minecraft: Pi Edition e pubblica un messaggio nella finestra di chat di Minecraft:
mc = Minecraft.create() mc.postToChat("Minecraft Whac-a-Block”)
- Esegui il programma.
Non farà molto, ma, se tutto funziona a dovere, leggerai la scritta Minecraft Whac-a-Block nella finestra di chat di Minecraft.

Creare l’interfaccia del gioco
Creiamo ora l’interfaccia del nostro gioco: un muro 3×3 di blocchi di pietra, che si trasformano in maniera casuale in luminite.
Il muro dovrà apparire di fronte al giocatore, e, quindi, dobbiamo prima di tutto determinare la sua posizione:
x, y, z = mc.player.getTilePos()
Usa quindi questa posizione con la funzione setBlocks()
per creare il muro di pietra:
mc.setBlocks(x - 1, y, z + 3, x + 1, y + 2, z + 3, block.STONE.id)
Per avvisare il giocatore dell’inizio del gioco, pubblica un paio di messaggi nella chat e inserisci un ritardo nel programma usando la funzione time.sleep()
:
mc.postToChat("Get ready ...")
sleep(2)
mc.postToChat(“Go")
Riassumendo, il programma scritto fino adesso è:
import mcpi.minecraft as minecraft
from mcpi import block
import random
from time import sleep
mc = Minecraft.create()
mc.postToChat("Minecraft Whac-a-Block”)
x, y, z = mc.player.getTilePos()
mc.setBlocks(x - 1, y, z + 3, x + 1, y + 2, z + 3, block.STONE.id)
mc.postToChat("Get ready ...")
sleep(2)
mc.postToChat(“Go")
Esegui il programma e vedi cosa succede.
Dovresti vedere l’interfaccia del gioco direttamente di fronte al giocatore, e i messaggi “Get ready …” e “Go” nella chat.
Creare i blocchi di luminite
Adesso dobbiamo scrivere il codice per trasformare in maniera casuale i blocchi di pietra in luminite.
Per farlo useremo la funzione random.randint(start, end)
per selezionare in maniera casuale uno dei blocchi del muro.
Definiamo, prima di tutto, la variabile numero_blocchi_luminite
per tenere conto del numero di blocchi che si sono già illuminati (cioè che sono stati trasformati in luminite), e la variabile punti
per tenere conto del punteggio raggiunto dal giocatore.
Poiché siamo all’inizio del gioco, assegnamo a entrambe il valore 0
:
numero_blocchi_luminite = 0
punti = 0
Poiché il gioco finisce quando tutti i blocchi saranno illuminati, programma deve ripetersi in loop fino a quel momento.
Creiamo, quindi, un loop while
che esegue le istruzioni finché numero_blocchi_luminite
assume valore 9
(cioè finché tutti i blocchi sono trasformati in luminite).
Inseriamo anche un ritardo di 0.5 secondi nel programma; se non lo facessimo, sarebbe così veloce, che non il giocatore non riuscirebbe a colpire nessun blocco!
while numero_blocchi_luminite < 9:
sleep(0.5)
D'ora in avanti, daremo per scontato che il codice che scriviamo sia interno al loop while
.
Dobbiamo fare in modo che un blocco a caso del nostro muro di pietra venga trasformato in luminite.
Non è così semplice come potrebbe sembrare: infatti, cosa succederebbe se il blocco scelto fosse già stato trasformato in luminite? Il nostro programma deve tenere in considerazione questa eventualità.
Il metodo che useremo è invece piuttosto semplice: il programma sceglierà una posizione in maniera casuale, controllerà che il blocco in quella posizione sia di pietra, e nel caso non lo fosse (e cioè fosse di luminite), sceglierà una nuova posizione in maniera casuale... e così via fino a che non troverà un blocco di pietra non ancora trasformato.
Creiamo la variabile trasformato_in_luminite
e le assegnamoli valore False
.
Quindi, creiamo un loop while
che continuerà fino a che trasformato_in_luminite
non assume il valore True
.
Dovremo anche aumentare di 1
il valore di numero_blocchi_luminite
per tenere conto di ogni nuovo blocco illuminato:
numero_blocchi_luminite = numero_blocchi_luminite + 1
trasformato_in_luminite = False
while not trasformato_in_luminite:
Quando un blocco di pietra viene trasformato in luminite, a trasformato_in_luminite
verrà assegnato il valore True
e il loop terminerà.
All’interno del loop usiamo la funzione random.randint(start, end)
per generare casualmente una posizione x (compresa fra -1 e 1) e una posizione y ( compresa fra 0 e 2).
xPos = x + random.randint(-1, 1)
yPos = x + random.randint(0, 2)
zPos = z + 3
Usiamo la funzione getBlock(x, y, z)
e if
per verificare che il blocco in quella posizione sia STONE
.
Nel caso lo sia, trasformiamololo in Luminite con setBlock(x, y, z, Id)
e rendiamo trasformato_in_luminite = True
.
In caso contrario, il programma dovrà tornare all'inizio del loop e genererà un'altra posizione casuale:
if mc.getBlock(xPos, yPos, zPos) == block.STONE.id:
mc.setBlock(xPos, yPos, zPos, block.GLOWSTONE_BLOCK.id)
trasformato_in_luminite = True
Nota: Al posto di usare le ID dei blocchi (ad es. pietra = 1
, luminite = 89
), puoi usare il modulo Block
, che contiene tutte le ID e tutti i nomi dei blocchi (ad es. block.STONE.id
).
Riassumendo, il programma scritto fino adesso è:
import mcpi.minecraft as minecraft
from mcpi import block
import random
from time import sleep
mc = Minecraft.create()
mc.postToChat("Minecraft Whac-a-Block”)
x, y, z = mc.player.getTilePos()
mc.setBlocks(x - 1, y, z + 3, x + 1, y + 2, z + 3, block.STONE.id)
mc.postToChat("Get ready ...")
sleep(2)
mc.postToChat(“Go")
numero_blocchi_luminite = 0
punti = 0
while numero_blocchi_luminite < 9:
sleep(0.2)
numero_blocchi_luminite = numero_blocchi_luminite + 1
trasformato_in_luminite = False
while not trasformato_in_luminite:
xPos = x + random.randint(-1, 1)
yPos = x + random.randint(0, 2)
zPos = z + 3
if mc.getBlock(xPos, yPos, zPos) == block.STONE.id:
mc.setBlock(xPos, yPos, zPos, block.GLOWSTONE_BLOCK.id)
trasformato_in_luminite = True
Lancia il programma.
Dovrebbe apparire l'interfaccia del gioco, i blocchi si dovrebbero trasformare uno dopo l'altro in luminite, e il programma dovrebbe terminare quando sono stati trasformati tutti.
Colpire i blocchi
Il giocatore potrà colpire i blocchi facendo clic con il tasto destro del mouse quando ha in mano la spada.
L'API di Minecraft ha funzioni che ti permettono di determinare quali blocchi sono stati colpiti.
Usando la funzione events.pollBlockHits()
puoi ottenere la lista degli eventi accaduti dall'ultima volta in cui l'hai richiamata. Fra questi c'è anche la lista dei blocchi che sono stati colpiti.
Possiamo usare questa funzione per determinare la posizione del blocco colpito, e quindi la funzione getBlock(x, y, z)
per verificare se sia di luminite. In caso affermativo, useremo la funzione setBlock(x, y, z, blockId)
per farlo ritornare di pietra, e diminuiremo il numero dei blocchi illuminati e aumentaremo il punteggio del giocatore.
Nel loop while
, inserisci il codice seguente per scandire la lista di eventi:
for hitBlock in mc.events.pollBlockHits():
Nota: hitBlock()
contiene gli eventi che sono accaduti. Ci sono molte informazioni, fra le quali la lista dei blocchi colpiti, quale faccia è stata colpita e chi li ha colpiti. Puoi vedere queste informazioni in Python con lil comando print hitBlock()
.
Usiamo getBlock(x, y, z)
con hitBlock()
e if
per determinare se il blocco colpito è di luminite.
Nel caso lo sia, usiamo setBlock(x, y, z, blockId)
per trasformarlo in pietra prima di ridurre il valore di numero_blocchi_illuminati
e aumentare di 1
il punteggio del giocatore punti
:
if mc.getBlock(hitBlock.x, hitBlock.y, hitBlock.z) == block.GLOWSTONE_BLOCK.id:
mc.setBlock(hitBlock.x, hitBlock.y, hitBlock.z, block.STONE.id)
numero_blocchi_illuminati = numero_blocchi_illuminati - 1
punti = punti + 1
Esegui il programma.
Dovrebbe apparire il gioco e, questa volta, quando i blocchi illuminati dovrebbero spegnersi se li colpisci con la spada facendo clic con il tasto destro del mouse.
Game over
Devi ora far sapere al giocatore quando il gioco è finito e quanti punti ha ottenuto.
L’ultimissima riga di codice del programma sarà:
mc.postToChat("Game Over - punti = " + str(punti))
Il programma completo è:
import mcpi.minecraft as minecraft
from mcpi import block
import random
from time import sleep
mc = Minecraft.create()
mc.postToChat("Minecraft Whac-a-Block”)
x, y, z = mc.player.getTilePos()
mc.setBlocks(x - 1, y, z + 3, x + 1, y + 2, z + 3, block.STONE.id)
mc.postToChat("Get ready ...")
sleep(2)
mc.postToChat(“Go")
numero_blocchi_luminite = 0
punti = 0
while numero_blocchi_luminite < 9:
sleep(0.2)
for hitBlock in mc.events.pollBlockHits():
if mc.getBlock(hitBlock.x, hitBlock.y, hitBlock.z) == block.GLOWSTONE_BLOCK.id:
mc.setBlock(hitBlock.x, hitBlock.y, hitBlock.z, block.STONE.id)
numero_blocchi_illuminati = numero_blocchi_illuminati - 1
punti = punti + 1
numero_blocchi_luminite = numero_blocchi_luminite + 1
trasformato_in_luminite = False
while not trasformato_in_luminite:
xPos = x + random.randint(-1, 1)
yPos = x + random.randint(0, 2)
zPos = z + 3
if mc.getBlock(xPos, yPos, zPos) == block.STONE.id:
mc.setBlock(xPos, yPos, zPos, block.GLOWSTONE_BLOCK.id)
trasformato_in_luminite = True
mc.postToChat("Game Over - punti = " + str(punti))
E adesso?
Al momento il gioco che hai costruito è piuttosto semplice, ma, partendo da questa base, puoi fare molte cose in più.
Ecco alcune idee:

This learning resource is provided for free by the Raspberry Pi Foundation under a Creative Commons licence.
Find more at raspberrypi.org/resources and github.com/raspberrypilearning.