Python – Property e Manager

In questo secondo tutorial andrò a spiegare come salvare la Property di un’oggetto e come usare un’oggetto per salvare i dati di tutti gli altri oggetti. Per questo tutorial hai bisogno del file dell’articolo precedente che puoi scaricare qua QUA. Iniziamo.

Property

Aggiungi una Property di tipo Int e rinominala come meglio credi, io l’ho chiamata count (il nome non è importante ai fini del tutorial). Adesso fai in modo che la Property cambi di valore, usa un Sensor Keyboard (con un tasto qualsiasi), un’Actuator Property con l’opzione Add e un valore qualsiasi, io ho inserito 1, in modo che ogni volta che premo il tasto la Property count aumenta di 1 il suo valore. Fai in modo di mostrare in debug la Property, se non sai come fare leggi la scheda relativa alle Properties.

Adesso vediamo il codice per connettere una Property ad uno script

count = own['count']

Come sempre è consigliabile assegnare il codice ad una variabile in modo da non doverlo scrivere se dovesse ripetersi nello script; quindi alla variabile count assegno il valore own che è l’oggetto proprietario dello script e [‘count’] che è la Property, tra le parentesi quadre e i singoli apici va inserito il nome che si da alla Property, quindi se l’hai chiamata in un’altro modo devi inserire quello che hai scelto come nome. Questo codice voglio che sia reperibile in tutto lo script, anche se per questo tutorial non è necessario, e va inserito tra le variabili globali, dopo le variabili cont e own.

Adesso voglio che sia salvata nel globalDict, per fare questo semplicemente aggiungo la Property alla lista dei dati nella riga del globalDict, così

bge.logic.globalDict['posCubo'] = [ posX, posY, posZ, count]

A questo punto la Property fa parte del salvataggio, salva il file blend, fai partire il motore di gioco e premi più volte il tasto che hai scelto per incrementare la Property, poi premi S per salvare il valore.

La Property viene estrapolata automaticamente insieme ai dati precedenti e inserita nella variabile cuboPos che è una lista (array) dei valori nel globalDict. Per riassegnare il valore salvato alla Property attuale, che essa sia zero o un valore qualsiasi verrà sovrascritto una volta premuto il tasto L. Scrivi il seguente codice in fondo alla def load

own['count'] = cuboPos[3]

Non ho usato la variabile dichiarata nelle variabili globali perché il dato salvato deve essere aggiunto direttamente alla fonte principale, il codice quindi dice che alla Property [‘count’] del proprietario own va assegnato il valore con indice [3] della lista (array) cuboPos precedentemente caricata. Quindi fai partire il motore di gioco e premi L, se la Property non dovesse cambiare nel valore che hai visto a schermo prima di salvare rivedi questi semplici passi, se cambia hai fatto tutto correttamente. Questo è solo un’esempio ma puoi fare altre prove con altri tipi di Property, in questo modo si possono salvare svariati tipi di dati dall’energia al punteggio, ai danni di un oggetto, del player o di un nemico, sei sempre tu a decidere cosa salvare.

Il Manager

In una scena, o livello di gioco, gli oggetti sono tanti tantissimi, statici, animati, che fanno parte della fisica del gioco ecc ecc. Quindi come puoi ben intuire aggiungere uno script per ogni oggetto non è una cosa semplice e richiede tempo (a meno che non hai già pianificato tutto e quindi sei consapevole di volerlo fare), quindi è buono avere un’oggetto solo che salva i dati di tutti gli altri oggetti. Il player di solito è l’oggetto che ha più Mattoni o codice e più interazione, quindi viene escluso in partenza, la Camera può fare da Manager ma è sconsigliato perché potrebbe anch’essa avere diverse parti di logica, si può benissimo usare ma sarebbe meglio evitare. Allora la scelta cade su un’oggetto che non ha nessuna forma ne interazione con la scena di gioco, una Empty, quindi aggiungine una e rinominala manager. Per evitare di inserire tutti i Mattoni e rifare i vari passaggi, fai un copy Logic Bricks, se non sai come fare l’ho già spiegato in questo articolo. Adesso elimina i Mattoni del cubo relativi allo script, lascia la Property vedrai come salvarne il valore dal manager e rinomina il Cube in cubo, servirà a rintracciarlo attraverso il suo nome nella modifica che farò allo script, questo ti fa capire ancora una volta com’è importante rinominare appropriatamente gli oggetti. Elimina la linea dei Mattoni relativa alla Property nel manager.

La prima cosa da fare è estrapolare dalla scena tutti gli oggetti, che non sono molti in questo caso, inserendo una semplice linea di codice in alto alle variabili globali, questa

scene = bge.logic.getCurrentScene()

Come sempre assegno ad una variabile il codice per ‘prendere’ (get) la scena corrente.

Non c’è bisogno di cambiare molto nello script, il proprietario (own) adesso è il manager, ma non serve salvarne la posizione, quindi aggiungi questa riga di codice sotto le tre variabili globali principali (scene, cont, own)

player = scene.objects['cubo']

Questo codice assegna alla variabile player (per questo esempio non serve dare un nome specifico), l’oggetto della scena (scene.object) cubo [‘cubo’], questo richiama l’oggetto attraverso il suo nome e qua ti rimando mentalmente alla pratica di rinominare gli oggetti.

Fatto questo puoi cambiare le parti di codice che fanno riferimento all’own (il proprietario), che in questo specifico caso non è più il cubo, con la parola player, cioè la variabile che richiama il cubo inserita nella riga precedente. Fai bene attenzione a cambiarla in entrambe le def sia save che load. La prima interessata è la variabile globale che punta alla Property del cubo, poi le tre variabili che puntano alla posizione del cubo su XYZ, questo per quanto riguarda la def save; per la def load è più semplice basta cambiare nelle ultime righe dove lo script assegna la posizione e la Property, il codice finale è questo

import bge

### VARIABILI GLOBALI ###
scene = bge.logic.getCurrentScene()
cont = bge.logic.getCurrentController()
own = cont.owner

# variabile che richiama il cubo attraverso il nome
player = scene.objects['cubo']

# Property count del cubo
count = player['count']

def save():
    # dichiarazione del sensor 
    sens_keyS = cont.sensors['keyS']
    # dichiarazione di tre variabili per la posizione
    posX = player.worldPosition.x
    posY = player.worldPosition.y
    posZ = player.worldPosition.z
    # struttura di controllo e salvataggio
    if sens_keyS.positive:
        bge.logic.globalDict['posCubo'] = [ posX, posY, posZ, count ]
        bge.logic.saveGlobalDict()
    
def load():
    # dichiarazione del sensor
    sens_keyL = cont.sensors['keyL']
    
    # se il tasto viene premuto
    if sens_keyL.positive:
        # carico le informazioni dal globalDict
        bge.logic.loadGlobalDict()
        # assegno alla variabile cuboPos i dati salvati
        cuboPos = bge.logic.globalDict["posCubo"]
        
        # assegno a ogni variabile l'indice dei dati salvati
        posX = cuboPos[0]      
        posY = cuboPos[1]
        posZ = cuboPos[2]
        # assegno le tre variabili alla posizione del cubo
        player.worldPosition = [ posX, posY, posZ ]
        # assegno il valore alla Property attuale
        player['count'] = cuboPos[3]

Per questo articolo è tutto, come puoi vedere non è difficile impostare e salvare una Property, neanche creare un manager che gestisca il salvataggio dei dati per gli altri oggetti, naturalmente essendo tu il creatore del tuo gioco puoi decidere come meglio credi il tuo modus operandi, puoi fare uno script per ogni oggetto per salvarne i dati, oppure usare il manager, o creare un manager per ogni categoria di oggetti, la scelta dipende da te, un consiglio che posso darti è quello di ridurre al minimo il lavoro che devi fare perché scrivere tanti script costa tempo e fatica e spesso quando si è stanchi gli errori si fanno e non si notano, quindi è facile andare nel pallone. Come ultima cosa ti ricordo di salvare spesso il file e di fare diverse prove, aggiungi altre Properties e altri oggetti per salvarne la posizione, se aggiungi altri oggetti crea altre righe per il globalDict per salvarne i dati, come la riga numero 23 dello script qui sopra, sarà più comprensibile e facile estrarre i dati. Nel prossimo articolo spiegherò i vari tipi di salvataggio (automatico e manuale) e il salvataggio dei dati tra una scena e l’altra. Buon divertimento.