Comment coder Time Stop ou Bullet Time dans un jeu?

11

Je suis en train de développer un jeu de plateforme RPG solo dans XNA 4.0. Je voudrais ajouter une capacité qui ferait arrêter ou ralentir le temps, et que seul le personnage du joueur bouge à la vitesse d'origine (similaire au sort Time Stop de la série Baldur's Gate). Je ne recherche pas une implémentation exacte, plutôt des idées générales et des modèles de conception.

EDIT: Merci à tous pour l'excellente contribution. J'ai trouvé la solution suivante

    public void Update(GameTime gameTime)
        {

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

ou quelque chose dans ce sens. De cette façon, je peux définir une heure différente pour le composant joueur et différente pour le reste. Ce n'est certainement pas assez universel pour fonctionner pour un jeu où le temps de déformation comme celui-ci serait un élément central, mais j'espère que cela devrait fonctionner pour ce cas. Je n'aime pas du tout le fait qu'il couvre la boucle de mise à jour principale, mais c'est certainement le moyen le plus simple de le mettre en œuvre. Je suppose que c'est essentiellement la même chose que le tesselode a suggéré, donc je vais lui donner la coche verte :)

David Miler
la source

Réponses:

8

Cela pourrait être une mauvaise solution, mais pas nécessairement. Si vous utilisez le temps delta, vous pouvez changer cela pour changer la vitesse de certaines choses.

Par exemple:

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

Bien sûr, cela ne fonctionne que si vous pouvez savoir quand vous mettez à jour l'ennemi plutôt que quelque chose d'autre. Vous pouvez également donner à tout une valeur de vitesse et faire quelque chose comme:

x = x + xspeed * dt * speed
tesselode
la source
La première partie est parfaitement logique, la deuxième partie n'est pas claire
AturSams
2
Donnez simplement à chaque objet qui déplace une variable de vitesse que vous pouvez modifier, et lorsque vous avez une transformation (de x, par exemple), multipliez la magnitude par la variable de vitesse.
tesselode
Ça a du sens maintenant. :)
AturSams
La deuxième idée sonne ... off. Une simple mise à l'échelle du mouvement par le facteur "vitesse" peut fonctionner pour les objets mus par la physique, mais l'IA pourrait réagir à une vitesse normale, avec seulement leur mouvement ralenti / altéré.
Que voulez-vous dire que l'IA serait capable de réagir à vitesse normale? Quel code aurait l'IA qui ne pourrait pas avoir une variable de vitesse appliquée?
tesselode
3

L'utilisation du temps delta (millisecondes qui se sont écoulées depuis la dernière image) peut ne pas être suffisante pour ralentir les ennemis. Des choses comme le taux d'attaque peuvent être implémentées en fonction du dernier temps d'attaque. Bien qu'il ralentisse le mouvement s'il est basé sur le temps, il néglige de ralentir le taux d'attaque, le lancement de sorts et d'autres effets (régénération de la santé, durée des effets des sorts) .. et autres

Si vous voulez ralentir un grand groupe d'éléments de jeu dans une partie solo, vous pouvez créer une deuxième horloge interne pour chaque créature, l'horloge démarre à l'heure actuelle lorsque la créature apparaît. Lorsqu'un sort lent est lancé, à chaque image, l'horloge est incrémentée de x% du temps qui s'est réellement écoulé. Tout comportement de monstre est alors déterminé par son horloge interne. Si différents monstres ont une résistance à ralentir, ils peuvent utiliser leur propre horloge, c'est fondamentalement un entier qui ne nécessite pas beaucoup d'espace ou de calcul.

Lorsque l'effet lent s'arrête, les horloges sont toujours utilisées et sont incrémentées de 100% du temps qui s'est réellement écoulé.

Cela pourrait également fonctionner pour les sorts de hâte.

@Sidar: Je vois deux choix,

  1. Horloge interne par créature. Pour savoir si la créature est prête à attaquer à nouveau: enregistrez la dernière fois que chaque attaque a été utilisée + temps de recharge et vérifiez si l'horloge interne est déjà passée à ce moment-là.

  2. Un chronomètre par attaque: vous savez combien de temps il faut à l'attaque pour se recharger et vous réglez simplement un chronomètre et soustrayez le temps écoulé * (1-% de ralentissement) à chaque tour.

Personnellement, je préfère éviter de soustraire plusieurs minuteries individuelles et d'utiliser une horloge interne pour économiser sur le temps de traitement et la complexité.

C'est vraiment à la préférence (cela n'affecte pas beaucoup les performances).

AturSams
la source
Le besoin d'horloges internes n'est pas nécessaire. Cela se résume simplement à un multiplicateur que vous pouvez (en quelque sorte) lier à votre objet qui augmente ou diminue le produit de votre dt (temps delta). Vous pouvez gérer les objets par groupes ou par tout autre moyen. Je pense que votre chemin pourrait être un peu excessif. Mais bon si ça marche ... alors ça marche.
Sidar
@Sidar Si vous évitez cela, vous aurez probablement besoin d'une horloge par attaque juste pour chronométrer la recharge de l'attaque, la durée des sorts et autres choses. Au moins de cette façon, il vous suffit de mettre à jour une horloge et de simplement conserver l'heure de la «dernière activation» pour la réinitialisation des propriétés.
AturSams du
Cependant, sa question concerne le ralentissement de l'environnement, à l'exception du joueur. Pour moi, cela ressemble à la forme la plus simple de simplement multiplier le dt avec un nombre inférieur à 1. Tout en le conservant tel quel pour le joueur.
Sidar
Eh bien, le ralentissement des environnements comprend le ralentissement de leur taux d'attaque ainsi que leurs autres capacités (car c'est un rpg), il pourrait y avoir diverses capacités de mob qui dépendent du temps de recharge. Soins, buffs, debuffs, sorts et etc. Sans parler du temps d'activation.
AturSams
2

Vous pouvez commencer avec une solution simple comme celle exposée par tesselode ou Mr Beast. Mais si vous commencez à mélanger des choses complexes, c'est-à-dire un temps de balle pendant qu'un sort de ralentissement est lancé, vous serez coincé.

Je vous suggère d'implémenter une hiérarchie d'horloge :

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

Tout dans votre jeu doit utiliser les temps delta de l'une des horloges: les effets graphiques s'exécutent sur l'horloge GFX, l'IA et l'animation s'exécutent sur l'horloge de gameplay, les créatures affectées par un sort de ralentissement s'exécutent sur une horloge de sort de ralentissement temporaire, etc. affecter différentes parties de votre hiérarchie: un sort de ralentissement crée et affecte une horloge personnalisée, tandis qu'un temps de balle affectera toute la hiérarchie d'horloge 3D.

Laurent Couvidou
la source
Merci, c'est un aperçu important. Cependant, je pense que je vais garder la pensée simple, car cela n'a pas de sens dans mon cas particulier que plusieurs effets de ralentissement se produisent en même temps.
David Miler
1

Vous avez juste besoin de deux horloges différentes au lieu d'une, une pour l'heure pertinente au gameplay et une "vraie" heure.

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

Ensuite, vous pouvez simplement changer gameSpeed ​​pour accélérer (> 1) ou ralentir le temps (<1). Pour que le joueur se déplace à une vitesse différente, vérifiez simplement si le temps est ralenti ou non.

API-Beast
la source