Come programmare Time Stop o Bullet Time in un gioco?


11

Sto sviluppando un platform RPG per giocatore singolo in XNA 4.0. Vorrei aggiungere un'abilità che farebbe “fermare” o rallentare il tempo e che solo il personaggio del giocatore si muovesse alla velocità originale (simile all'incantesimo Time Stop della serie Baldur's Gate). Non sto cercando un'implementazione esatta, piuttosto alcune idee generali e modelli di progettazione.

EDIT: grazie a tutti per l'ottimo contributo. Ho trovato la seguente soluzione

    public void Update(GameTime gameTime)
        {

            GameTime newGameTime = new GameTime(gameTime.TotalGameTime,
 new TimeSpan(gameTime.ElapsedGameTime.Ticks / DESIRED_TIME_MODIFIER));
            gameTime = newGameTime;

o qualcosa del genere. In questo modo posso impostare un orario diverso per il componente giocatore e diverso per il resto. Certamente non è abbastanza universale lavorare per un gioco in cui il tempo deformato come questo sarebbe un elemento centrale, ma spero che dovrebbe funzionare in questo caso. Non mi piace il fatto che sporchi il ciclo di aggiornamento principale, ma è sicuramente il modo più semplice per implementarlo. Immagino che sia essenzialmente lo stesso suggerito da tesselode, quindi gli darò il segno di spunta verde :)

Risposte:


8

Questa potrebbe essere una cattiva soluzione, ma non necessariamente. Se stai usando delta time, puoi cambiarlo per cambiare la velocità di certe cose.

Per esempio:

player.update(dt)
dt = dt * .5 --half speed
enemy.update(dt)

Questo, ovviamente, funziona solo se riesci a capire quando stai aggiornando il nemico piuttosto che qualcos'altro. Puoi anche dare a tutto un valore di velocità e fare qualcosa del tipo:

x = x + xspeed * dt * speed

La prima parte ha perfettamente senso, la seconda parte non è chiara
AturSams

2
Basta dare a ciascun oggetto che sposta una variabile di velocità che è possibile modificare e quando si ha una trasformazione (ad esempio di x), moltiplicare l'intensità per la variabile di velocità.
tesselode,

Ha senso adesso. :)
AturSams,

La seconda idea sembra ... spenta. Il semplice ridimensionamento del movimento in base al fattore "velocità" può funzionare per gli oggetti guidati dalla fisica, ma l'IA sarebbe in grado di reagire a velocità normale, con solo il loro movimento rallentato / compromesso.

Cosa intendi dire che l'IA sarebbe in grado di reagire a velocità normale? Quale codice avrebbe l'IA a cui non potrebbe essere applicata una variabile di velocità?
tesselode

3

L'uso del delta time (millisecondi passati dall'ultimo frame) potrebbe non essere sufficiente per rallentare i nemici. Cose come il tasso di attacco potrebbero essere implementate in base all'ultimo tempo di attacco. Mentre rallenterà il movimento se è basato sul tempo, trascurerà di rallentare la velocità di attacco, il lancio di incantesimi e altri effetti (rigenerazione della salute, durata degli effetti degli incantesimi) .. e simili

Se vuoi rallentare un folto gruppo di elementi di gioco in una partita a giocatore singolo, puoi creare un secondo orologio interno per ogni creatura, l'orologio inizia nel momento in cui appare la creatura. Quando viene lanciato un incantesimo lento, ogni fotogramma, l'orologio viene incrementato di x% del tempo effettivamente trascorso. Tutto il comportamento dei mostri viene quindi determinato dal suo orologio interno. Se vari mostri hanno resistenza al rallentamento, possono usare il proprio orologio, è fondamentalmente un numero intero che non richiede molto spazio o calcolo.

Quando l'effetto lento si interrompe, gli orologi vengono ancora utilizzati e vengono incrementati del 100% del tempo effettivamente trascorso.

Questo potrebbe funzionare anche per gli incantesimi accelerati.

@Sidar: vedo due scelte,

  1. Orologio interno per creatura. Per scoprire se la creatura è pronta ad attaccare di nuovo: salva l'ultima volta che è stato usato ogni attacco + tempo di ricarica e controlla se l'orologio interno è già passato quel tempo.

  2. Un timer per attacco: sai quanto tempo impiega l'attacco a ricaricarsi e devi semplicemente impostare un timer e sottrarre il tempo che è passato * (1% di rallentamento) ogni turno.

Personalmente preferisco evitare di sottrarre più singoli timer e l'utente un orologio interno per risparmiare tempo e complessità di elaborazione.

Dipende davvero dalle preferenze (non influisce molto sulle prestazioni).


Non è necessaria la necessità di orologi interni. Si riduce semplicemente a un moltiplicatore che puoi (in qualche modo) collegare al tuo oggetto che aumenta o diminuisce il prodotto del tuo dt (delta time). Puoi gestire gli oggetti per gruppi o qualunque altro mezzo. Penso che la tua strada potrebbe essere un po 'eccessiva. Ma hey se funziona ... allora funziona.
Sidar,

@Sidar Se lo eviti, probabilmente avrai bisogno di un clock per attacco solo per ricaricare l'attacco, la durata dell'incantesimo e cose del genere. Almeno in questo modo è necessario aggiornare solo un orologio e mantenere semplicemente l'ora dell'ultima attivazione per il ripristino delle proprietà.
AturSams,

La sua domanda, tuttavia, riguarda il rallentamento dell'ambiente ad eccezione del giocatore. A me sembra la forma più semplice di moltiplicare il dt con un numero inferiore a 1. Mantenendolo come per il giocatore.
Sidar,

Bene, il rallentamento degli ambienti include il rallentamento del loro tasso di attacco e delle loro altre abilità (dal momento che è un gioco di ruolo), potrebbero esserci varie abilità mob che si basano sul tempo di ricarica. Guarisce, buff, debuff, incantesimi ecc. Per non parlare dei tempi di attivazione.
AturSams,

2

Puoi iniziare con una soluzione semplice come quella esposta da tesselode o Mr Beast. Ma se inizi a mescolare cose complesse, cioè un tempo di proiettile mentre viene lanciato un incantesimo di rallentamento, rimarrai bloccato.

Ti suggerisco di implementare una gerarchia di clock :

.
├── Main clock
│   └── UI clock
│   └── 3D clock
│       ├── GFX clock
│       └── Gameplay clock
│           └── Slowdown spell clock 01
│           └── Slowdown spell clock 02

Tutto nel tuo gioco dovrebbe usare i tempi delta da uno dell'orologio: gli effetti grafici vengono eseguiti sull'orologio GFX, l'intelligenza artificiale e l'animazione vengono eseguite sull'orologio di gioco, le creature colpite da un incantesimo di rallentamento corrono su un temporaneo incantesimo di rallentamento, ecc. Poi varie cose influisce su diverse parti della gerarchia: un incantesimo di rallentamento crea e influenza un orologio personalizzato, mentre un tempo di proiettile influenzerà l'intera gerarchia dell'orologio 3D.


Grazie, questa è una visione importante. Tuttavia, penso che continuerò a pensare in modo semplice, dal momento che non ha senso nel mio caso particolare che si verifichino più effetti di rallentamento allo stesso tempo.
David Miler,

1

Hai solo bisogno di due orologi diversi invece di uno, uno per il tempo rilevante per il gameplay e un tempo "vero".

currentGameTime = 0;
gameSpeed = 1.0f;
[...]
currentApplicationTime = GetTime():
timeDelta = (currentApplicationTime - lastApplicationTime)*gameSpeed;
currentGameTime += timeDelta;
lastApplicationTime = currentApplicationTime;

Quindi puoi semplicemente cambiare gameSpeed ​​per accelerare (> 1) o rallentare il tempo (<1). Per far muovere il giocatore a velocità diverse basta controllare se il tempo viene rallentato o meno.

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.