2012-10-10 6 views
1

J'ai posé une question similaire il y a quelques heures, mais je pense qu'il y avait trop d'informations dans cette question, donc j'ai supprimé celle-ci et j'ai rendu celle-ci plus pertinente.La décélération ne fonctionnait pas comme prévu

J'essaie de déplacer un objet avec une accélération décroissante dans un laps de temps spécifié mais l'accélération atteint 0 avant que l'objet n'atteigne la destination.

Je calcule l'accélération comme ceci:

//Linear acceleration starts at 0 and finishes at 2. 
acceleration = this.elapsed/(this.duration/2.0f); 

accélération sera une valeur comprise entre 0 et 2 en fonction du temps écoulé. La valeur sera plus proche de 2 lorsque le temps écoulé est plus proche de la durée (totale).

Donc, pour calculer une décélération que je ferais:

//Linear deceleration starts at 2 and finishes at 0. 
acceleration = 2.0f - this.elapsed/(this.duration/2.0f); 

Cela semble fonctionner très bien, mais l'objet décélérer atteint jamais la destination, à environ 99% de la distance la elapsedTime devient supérieure à la durée totale, provoquant l'accélération à devenir négatif. En d'autres termes, il semble avoir décéléré d'environ 1% trop vite.

L'accélération d'origine fonctionne parfaitement, tout comme la vitesse linéaire. C'est juste la décélération qui ne fonctionne pas correctement.

Est-ce que je fais quelque chose de mal?

Merci

+1

Veuillez préciser les quantités que vous exprimez (accélération, vitesse, déplacement, temps?) Et les unités des variables impliquées. Comme je l'ai lu en ce moment, vous définissez l'accélération = temps/temps, ce qui n'a aucun sens. –

+0

Quels sont les types de données et la durée? Sont-ils aussi flottants ou sont-ils des entiers? – mclark1129

+0

Dans mon code pour le moment la durée est 2000, cela signifie que cela prendra 2 secondes pour que l'objet atteigne la destination. Le temps écoulé correspond au temps écoulé depuis le départ de l'objet. Donc, quand il a bougé pendant 1 seconde, l'accélération serait de 1.0f. Quand il a bougé pendant 0.5f seconde, l'accélération serait de 0.5 etc. Puis je l'inverse pour la décélération, donc après 0.5 secondes l'accélération serait 1.5f si l'objet décélère. Cela me donne une accélération moyenne de 1.0 pour qu'il atteigne la destination en même temps que l'objet sans accélération. – Orujimaru

Répondre

1

Sans voir votre code complet, je pense que le problème est probablement dû à l'utilisation d'un float comme variable d'itération dans une boucle for quelque part. En utilisant le programme suivant à titre d'exemple, je suis capable de répliquer que la précision en virgule flottante est quelque peu foirée quelque part dans la boucle quand j'essaie d'utiliser directement la float comme variable d'itération.

float duration = 10f; 

for(float elapsed = 0.0f; elapsed <= duration; elapsed = elapsed + 0.1f) { 
    Console.WriteLine(2.0f - elapsed/(duration/2.0f)); 
} 

Console.ReadLine(); 

La sortie de ce programme est:

2 
1.98 
1.96 
1.94 
1.92 
1.9 
1.88 
1.86 
1.84 
1.82 
1.8 
1.78 
1.76 
1.74 
1.72 
1.7 
1.68 
1.66 
1.64 
1.62 
1.6 
1.58 
1.56 
1.54 
1.52 
1.5 
1.48 
1.46 
1.44 
1.42 
1.4 
1.38 
1.36 
1.34 
1.32 
1.3 
1.28 
1.26 
1.24 
1.22 
1.2 
1.18 
1.16 
1.14 
1.12 
1.1 
1.08 
1.06 
1.04 
1.02 
1 
0.9800005 
0.9600005 
0.9400005 
0.9200006 
0.9000006 
0.8800006 
0.8600006 
0.8400006 
0.8200006 
0.8000007 
0.7800007 
0.7600007 
0.7400007 
0.7200007 
0.7000008 
0.6800008 
0.6600008 
0.6400008 
0.6200008 
0.6000009 
0.5800009 
0.5600009 
0.5400009 
0.5200009 
0.500001 
0.480001 
0.460001 
0.440001 
0.420001 
0.400001 
0.3800011 
0.360001 
0.3400009 
0.3200008 
0.3000008 
0.2800007 
0.2600006 
0.2400005 
0.2200005 
0.2000004 
0.1800003 
0.1600002 
0.1400001 
0.1200001 
0.1 
0.07999992 
0.05999985 
0.03999977 
0.01999969 

Vous pouvez voir que à mi-chemin de la précision tire sortie, et parce que la précision de la variable d'itération se fait défoncer vers le haut.

Dans le deuxième exemple, j'utilise à la place une variable d'itération integer et je redimensionne simplement le integer à mon calcul à l'intérieur de chaque itération. Cela empêche la variable d'itération d'aller tout çela:

float duration = 10f; 
float offset_scale = 10.0f; 

for (int elapsed = 0; elapsed <= (duration * offset_scale); elapsed++) { 
    Console.WriteLine(2.0f - (elapsed/offset_scale)/(duration/2.0f)); 
} 

Console.ReadLine(); 

La sortie de ce programme est:

2 
1.98 
1.96 
1.94 
1.92 
1.9 
1.88 
1.86 
1.84 
1.82 
1.8 
1.78 
1.76 
1.74 
1.72 
1.7 
1.68 
1.66 
1.64 
1.62 
1.6 
1.58 
1.56 
1.54 
1.52 
1.5 
1.48 
1.46 
1.44 
1.42 
1.4 
1.38 
1.36 
1.34 
1.32 
1.3 
1.28 
1.26 
1.24 
1.22 
1.2 
1.18 
1.16 
1.14 
1.12 
1.1 
1.08 
1.06 
1.04 
1.02 
1 
0.98 
0.96 
0.94 
0.92 
0.9 
0.88 
0.86 
0.84 
0.82 
0.8 
0.78 
0.76 
0.74 
0.72 
0.7 
0.68 
0.66 
0.64 
0.62 
0.6 
0.58 
0.56 
0.54 
0.52 
0.5 
0.48 
0.46 
0.44 
0.42 
0.4 
0.38 
0.36 
0.34 
0.32 
0.3 
0.28 
0.26 
0.24 
0.22 
0.2 
0.18 
0.16 
0.14 
0.12 
0.1 
0.08 
0.06 
0.04 
0.02 
0 

Vous pouvez voir que la précision ne devient fou, et le résultat finit juste à 0.

+0

C'est un très bon appel, et je pense que cela pourrait être mon problème. Mais je ne suis pas sûr de savoir comment y remédier puisque j'utilise la boucle de jeu de XNA. J'ai essayé de changer les flotteurs pour ints/doubles/decimals sans succès. L'accélération/constante fonctionne toujours bien quelle que soit la valeur que j'utilise, mais la décélération ne fonctionne jamais. Cependant, j'ai trouvé une solution, lorsque le temps écoulé atteint la durée que je force la valeur au maximum (maintenant l'objet ne se désynchronise pas et le saut à la fin n'est pas visible du tout, puisque c'est seulement> 1 %). Je vais quand même choisir votre réponse, je pense que ça peut aider les autres. – Orujimaru

+0

Je voulais ajouter que la même chose se produit probablement pour l'accélération: l'accélération dépasse probablement 2.0 de la même quantité que la décélération rate 2.0. Mais je ne remarquerais pas l'accélération dépassant 2.0 puisqu'elle atteint sa cible de toute façon. Est-il possible que cela ait quelque chose à voir avec GameTime de XNA? – Orujimaru

1

Vous pouvez essayer d'utiliser la fonction C# de serrage pour les flotteurs: http://msdn.microsoft.com/en-us/library/microsoft.xna.framework.mathhelper.clamp.aspx

acceleration = MathHelper.Clamp(2.0f - this.elapsed/(this.duration/2.0f), 0.0, 2.0); 

Il suffit simplement de définir une valeur min et max pour la première COMMUT.

+0

Merci pour la suggestion, je ne savais pas à propos de MathHelper. Cela rend les autres parties de mon code beaucoup plus propres. Mais je crains que cela n'ait pas résolu mon problème. L'objet n'atteint toujours pas la destination. – Orujimaru

Questions connexes