Prima di iniziare a scrivere il codice Verse per il Puzzle delle luci con tag, è cruciale che pianifichi il modo migliore per realizzare il tuo obiettivo. Questa sezione ti mostra come affrontare la creazione di una meccanica di puzzle. Al termine di questo passaggio, avrai a disposizione un pseudocodice che rappresenta l'algoritmo per creare questo puzzle. Nel passaggio successivo imparerai poi come implementare questo algoritmo in Verse e UEFN.
Identificare obiettivi, requisiti e vincoli
Il primo passaggio è quello di identificare i tuoi obiettivi, requisiti e vincoli. I requisiti spesso derivano dalla scomposizione di obiettivi più ampi in parti più piccole.
| Obiettivi |
|
| Requisiti |
|
| Vincoli |
|
Suddividere il problema
Ora che hai capito cosa vuoi ottenere e le modalità di lavoro, suddividi il problema in parti più piccole che possano risultare più facili da risolvere. Porsi una serie di domande può aiutare a scomporre un problema più grande:
- Come può il giocatore interagire con il puzzle?
- Come puoi utilizzare i tag di gameplay per trovare le luci?
- Come definisci le condizioni iniziali e le soluzioni che possono essere modificate nell'editor?
- Come puoi abbinare lo stato del gioco, memorizzato in una struttura di Verse, alla grafica nel gioco?
- In che modo un'interazione tra giocatori è in grado di aggiornare un set specifico di luci?
- Come puoi disabilitare l'interazione con il giocatore dopo che il puzzle è stato risolto?
Quindi, identifica le potenziali dipendenze tra questi problemi più piccoli. In questo caso, sembra che i problemi siano indipendenti, ma vale la pena considerare quanto segue:
- Le domande 1, 5 e 6 sono liberamente associate.
- Per le domande 1 e 6, il modo in cui il giocatore interagisce con il puzzle non può determinare il modo in cui l'interazione viene disattivata, una volta risolto il puzzle.
- Per le domande 1 e 5, una singola interazione attiva più luci contemporaneamente. Questa operazione informerà la struttura dei dati da utilizzare per la mappatura delle interazioni con le luci.
- La domanda 2 è un'importante considerazione di progettazione. Il funzionamento dell'API Tag di gameplay potrebbe esercitare un impatto sul controllo delle luci nel codice. Ciò si ripercuote sulle domande 4 e 5, perché dovrai modificare lo stato delle luci nel gioco e quindi dovresti identificare un metodo comune per riuscirci.
- Le domande 3 e 4 dovrebbero probabilmente convergere verso un'unica soluzione per la struttura dati sottostante relativa agli stati: iniziale, attuale e di soluzione.
Ideare soluzioni potenziali
Ora che il problema è stato suddiviso in problemi minori, concentrati sulla risposta alle domande legate ai problemi più piccoli:
1. Come può il giocatore interagire con il puzzle?
Le soluzioni a questa domanda sono molteplici. In generale, puoi utilizzare qualsiasi dispositivo con cui il giocatore possa interagire e che Verse possa utilizzare per rilevare l'interazione. Il set di strumenti di Fortnite Creativo dispone di molti dispositivi che soddisfano questi requisiti, come i dispositivi Attivatori, Dispositivi Pulsante, ma anche i dispositivi Unità cambia-colore e i dispositivi Attivatori a percezione.
Questo esempio utilizzerà il dispositivo Pulsante e il relativo InteractedWithEvent, che viene inviato ogni volta che il giocatore interagisce con il pulsante, finché quest'ultimo è abilitato. Per ulteriori informazioni sugli eventi, vedi Codificare le interazioni tra i dispositivi.
2. Come puoi utilizzare i tag di gameplay per trovare le luci?
Con i tag di gameplay, puoi recuperare gruppi di attori a cui è stato assegnato un tag personalizzato definito nel tuo codice Verse.
Puoi utilizzare la funzione GetCreativeObjectsWithTag() per ottenere un array di tutti gli attori a cui è stato assegnato il tuo tag personalizzato. Il risultato della funzione è un array di tutti gli oggetti che implementano creative_object_interface. customizable_light_device è la rappresentazione di Verse di un dispositivo Luce personalizzabile ed è una classe che implementa creative_object_interface.
Non esiste un ordine garantito per l'elenco dei dispositivi restituiti da GetCreativeObjectsWithTag(), e la chiamata di funzione può richiedere del tempo per restituire tutti i dispositivi, specialmente se sono presenti numerosi dispositivi nel livello, quindi è buona idea memorizzare le luci, in modo da potervi accedere rapidamente in seguito. Questa operazione si chiama memorizzazione nella cache e spesso può migliorare le prestazioni. Poiché le luci sono una raccolta dello stesso tipo, puoi utilizzare un array per memorizzarle insieme.
Ciò significa che puoi:
- Crea un nuovo tag denominato
puzzle_light. - Contrassegna tutte le luci del puzzle con il tag
puzzle_light. - Chiama
GetCreativeObjectsWithTag(puzzle_light)per ottenere tutti gli attori che hanno il tagpuzzle_light. - Determina quali risultati della chiamata di funzione sono un
customizable_light_device. - Salva l'elenco degli oggetti
customizable_light_devicein un array, in modo da potervi accedere in seguito.
3. Come definisci le condizioni iniziali e le soluzioni che possono essere modificate nell'editor?
Una luce ha solo due stati: on o off. Puoi utilizzare il tipo logic in Verse per rappresentare lo stato on/off di una luce, dato che i valori del tipo logic possono essere solo true o false. Poiché ci sono più luci, puoi utilizzare un array anche in questo caso per memorizzare tutti i valori logic e far sì che la posizione dell'array, o indice, di uno stato di luce corrisponda all'indice della luce a cui è associato.
Questo array di valori logic può essere usato per definire lo stato iniziale delle luci del puzzle e contiene anche lo stato attuale delle luci durante il gioco. Puoi esporre questo array all'editor con l'attributo @editable. Le luci all'inizio del gioco possono quindi essere accese o spente per corrispondere visivamente allo stato memorizzato nell'array.
Affinché il puzzle possa essere risolto correttamente, è essenziale che la soluzione sia rappresentata utilizzando lo stesso tipo di dati usato per memorizzare lo stato attuale delle luci. Per rendere tutto ciò possibile, utilizzerai due array chiamati logic, entrambi modificabili. Un array rappresenterà lo stato corrente delle luci, mentre l'altro conterrà la soluzione del puzzle. In questo modo potrai modificare sia lo stato iniziale delle luci del puzzle sia la soluzione del puzzle dall'editor, e quindi riutilizzare il puzzle con diverse configurazioni.
4. Come puoi abbinare lo stato del gioco, memorizzato in una struttura di Verse, alla grafica nel gioco?
Puoi accendere o spegnere un customizable_light_device nel gioco utilizzando le funzioni TurnOn() e TurnOff(). Quindi, ogni volta che aggiorni lo stato attuale delle luci, rappresentato dall'array logico, devi chiamare anche TurnOn() e TurnOff() per far corrispondere la grafica del gioco con lo stato del gioco.
5. In che modo un'interazione tra giocatori è in grado di aggiornare un set specifico di luci?
Dalla prima domanda, hai già stabilito che il giocatore interagirà con il puzzle utilizzando il dispositivo Pulsante. Puoi sottoscrivere un gestore eventi all'InteractedWithEvent del Pulsante che cambierà le luci quando il giocatore interagisce con il dispositivo Pulsante. Poiché vi sono più pulsanti che il giocatore può utilizzare, puoi usare di nuovo un array per tenerli insieme.
Ora devi individuare il modo in cui mappare ogni evento pulsante separato al set di luci che deve attivare/disattivare.
Poiché l'ordine delle luci nell'array customizable_light_device sarà lo stesso ordine dell'array logico per rappresentare lo stato delle luci, puoi creare una mappatura tra un pulsante e gli indici delle luci su cui influirà. Questa mappatura può essere rappresentata in un array, dove l'ordine degli elementi corrisponde all'ordine dei pulsanti e gli elementi sono array di indici.
Puoi rendere l'array modificabile, in modo da poter cambiare la mappatura da pulsanti a luci nell'editor e poter riutilizzare il puzzle senza modificare il codice stesso.
6. Come puoi disabilitare l'interazione con il giocatore dopo che il puzzle è stato risolto?
Sai già che il giocatore sta interagendo con il puzzle usando il dispositivo Pulsante, che viene rilevato attraverso l'evento InteractedWithEvent.
Una volta risolto il puzzle, come può il dispositivo del puzzle smettere di ricevere input dal giocatore, in modo che quest'ultimo non possa più modificare il puzzle?
Vi sono almeno tre modi per eseguire questa operazione:
- Disattiva i pulsanti in gioco quando il puzzle è risolto.
- Aggiungi un campo
logicaltagged_lights_puzzleche viene modificato quando il puzzle viene risolto. Ogni volta che lo stato del gioco viene aggiornato, questo campologicdeve essere controllato per primo, per assicurarsi che il puzzle non sia già stato risolto. - Annulla la sottoscrizione da
InteractedWithEventdei pulsanti quando il puzzle è risolto, in modo che i gestori eventi non vengano più chiamati.
La terza opzione è la migliore perché rappresenta una soluzione semplice ed efficiente. Non devi creare nuovi campi per verificare l'esecuzione di codice condizionale. Il concetto di annullamento della sottoscrizione da un evento del dispositivo è riutilizzabile anche in altre situazioni. In generale, è buona norma sottoscrivere a un evento quando vuoi ricevere una notifica e annullare la sottoscrizione quando non ne hai più bisogno. I dettagli dell'implementazione dell'annullamento della sottoscrizione sono spiegati più avanti in questo tutorial.
Combinare più soluzioni e pianificare con lo pseudocodice
Ora che hai le soluzioni ai problemi più piccoli, combinale insieme per risolvere il problema originale. Formalizza l'algoritmo per costruire la soluzione utilizzando uno pseudocodice.
Cosa succede quando inizia la partita? Le luci sono state allestite. Puoi sottoscrivere all'evento InteractedWithEvent di Pulsanti, trovare tutti i dispositivi con il tag puzzle_light e memorizzarli nella cache. Puoi anche accendere e spegnere le luci del gioco in base al LightState iniziale.
OnBegin:
Result of GetCreativeObjectsWithTag(puzzle_light) is stored in the variable FoundDevices
for each Device in FoundDevices:
if Device is a Customizable Light Device:
Store the Light
if ShouldLightBeOn?:
Turn on Light
else:
Turn off Light
for each Button:
Subscribe to the Button InteractedWithEvent using the handler OnButtonInteractedWith
Una versione del pseudocodice di OnButtonInteractedWith potrebbe essere simile a questa, dove InteractedButtonIndex indica l'indice dell'array button_device che corrisponde al pulsante con cui il giocatore ha interagito. Nella parte successiva del tutorial, vedrai come ricevere queste informazioni all'interno del gestore eventi.
OnButtonInteractedWith:
Get lights associated with the button interacted with using the ButtonsToLights array and store in the variable Lights
# Attiva/disattiva le luci
for each Light in Lights:
if IsLightOn?:
Set the Light game state to off
Turn off Light
else:
Set the Light game state to on
Turn on Light
if IsPuzzleSolved():
Enable Item Spawner
for each Button:
Unsubscribe from the Button InteractedWithEvent
Lo pseudocodice di IsPuzzleSolved controlla se lo stato attuale delle luci corrisponde alla soluzione. Se lo stato attuale non corrisponde alla soluzione, la verifica fallisce e il blocco if IsPuzzleSolved dello pseudocodice precedente non viene eseguito. Se lo stato corrente corrisponde alla soluzione, la verifica riesce e viene eseguito il blocco if IsPuzzleSolved.
IsPuzzleSolved:
for each Light:
if IsLightOn is not equal to IsLightOnInSolution
fail and return
esecuzione con successo
Hai sviluppato con successo il tuo algoritmo!
Passaggio successivo
Nel passaggio successivo di questo tutorial, tradurrai questo algoritmo nel linguaggio di programmazione Verse ed eseguirai un playtest del tuo progetto per visualizzare questi passaggi in azione.