Comment implémenter le voyage dans le temps dans un jeu?

10

Je me demandais comment implémenter le voyage dans le temps dans un jeu. Rien de super complexe, juste une inversion du temps comme ce qui est dans Braid, où l'utilisateur peut rembobiner / avancer rapidement de 30 secondes ou autre.

J'ai beaucoup cherché sur le Web, mais mes résultats faisaient généralement référence à l'utilisation du temps comme «il est 3 h» ou d'une minuterie et ainsi de suite.

La seule chose à laquelle je pouvais penser était d'utiliser 2 tableaux, l'un pour la position x du joueur et l'autre pour la position y du joueur, puis d'itérer à travers ces tableaux et de placer le personnage à cette position pendant le rembobinage / l'avance rapide. Cela pourrait-il fonctionner? Si cela fonctionnait, quelle serait la taille du tableau et à quelle fréquence devrais-je stocker les x et y du joueur? Si cela ne fonctionne pas, que puis-je essayer d'autre?

Merci d'avance!

Alex
la source
11
Ne lisez-vous pas les nouvelles ( ust.hk/eng/news/press_20110719-893.html )? Ils viennent de montrer qu'il n'est pas possible de voyager dans le temps. Par conséquent, il est impossible de coder.
Vous devez penser à une sémantique possible pour le voyage dans le temps, seulement après, vous pouvez commencer à penser à la mise en œuvre.
Paŭlo Ebermann
2
Apprenez-vous quelques mathématiques vectorielles . Si vous proposez deux tableaux distincts, cela suggère que vous n'avez jamais travaillé avec eux. Je les considère comme vitaux pour un programmeur de jeux, car ils peuvent simplifier les choses.
doppelgreener
5
import universal.back2future.FluxCapacitor;
jhocking

Réponses:

6

L'idée du tableau est à peu près la façon dont il a été mis en œuvre dans Braid. Lorsque les seules choses qui agissent sur un personnage sont la gravité, la saisie au clavier / joypad et d'autres caractères, il vous suffit à peu près de stocker la position et la vitesse à chaque étape pour tout savoir sur ce personnage. Si vous stockez 10 instantanés par seconde et par personnage, c'est encore moins de 50K pour une minute de l'historique d'un personnage - facilement gérable sur la plupart des systèmes, et vous pouvez également trouver des moyens plus efficaces que cela.

Kylotan
la source
C'est la bonne voie. Par exemple, stocker des commandes actives: des touches avec des horodatages. Vous pouvez extrapoler la plupart des autres comportements si le système est déterministe. Le tracker 10 fps est bien pour un système de rembobinage, encore moins pourrait être acceptable, tant que les commandes réelles sont conservées, en fait l'état ou les statechanges des objets.
karmington
4

Lisez le modèle de commande . Il permet d'annuler des actions (et de les refaire plus tard.) Cela gérerait plus que la position d'un navire, mais toutes les actions que le joueur prend.

Mais je pense que votre idée de tableau est également valable.


la source
Probablement pas une bonne idée - en plus d'être plus gourmande en mémoire (chaque fois que vous ajoutez la vitesse d'une entité à sa position, vous devez la stocker comme une "action") , elle nécessite à peu près des calculs à virgule fixe, car si vous utilisez flottant -point pour vos positions / vitesse, (x+v)-vpeut ne pas être égal à x.
BlueRaja - Danny Pflughoeft
1
@BlueRaja - Ne voyez pas où cette approche serait gourmande en mémoire. À 100 FPS et en stockant les 10 dernières secondes, vous devez stocker 1000 n-tupels de commandes, où n est au plus égal à 5 ​​environ. Ou, mieux encore, vous ne stockez que la position absolue dans chacune de ces images, et pour le rembobinage, vous animez simplement le personnage à l'envers le long de ce chemin. Cela éliminerait également les éventuels problèmes de virgule flottante et vous ramènerait exactement à votre point de départ.
Hackworth
3

Plutôt que d'avoir deux tableaux séparés, vous devriez probablement avoir une classe qui décrit la position du joueur (il y a probablement déjà une classe Point en Java ... Je suis un gars C # récemment) et utiliser un seul tableau pour conserver les positions passées.

Vous devez configurer un "tampon en anneau", ce qui signifie que lorsque vous arrivez à la fin du tableau, vous retournez au début du tableau, en remplaçant les entrées les plus anciennes. Si vous voyagez dans le temps, l'inverse est vrai (lorsque vous arrivez au début, encerclez jusqu'à la fin).

Si vous souhaitez conserver 30 secondes de données passées, vous devez connaître votre fréquence d'images si vous souhaitez pré-allouer de l'espace et utiliser un tableau de taille fixe. Si vous rendez le jeu à 10 images / seconde, fois 30 secondes, cela fait 300 éléments.

Eric J.
la source
2

GDCVault a une conférence de Jon Blow (le créateur de Braid ) sur leur site intitulé The Implementation of Rewind in Braid pour 3,95 $. Je parie que cela contient les informations que vous voulez;)

EDIT: ne sera probablement pas en Java mais les idées devraient tenir.

NoobsArePeople2
la source
Savez-vous s'ils vendent aussi la transcription, ou seulement l'audio?
o0 '.
Je n'ai rien trouvé via une recherche rapide sur le site. Peut-être pourriez-vous utiliser un logiciel de transcription ?
NoobsArePeople2
1

Comme l'a dit Erik J , stocker les positions passées du joueur comme une collection d'objets ponctuels dans un tampon en anneau semble raisonnable.

Cependant, je suggère d'utiliser une file d' attente pour implémenter le tampon. La mise à jour est beaucoup moins chère qu'un tableau et vous n'avez pas besoin de connaître votre fréquence d'images à l'avance:

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

Cela ne prend pas encore en compte la variation des fréquences d'images ou ce qui devrait se produire si vous effectuez des voyages dans le temps, je vous suggère donc de stocker un horodatage avec chaque entrée et de le vérifier à la place:

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()

J'espère que cela t'aides!

HumanCatfood
la source
1

Il y a un modèle de conception appelé Memento , je pense que c'est un point de départ pour un jeu comme Braid

Le modèle de souvenir est un modèle de conception logicielle qui permet de restaurer un objet à son état précédent (annuler via une restauration).

Le motif souvenir est utilisé par deux objets: l'initiateur et un gardien. Le créateur est un objet qui a un état interne. Le gardien va faire quelque chose à l'expéditeur, mais veut pouvoir annuler le changement. Le gardien demande d'abord à l'expéditeur un objet souvenir. Ensuite, il fait n'importe quelle opération (ou séquence d'opérations) qu'il allait faire. Pour revenir à l'état avant les opérations, il renvoie l'objet memento à l'expéditeur. L'objet souvenir lui-même est un objet opaque (celui que le gardien ne peut pas, ou ne devrait pas, changer). Lors de l'utilisation de ce modèle, il convient de veiller à ce que le créateur puisse modifier d'autres objets ou ressources - le modèle de mémento fonctionne sur un seul objet.

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

Informations supplémentaires ici: http://dofactory.com/Patterns/PatternMemento.aspx

Marcelo Assis
la source
2
Je ne vois pas comment cela devrait aider. On dirait que c'est un "retour instantané", tandis que l'OP a demandé quelque chose de lisse comme celui de Braid. Peut-être que j'ai mal lu quelque chose?
o0 '.
Ce modèle n'implique pas sur une seule restauration, vous pouvez créer une "chronologie" d'actions, par exemple. Voici un article de blog de Brazillian sur l'utilisation de ce modèle: abrindoojogo.com.br/padroes-de-projeto-memento Voici un exemple réalisé en Flash: abrindoojogo.com.br/files/fasteroids.swf Move: Arrows | Shoot: Space | Actions de rembobinage: Retour arrière
Marcelo Assis
1

Il y avait un jeu sorti pour la XBox360 qui impliquait la manipulation du temps. C'était médiocre, donc je ne me souviens pas du titre pour le moment. Quoi qu'il en soit, dans une interview avec un développeur pour cela, ils ont décrit comment ils ont géré la manipulation du temps:

Toutes les images X (avec des valeurs plus faibles de X conduisant à une manipulation plus fine), vous prenez un "instantané" du monde du jeu à ce moment-là, et l'associez à un moment dans le jeu.

Tout en jouant normalement dans le jeu, dans le temps, chaque entrée d'une réaction contribue à l'instantané défini à un moment donné dans le futur.

Le monde du jeu itère ensuite entre l'instantané à l'heure actuelle et les images instantanées X à l'avenir.

Ensuite, lorsque vous souhaitez inverser le temps, définissez simplement la direction du temps pour qu'il soit en arrière, afin qu'il itère entre le présent et les images X de l'instantané dans le passé (tout en désactivant la possibilité de créer de futurs instantanés).

Jordaan Mylonas
la source
+1 pour le point sur la granularité des instantanés.
Omar Kooheji du
0

Vous pouvez simplement traiter le temps virtuel du jeu comme une autre dimension semblable à l'espace. Donc, ce qui voyage dans le temps de l'extérieur est un simple mouvement de dimension n + 1 dans l'univers virtuel du jeu.

En supposant une interaction utilisateur et une sorte de système physique qui déterminent le comportement de votre univers lorsqu'il n'y a pas d'entrée utilisateur, tout ce que vous devez enregistrer est l'effet des interactions utilisateur (par exemple, les changements dans les vecteurs vitesse / accélération de dimension n + 1) , car votre physique doit être réversible dans le temps.

De cette façon, vous auriez besoin de beaucoup moins de mémoire pour calculer l'état de l'univers du jeu à n'importe quelle coordonnée temporelle donnée.

biziclop
la source
Comme je l'ai mentionné dans un autre commentaire, la physique dans les jeux vidéo n'est généralement pas réversible dans le temps, car lors de l'utilisation de nombres à virgule flottante, (x+v)-vpeut ne pas être égal àx
BlueRaja - Danny Pflughoeft
0

Disons qu'une entité a une vitesse, une rotation, une position x et y. Ce sont, avec l'accélération, les états de mouvement de base, les valeurs, peu importe comment vous l'appelez. Vous pouvez enregistrer les données de deux manières:
1. Enregistrer la rotation, la position x et y
2. Enregistrer la rotation, la vitesse x et la vitesse y

Si vous avez une vitesse fixe, vous pouvez également enregistrer uniquement la rotation ou enregistrer une seule vitesse pour les deux axes.

L'enregistrement de la rotation est nécessaire dans les jeux, à moins que votre entité n'ait une rotation statique, ce qu'elle n'est pas dans la plupart des cas.

Cela dit, l'utilisation d'une liste d'objets pour plusieurs valeurs est nécessaire. Si vous avez un bon système de minuterie, qui, par exemple, appelle les méthodes de mise à jour 20 fois en une seconde, et est donc indépendant des fps, vous pouvez créer un tableau de 20 * 30 objets pour stocker les valeurs de mouvement dont vous avez besoin pour les 30 dernières secondes . L'utilisation d'un tableau simple n'est pas recommandée, car vous devrez déplacer chaque élément d'un index à gauche de chaque appel de mise à jour.

Sur cette base, vous pouvez parcourir la liste ou quoi que ce soit pour revenir en arrière. Si vous voulez vraiment obtenir un effet "réaliste", utilisez cette technique pour tous les objets en mouvement. Mais c'est lié à la conception de jeux.

Si vous détruisez des objets, n'oubliez pas de les regrouper, afin de ne pas stresser votre bon ami M. Garbage;)

Marco
la source