2010-03-21 3 views
3

Je fais un petit jeu sur l'iphone, et j'obtiendrais quelques indices. Imaginez:Bon moyen de faire des animations avec Cocos2D?

Deux sprites de fond se déplaçant assez rapidement de droite à gauche et se déplaçant de haut en bas avec un accéléromètre.

Je suppose que je ne peux pas utiliser d'animations ici, car le mouvement de l'arrière-plan est recalculé à chaque image. donc j'utiliser un calendrier avec un intervalle de 0.025s et déplacer mes sprites à chaque horloge avec:

sprite.position = ccp(x, y); 

Voici mon problème: le résultat est laggy, avec seulement ces deux sprites.

J'ai essayé à la fois de déclarer des sprites dans l'en-tête et de les obtenir avec CCNodes et Tags. C'est pareil. Donc, si quelqu'un peut me donner un indice sur la meilleure façon de le faire, ce serait tellement agréable. Je me demande si le problème ne peut pas être le fait que les sprites se déplacent très rapidement, mais je ne suis pas sûr.

En tout cas, merci pour votre temps.

J.

Répondre

3

0,025 est égal à 40 images par seconde, qui pourrait être un peu raide en fonction du reste de la boucle de jeu. Il est bon de penser à la relation entre le framerate et la vitesse perçue. Lorsque vous augmentez le framerate, vous rendez le mouvement plus fluide, mais seulement tant que vous savez comment calculer le mouvement. Si vous déplacez les objets avec une distance fixe à chaque tick de l'heure, ils bégayeront, car la minuterie n'est pas précise. (Pensez-y: 40 fps signifie 25 ms par image.Quand la minuterie s'éteint de cinq millisecondes - pas très bien, n'est-ce pas? -, vous changez le temps de trame de 20 pour cent.Il n'est pas inhabituel pour les événements de temps à obtenir off de 10-20 ms.)

Cela signifie que vous devez calculer le delta en temps réel à partir de la dernière image et déplacer les objets en fonction. Un peu comme ceci:

const int kDesiredModelFramerate = 50; // fps 
const double kDesiredFrameTime = 1.0/kDesiredModelFramerate; 

double now = CFAbsoluteTimeGetCurrent(); 
double delta = now - lastFrameTime; 
double correction = delta/kDesiredFrameTime; 
[object setX:object.x + step*correction]; 

Cela semble compliqué, mais n'est pas. Quand il a fallu 40 ms à partir de la dernière image, vous savez que vous avez une image "en retard", puisque pour garder le framerate souhaité de 50 fps, vous souhaitez garder chaque image inférieure à 20 ms. Par conséquent, le correction sera 0,04/0,02 = 2 et l'étape de mouvement habituelle sera multipliée par 2 pour compenser le décalage. Maintenant vous pouvez changer le framerate comme vous voulez - la vitesse perçue du mouvement restera la même, seule la douceur du mouvement changera.

<voice class="Simon Peyton Jones"> Est-ce que cela a du sens? </voice>

Il existe un great article about game loops où vous pouvez lire à ce sujet plus en détail. C'est un must pour les programmeurs de jeux. La façon exacte de réaliser tout cela dans Cocos2D peut varier, mais le point reste le même. Obtenir ce problème devrait vous aider à faire avancer les choses en douceur et rapidement.

+0

Très bien. Vous vous êtes fait clair et je vois maintenant où je dois mener. Cet article est très utile en effet. Merci! –

1

Si vous utilisez Cocos2D et que vous avez besoin de trouver le temps écoulé depuis le début du "jeu", il est préférable d'utiliser time_elapsed comme indiqué ci-dessous. Beaucoup d'autres méthodes que j'ai essayées retournent une variable DOUBLE très haute valeur, qui cause plus de problèmes dans la précision de conversion double-à-flottante.

faire des changements dans la fonction "tique" dans les scènes Cocos2D CCLayer

-(void) tick: (ccTime) dt 
{ 
    static float time_elapsed = 0.0; 
    time_elapsed += dt; 

    ... 

    float velocity = 5.0f * cosf(time_elapsed * 2 * M_PI) ; 
    jPrism->SetMotorSpeed(velocity); 
}