Come implementare il viaggio nel tempo in un gioco?


10

Mi chiedevo come implementare il viaggio nel tempo in un gioco. Niente di super complesso, solo un'inversione di tempo come quello che c'è in Braid, in cui l'utente può riavvolgere / avanzare rapidamente di 30 secondi o altro.

Ho cercato molto sul Web, ma i miei risultati di solito si riferivano all'utilizzo del tempo come in "Sono le 3:00" o un timer e così via.

L'unica cosa che mi è venuta in mente è stata di usare 2 matrici, una per la posizione x del giocatore e l'altra per la posizione y del giocatore, e poi scorrere tra quelle matrici e posizionare il personaggio in quella posizione mentre si riavvolgono / avanzano rapidamente. Potrebbe funzionare? Se funzionasse, quanto dovrebbe essere grande l'array e con quale frequenza devo archiviare xey del lettore? Se non funziona, cos'altro potrei provare?

Grazie in anticipo!


11
Non leggi le notizie ( ust.hk/eng/news/press_20110719-893.html )? Hanno appena dimostrato che non è possibile viaggiare nel tempo. Pertanto, è impossibile codificare.

Devi pensare a una possibile semantica per i viaggi nel tempo, solo dopo puoi iniziare a pensare all'implementazione.
Paŭlo Ebermann,


2
Impara un po 'di matematica vettoriale . Se stai proponendo due array separati che suggeriscono che non hai mai lavorato con loro. Li considero vitali per un programmatore di giochi per sapere quanto possono semplificare le cose.
doppelgreener,

5
import universal.back2future.FluxCapacitor;
jhocking

Risposte:


6

L'idea di array è praticamente come è stata implementata in Braid. Quando le uniche cose che agiscono su un personaggio sono la gravità, l'input da tastiera / joypad e altri personaggi, praticamente devi solo memorizzare la posizione e la velocità ad ogni passo per sapere tutto ciò che è importante su quel personaggio. Se memorizzi 10 istantanee al secondo per personaggio, sarà comunque meno di 50K per un minuto della storia di un personaggio - facilmente gestibile sulla maggior parte dei sistemi e puoi trovare modi più efficienti di quello.


Questa è la strada giusta. Ad esempio memorizzare i comandi attivi: premere i tasti con i timestamp. È possibile estrapolare la maggior parte degli altri comportamenti se il sistema è deterministico. Il tracker a 10 fps va bene per un sistema di riavvolgimento, anche meno potrebbe essere accettabile, purché i comandi effettivi vengano mantenuti, in effetti lo stato o gli statechanges degli oggetti.
Karmington,

4

Leggi sul modello di comando . Prevede le azioni di annullamento (e di ri-eseguirle in seguito). Ciò gestirà molto più della semplice posizione di una nave, ma di tutte le azioni intraprese dal giocatore.

Ma penso che anche la tua idea di array sia valida.


Probabilmente non è una grande idea - oltre ad essere più intensivo in termini di memoria (ogni volta che aggiungi la velocità di un'entità alla sua posizione, devi memorizzarla come "azione") , richiede praticamente matematica a punto fisso, poiché se usi il floating -punto per le tue posizioni / velocità, (x+v)-vpotrebbe non essere uguale a x.
BlueRaja - Danny Pflughoeft,

1
@BlueRaja - Non vedo dove l'approccio richiederebbe molta memoria. A 100 FPS e con la memorizzazione degli ultimi 10 secondi, è necessario memorizzare 1000 n-tupel di comandi, dove n è al massimo 5 o giù di lì. O, ancora meglio, memorizzi solo la posizione assoluta in ciascuno di quei frame e, per il riavvolgimento, devi semplicemente animare il personaggio all'indietro lungo quel percorso. Ciò eliminerebbe anche ogni possibile problema in virgola mobile e ti riporterà esattamente da dove hai iniziato.
Hackworth,

3

Invece di avere due array separati, probabilmente dovresti avere una classe che descrive la posizione del giocatore (probabilmente c'è già una classe Point in Java ... sono un tipo C # ultimamente) e usa un singolo array per mantenere le posizioni passate.

È necessario impostare un "ring buffer", il che significa che quando si arriva alla fine dell'array, si torna indietro all'inizio dell'array, sovrascrivendo le voci più vecchie. Se viaggi indietro nel tempo, è vero il contrario (quando arrivi all'inizio, cerchia fino alla fine).

Se si desidera conservare i dati passati per 30 secondi, è necessario conoscere la frequenza dei fotogrammi se si desidera pre-allocare spazio e utilizzare un array di dimensioni fisse. Se esegui il rendering del gioco a 10 fotogrammi / secondo, per 30 secondi, sono 300 elementi.



1

Come ha detto Erik J , la memorizzazione delle posizioni passate del giocatore come una raccolta di oggetti punto in un buffer ad anello sembra ragionevole.

Tuttavia, suggerirei di utilizzare una coda per implementare il buffer. È molto più economico aggiornare di un array e non è necessario conoscere in anticipo la frequenza dei fotogrammi:

update():
   time_queue.push(player.positions)
   if current_time() - start_time > n:
       queue.pop()

Questo non considera ancora la variazione di frame rate o cosa dovrebbe accadere se effettivamente viaggi nel tempo, quindi ti suggerisco di memorizzare un timestamp con ogni voce e controllare invece:

update():
    time_queue.push({
        'pos': player.positions,
        'time': current_time()
    })
    first_entry = queue.peek()
    while current_time() - first_entry['time'] > n:
       queue.pop()
       first_entry = queue.peek()

Spero che sia di aiuto!


1

C'è un modello di design chiamato Memento , penso che sia un punto di partenza per un gioco come Braid

Il modello ricordo è un modello di progettazione software che consente di ripristinare> un oggetto al suo stato precedente (annullare tramite rollback).

Il modello ricordo è usato da due oggetti: l'originatore e un custode. Il mittente è un oggetto che ha uno stato interno. Il custode farà qualcosa al mittente, ma vuole essere in grado di annullare il cambiamento. Il custode prima chiede all'originatore un oggetto ricordo. Quindi esegue qualsiasi operazione (o sequenza di operazioni) che stava per fare. Per tornare allo stato precedente alle operazioni, restituisce l'oggetto ricordo al mittente. L'oggetto memento stesso è un oggetto opaco (uno che il custode non può o non dovrebbe cambiare). Quando si utilizza questo modello, è necessario prestare attenzione se l'originatore può modificare altri oggetti o risorse: il modello ricordo si basa su un singolo oggetto.

http://en.wikipedia.org/wiki/Memento_pattern

Informazioni aggiuntive qui: http://dofactory.com/Patterns/PatternMemento.aspx


2
Non riesco a vedere come questo dovrebbe aiutare. Sembra un "rollback istantaneo", mentre l'OP ha chiesto qualcosa di liscio come quello di Braid. Forse ho letto male qualcosa?
o0 '.

Questo modello non implica un singolo rollback, ad esempio è possibile creare una "sequenza temporale" di azioni. Ecco un post sul blog di Brazillian sull'uso di questo modello: abrindoojogo.com.br/padroes-de-projeto-memento Ecco un esempio realizzato in Flash: abrindoojogo.com.br/files/fasteroids.swf Move: Arrows | Spara: Spazio | Azioni di riavvolgimento: Backspace
Marcelo Assis,

1

È stato rilasciato un gioco per XBox360 che prevedeva la manipolazione del tempo. Era mediocre, quindi non ricordo il titolo in questo momento. Ad ogni modo, in un'intervista con uno sviluppatore per questo, hanno delineato come hanno gestito la manipolazione del tempo:

Ogni fotogramma X (con valori inferiori di X che porta a una manipolazione più precisa), a quel punto prendi una "istantanea" del mondo di gioco e lo associ a un tempo di gioco.

Durante il gioco normalmente, time-forward, ogni input di una reazione contribuisce allo snapshot impostato in futuro.

Il mondo di gioco quindi scorre l'istantanea al momento attuale e i fotogrammi X dell'istantanea in futuro.

Quindi, quando si desidera invertire il tempo, basta impostare la direzione del tempo in modo che sia indietro, in modo che itererà tra il presente e i fotogrammi X dell'istantanea in passato (disabilitando al contempo la possibilità di creare istantanee future).


+1 per il punto sulla granularità delle istantanee.
Omar Kooheji,

0

Puoi semplicemente considerare il tempo virtuale del gioco come un'altra dimensione spaziale. Quindi ciò che il viaggio nel tempo dall'esterno è un semplice movimento dimensionale n + 1 nell'universo virtuale del gioco.

Supponendo un po 'di interazione dell'utente e una sorta di sistema fisico che determina il comportamento del tuo universo quando non c'è input dell'utente, tutto ciò che devi registrare è l'effetto delle interazioni dell'utente (ad esempio, cambiamenti nei vettori di velocità / accelerazione della dimensione n + 1) , poiché la tua fisica dovrebbe essere reversibile nel tempo.

In questo modo avresti bisogno di molta meno memoria per calcolare lo stato dell'universo di gioco in qualsiasi dato momento.


Come ho già detto in un altro commento, la fisica nei videogiochi di solito non è reversibile nel tempo, perché quando si usano numeri in virgola mobile, (x+v)-vpotrebbe non essere uguale ax
BlueRaja - Danny Pflughoeft

0

Supponiamo che un'entità abbia velocità, rotazione, posizione xey. Questi sono, con accelerazione, gli stati di movimento di base, i valori, qualunque cosa tu lo chiami. È possibile salvare i dati in due modi:
1. Salva rotazione, posizione xey
2. Salva rotazione, velocità x e velocità y

Se hai una velocità fissa, puoi anche salvare solo la rotazione o salvare solo una velocità per entrambi gli assi.

Il salvataggio della rotazione è necessario nei giochi, a meno che la tua entità non abbia una rotazione statica, cosa non accade nella maggior parte dei casi.

Detto questo, è necessario utilizzare un elenco di oggetti per più valori. Se hai un bel sistema di timer, che, ad esempio, chiama i metodi di aggiornamento 20 volte in un secondo, e quindi è indipendente dai fps, puoi creare una matrice di oggetti 20 * 30 per memorizzare i valori di movimento necessari negli ultimi 30 secondi . L'uso di un array semplice non è raccomandato, poiché si dovrebbe spostare ogni elemento di un indice a sinistra di ogni chiamata di aggiornamento.

Sulla base di questo, è possibile consultare l'elenco o qualsiasi altra cosa per tornare indietro. Se vuoi davvero ottenere un effetto "realistico", usa questa tecnica per tutti gli oggetti in movimento. Ma questo è legato al design del gioco.

Se distruggi oggetti, ricordati di raggrupparli, per assicurarti di non stressare il tuo amico pulito Mr. Garbage;)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.