È finalmente giunto il momento di aggiungere dei nemici al gioco, il che vuol dire factories!
Factories
Un nemico è solo un altro tipo di entità, motivo che mi ha spinto ad implementare una classe la cui sola responsabilità è di creare entità: la EntityFactory
. Questa factory contiene una lista di prototipi che possono essere selezionati dall’editor a piazzati nella scena. Dietro le quinte, il prototipo viene clonato, il clone viene spostato nella posizione del mouse, ed è aggiunto alla lista delle entità della scena.
A questo punto ho realizzato che ogni clone stava duplicando le proprie texture, che è qualcosa che potremmo e dovremmo evitare, quindi ho aggiunto un’altra factory: la GraphicsFactory
. La responsabilità di questa classe è di mantenere una lista di texture che possano essere referenziate da più graphics components, oltre a quella di creare ogni tipo di sprite che faccia uso di una di queste texture.
Comandi
Una volta aggiunti i nemici alla scena, ho cominciato a riflettere su come farli muovere. Riutilizzare lo state component del personaggio principale sembrava una buona idea, ma c’era un problema. La logica di movimento dello state component controllava direttamente il gamepad e la tastiera, e ciò significava che l’input del giocatore potesse muovere all’unisono sia il personaggio principale che tutti i nemici. La soluzione a questo tipo di problemi sta nel decoupling.
Input → MoveCommand → StateComponent
Ho rimosso la dipendenza che lo state component aveva verso l’input, e ho introdotto il concetto di comando. Per semplicità, mi concentrerò sul MoveCommand
. Lo state component adesso sta semplicamente in attesa di move commands e, quando arrivano, il component aggiorna il proprio stato a seconda dei valori del comando. Move commands, ed eventualmente altri tipi di comandi, possono essere generati da qualsiasi fonte: player input, in-game console, script, e così via, il che li rende molto flessibili.
Script
Altri engine usano termini come behaviors, ma io preferisco il termine tecnico di script. Con questo si può certamente modellare il comportamento delle entità, come ad esempio il wandering behavior, un tipo di movimento che avevo in mente per la prima classe di nemici. Idealmente si potrebbe anche usare un linguaggio di scripting, come LUA che è supportato dall’nCine, tuttavia ho rimandato l’esplorazione di questa possibilità ad un’altra volta.
Ho scritto un paio di righe per il wandering behavior che dovrebbero muovere l’entità verso destra o sinistra finchè non vi sia un ostacolo. A quel punto dovrebbe girarsi e continuare in un loop. Il risultato è sicuramente interessante, anche se credo che possa essere migliorato ancora. Bye for now!