Sviluppare un gioco in Python: Panda3D – nodi e textures

Introduzione

In questo articolo vedremo meglio quali sono i rapporti tra i vari nodi dell’albero di rendering di Panda3d; inoltre vedremo come aggiungere una texture da una semplice immagine da noi creata, per rendere più viva la scena e cominciare così a caratterizzare gli oggetti del gioco.

Per cominciare vediamo come “spalmare” la nostra immagine sull’oggetto 3d da noi creato. Il nostro cubo diventerà colorato e manterrà le proprietà acquistate, che saranno opportunatamente memorizzate nel file .egg o .bam, a seconda di come esportere l’oggetto. Ricordate che le texture applicate dovranno comunque essere presenti tra file di gioco, visto che i file egg o bam faranno riferimento proprio alle stesse immagini che inseriremo sull’oggetto.

Aggiungere una texture

Per prima cosa apriamo blender con il nostro cubo di base e dividiamo l’area di lavoro cliccando su un separatore ed aggiungendone uno verticale.

Nell’area destra selezioniamo la vista UV/Image Editor.

Fatto questo premiamo Tab per selezionare tutti i vertici del cubo che abbiamo sulla scena, poi premiamo ‘u’ e selezioniamo dal menù a tendina la voce Project From View.

Ora dobbiamo porre la nostra attenzione al pannello dei pulsanti. Premendo F5 accederemo alle proprietà di Shading. Nella sezione Link to Object diamo un nome al nostro oggetto, nell’esempio è chiamato TEST. Dalla scheda material selezioniamo la voce TexFace ed infine diamo un nome alla texture, nell’esempio è chiamata my Texture.

Successivamente premiamo F6 per accedere al menù delle textures. Qui selezioniamo su Texture Type la voce Image. Caricate quindi la vostra immagine con il pulsante load che verrà visualizzato dopo la selezione.

Fatto questo, possiamo selezionare la nostra texture dalla visuale UV/Image Editor.

Con questi semplici passi, avremo un’immagine che si adatta al poligono creato in base alla posizione dei vertici nella visuale UV/Image Editor. Potete modificare la posizione di questi ultimi per vedere gli effetti sulla renderizzazione della texture sul cubo. Per controllarlo sulla vista 3d di blender basta selezionare in Draw Type la voce Textured.

Una volta concluso il procedimento non vi resta che esportare il tutto con il plugin di cui abbiamo parlato nel precedente articolo.

Nodi della scena

Nel seguente pezzo di codice  non ci sarà nulla di nuovo, ma servirà per capire come funzionano i nodi.

# -*- coding: utf-8 -*-

from direct.showbase.ShowBase import ShowBase
from pandac.PandaModules import *

class MyApp(ShowBase):
    def __init__(self):
        ShowBase.__init__(self)

        self.oggetto0 = self.loader.loadModel("models/cubo_giallo.egg")
        self.oggetto0.reparentTo(self.render)
        self.oggetto0.setPos(-3,7,3)
        self.oggetto0.setScale(0.15,0.15,0.15)

        self.oggetto0_0 = self.loader.loadModel("models/cubo_giallo.egg")
        self.oggetto0_0.reparentTo(self.render)
        self.oggetto0_0.setPos(self.oggetto0,-5,10,5)
        self.oggetto0_0.setScale(0.15,0.15,0.15)

        self.oggetto0_00 = self.loader.loadModel("models/cubo_rosso.egg")
        self.oggetto0_00.reparentTo(self.render)
        self.oggetto0_00.setPos(-5,10,5)
        self.oggetto0_00.setScale(0.15,0.15,0.15)
        #self.oggetto0_00.setHpr(50,50,50)

        self.oggetto1 = self.loader.loadModel("models/cubo_rosso.egg")
        self.oggetto1.reparentTo(self.render)
        self.oggetto1.setPos(3,7,3)
        self.oggetto1.setScale(0.15,0.15,0.15)
        self.oggetto1_1 = self.loader.loadModel("models/cubo_rosso.egg")
        self.oggetto1_1.reparentTo(self.oggetto1)
        self.oggetto1_1.setPos(-5,10,5)
        self.oggetto1_1.setScale(1,1,1)

        self.oggetto2 = self.loader.loadModel("models/carousel_base.egg.pz")
        self.oggetto2.reparentTo(self.render)
        self.oggetto2.setPos(0,7,2)
        tex = self.loader.loadTexture("models/test_texture.png")
        self.oggetto2.setTexture(tex,1)

        self.setBackgroundColor(0,0,255)
        self.disableMouse()
        self.useDrive()

app = MyApp()
app.run()

Analisi

Il codice vi permetterà di visualizzare la seguente scena:

Sull’immagine ho aggiunto dei numeri per identificare meglio i cubi presenti sullo schermo. Spero mi scuserete per la banalità dei nomi dati agli oggetti nello script, ma sono solo esempi per far vedere un certo tipo di comportamento.

Detto questo, possiamo vedere come il cubo numero 1 (oggetto0) e 4 (oggetto1) siano gli stessi del precedente esempio, ora arricchiti dalle textures. Il cubo numero 2 (oggetto0_0) è identico al primo ma la sua posizione è settata rispetto al cubo numero uno, come potete notare alla riga numero 17.

Il cubo rosso numero 3 (oggetto0_00), rappresenta la posizione che dovrebbe avere il cubo numero 2 se non si prendeva come riferimento le coordinate del primo cubo.

Ora passiamo al cubo numero 5 (oggetto1_1). Quest’ultimo diventa figlio del cubo numero 4 (0ggetto1) e quindi la sua posizione avrà le coordinate relative a quest’ultimo. Da notare che ha lo stesso effetto di spostare l’oggetto utilizzando come riferimento un’altro oggetto, come abbiamo già visto per il cubo giallo numero 2.

Ponete attenzione anche alla linea 33, dove possiamo vedere che il cubo rosso numero 5 non ha le dimensioni originali dell’oggetto da noi creato con blender, ma visto che il padre è stato già scalato (linea 29), anche il figlio prende questa caratteristica e quindi il setScale della linea 33 non ha effetto (nel senso che il cubo mantiene le proporzioni del padre).

Per concludere, le linee 38 e 39 mostrano come sostituire una texture già presente, ma questo aspetto sarà approfondito in un secondo tempo, visto che è solo un esempio di come Panda3d può caricare un’immagine ed applicarla ad un oggetto.

Conclusioni

Con questo breve esempio si può notare come le proprietà di un nodo padre vengono estese al figlio che le eredita automaticamente. Il fulcro della scena rimane sempre render, quindi spetta a noi gestire l’albero di rendering in base alle nostre esigenze. Se applichiamo qualcosa a render, come per esempio un effetto nebbia, tutti i suoi figli prenderanno quell’effetto e quindi tutti gli elementi visualizzati sulla scena visto che devono per forza essere legati a render per essere visualizzati sullo schermo.

Le coordinate relative possono tornare molto utili e rendono più facile il posizionamento degli oggetti sulla scena. Questo concetto vale anche per le rotazioni.

Anche se l’applicazione delle texture ora è stata fatta in modo banale, nulla vieta di fare i propri esperimenti se siete dei bravi modellatori 3d.

Nel prossimo capitolo vedremo come gestire oggetti dinamici muovendo le nostre creazioni durante il tempo di gioco. Questo sarà un passo necessario per arrivare al controllo degli input per far interagire l’utente.

Di seguito rilascio i sorgenti dell’esempio:

Download esempio : http://tinyurl.com/6bxzh7c

Press ESC to close