Mouvement indépendant du cadre


11

J'ai lu deux autres fils ici sur le mouvement: Mouvement basé sur le temps Vs Mouvement basé sur la fréquence d'images? et quand dois-je utiliser un pas de temps fixe ou variable?

mais je pense que je manque d'une compréhension de base du mouvement indépendant du cadre parce que je ne comprends pas de quoi parle l'un de ces fils.

Je suis avec les tutoriels SDL de lazyfoo et suis tombé sur la leçon indépendante du cadre. http://lazyfoo.net/SDL_tutorials/lesson32/index.php

Je ne suis pas sûr de ce que la partie mouvement du code essaie de dire, mais je pense que c'est cela (veuillez me corriger si je me trompe): Afin d'avoir un mouvement indépendant du cadre, nous devons savoir jusqu'où un objet ( ex. sprite) se déplace dans un certain laps de temps, par exemple 1 seconde. Si le point se déplace à 200 pixels par seconde, je dois calculer combien il se déplace dans cette seconde en multipliant 200 pps par 1/1000 de seconde.

Est-ce correct? La leçon dit:

"vitesse en pixels par seconde * temps depuis la dernière image en secondes. Donc si le programme fonctionne à 200 images par seconde: 200 pps * 1/200 secondes = 1 pixel"

Mais ... je pensais que nous multiplions 200 pps par 1 / 1000ème de seconde. Quelle est cette activité avec des images par seconde?

J'apprécierais que quelqu'un puisse me donner des explications un peu plus détaillées sur le fonctionnement du mouvement indépendant du cadre.

Je vous remercie.

UNE ADDITION:

SDL_Rect posRect;
posRect.x = 0;
posRect.y = 0;

float y, yVel;
y = 0;
yVel = 0;

Uint32 startTicks = SDL_GetTicks();

bool quit = false;
SDL_Event gEvent;

while ( quit == false )
{
    while ( SDL_PollEvent( &gEvent ) )
    {
        if ( gEvent.type == SDL_QUIT )
            quit = true;
    }

    if ( y <= 580 )
    {
        yVel += DOT_VEL;
        y += (yVel * (SDL_GetTicks() - startTicks)/1000.f);
        posRect.y = (int)y;
    }

    startTicks = SDL_GetTicks();
    SDL_BlitSurface( bg, NULL, screen, NULL );
    SDL_BlitSurface( dot, NULL, screen, &posRect );
    SDL_Flip( screen );
}

C'est du code qui déplace un point sur l'écran. Je pense que tout est correct jusqu'à présent. Il descend sur l'écran mais il y a une chose étrange que je ne peux pas expliquer. Le point est censé rester à y = 580 lorsqu'il atteint une valeur supérieure à cette valeur y. Cependant, chaque fois que j'exécute le programme, le point se retrouvera à un endroit différent, ce qui signifie un peu plus de 580, donc le point est à mi-chemin ou à mi-chemin de l'écran (le point fait 20 pixels, écran dimensions 800x600). Si je fais quelque chose comme cliquer et maintenir la barre de titre du programme, puis relâcher, le point disparaît de l'écran. Comment se fait-il que cela soit variable à chaque fois? En ce qui concerne le problème de la barre de titre, je pense que c'est parce que lorsque je m'accroche à la barre de titre, le chronomètre fonctionne toujours et le temps écoulé augmente, résultant en une plus grande distance, le point se déplace dans l'image suivante. Est-ce correct?


Votre ajout est en fait une autre question. Vous devriez en faire une deuxième question au lieu de l'ajouter à votre question existante. Il peut être répondu facilement cependant: calculez simplement le mouvement y, par exemple. yMovement = (yVel * (SDL_GetTicks() - startTicks)/1000.f);alors faites:if(y + yMovement <= 580){ y += yMovement; } else { y = 580; }
bummzack

Réponses:


10

REMARQUE: Toutes les fractions sont censées être des flottants.

Le mouvement indépendant du cadre fonctionne en basant le mouvement hors du temps. Vous obtenez le temps passé depuis la dernière image (donc s'il y a 60 images en une seconde, chaque image prend 1,0 / 60,0 secondes, si toutes les images ont pris le même temps) et découvrez combien de mouvement cela se traduit par.

Si vous voulez que votre entité déplace une certaine quantité d'espace pour une unité de temps spécifiée (nous dirons 100 pixels pour chaque seconde de temps), alors vous pouvez savoir combien de pixels vous devez déplacer par image en multipliant la quantité de mouvement par seconde (100 pixels) par le temps écoulé en secondes (1,0 / 60,0) afin de déterminer la quantité de mouvement qui doit avoir lieu dans l'image actuelle.

Il fonctionne en déterminant la quantité de mouvement que vous devez effectuer par image en utilisant le temps écoulé et une vitesse définie avec une certaine unité de temps (les secondes ou les millisecondes sont préférables). Ainsi, votre calcul pourrait ressembler à:movementPerSecond * (timeElapsedInMilliseconds / 1000.0)

J'espère que cela vous a semblé logique.

Je veux déplacer mon gars de 200 pixels vers la droite chaque seconde. Si l'image actuelle est exécutée 50 millisecondes après l'image précédente, je devrais déplacer mon gars d'une fraction de la vitesse précédemment spécifiée (qui était de 200 pixels). Je devrais le déplacer 50 / 1000ème de la distance car seul un 1 / 20ème (50/1000 = 1/20) de temps s'est écoulé. Par conséquent, il serait logique de ne le déplacer que de 10 pixels (si 19 images supplémentaires se produisaient, à 50 millisecondes les unes des autres, alors la quantité totale de mouvement dans cette seconde serait de 200 pixels, la quantité que nous voulions).

La façon dont le mouvement indépendant des images fonctionne est que les images se produisent généralement à des pas de temps variables (il y a une quantité de temps différente qui a lieu entre les images suivantes). Si nous déplaçons constamment une entité à une distance constante à chaque image, le mouvement est basé sur la fréquence d'images. S'il y a beaucoup de temps entre les images, le jeu semblera se déplacer trop lentement et s'il n'y a pas beaucoup de temps entre les images, le jeu semblera aller trop vite. (trop peu de temps entre les images = beaucoup d'images = plus de mouvement) Pour surmonter cela, nous utilisons une vitesse en termes de temps et gardons une trace du temps entre les images. De cette façon, nous savons combien de temps s'est écoulé depuis la dernière mise à jour de la position et à quel point nous devons déplacer l'entité.

Images par seconde: il s'agit de la quantité d'images qui ont lieu par seconde. Habituellement, une fréquence d'images est le nombre de fois où le jeu est dessiné / rendu une seconde ou combien de fois la boucle de jeu est terminée une seconde.

Pas de temps variable de vers fixe: il s'agit de la durée entre les images. Habituellement, le temps entre les images ne sera pas constant. Certains systèmes / cœurs comme la physique auront besoin d'une certaine unité de temps pour simuler / exécuter quelque chose. Habituellement, les systèmes physiques sont plus stables / évolutifs si le pas de temps est fixe. La différence entre les pas de temps fixes / variables réside dans les noms. Les pas de temps fixes sont ce à quoi ils ressemblent: des pas de temps qui se produisent à un rythme fixe. Les pas de temps variables sont des pas de temps qui se produisent à des taux de temps variables / différents.


Dans l'exemple que vous donnez, 50 millisecondes est le temps pour chaque image, n'est-ce pas? Et cela a été calculé par 1000 / FPS? Et donc le mouvement dont vous avez besoin pour faire chaque image est de pixels par seconde * 50/1000?
ShrimpCrackers

hm, je me suis rendu compte que les millisecondes pour chaque période seraient probablement variables, non? Quelque chose comme getTicks () - startTicks serait toujours différent et non constant.
ShrimpCrackers

@Omnion: Si vous spécifiez la distance en "pixels par seconde", vous ne pouvez pas utiliser les millisecondes ... elle devrait être de 1,0 / 60,0 et non de 1000/60, ce qui entraînerait quelque chose de complètement différent.
bummzack

@ShrimpCrackers oui, le temps écoulé change. Imaginez un PC plus ancien qui n'est pas capable de rendre 60 ips. Vous voulez toujours que le jeu fonctionne à la même vitesse (mais pas aux mêmes images par seconde) sur une telle machine.
bummzack

alors, alors dans le tutoriel lazyfoo, que signifie le 1000 dans deltaticks / 1000.f? FPS? 1000 millisecondes? Je suis un peu confus en ce moment. Il semble que le FPS soit nécessaire pour déterminer le temps requis pour chaque image, mais qu'il ne se calcule pas réellement dans le mouvement.
ShrimpCrackers

7

Dans la dynamique de trame, votre code pour (par exemple) déplacer une entité ressemblerait à ceci:

x = x + speedPerFrame

Si vous voulez être indépendant du cadre, cela pourrait ressembler à ceci:

x = x + speedPerSecond * secondsElapsedSinceLastFrame

merci, cela a du sens. J'ai une autre question ci-dessus.
ShrimpCrackers

1

Concernant la question supplémentaire.

Votre point s'arrête à des endroits différents à chaque fois parce que vous ne vérifiez pas la limite (y> 580) lorsque vous la déplacez. Vous n'arrêtez plus de le mettre à jour une fois ses 580 passés.

Sur la dernière image avant de traverser 580, vous pourriez commencer à partir de 579 ou vous pourriez être à 570 ou vous pourriez être à 100. Vous pouvez également avancer de 1 pixel ou 1000, selon le temps que la dernière image a pris pour s'exécuter.

Changez simplement votre condition IF en quelque chose comme ça et ça devrait aller.

if ( y <= 580 )
{
    yVel += DOT_VEL;
    y += (yVel * (SDL_GetTicks() - startTicks)/1000.f);
    if( y > 580 )
    {
        y = 580;
    }
    posRect.y = (int)y;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.