J’ai fais un algo qui me permet de bouger des sprites sur l’écran, il fonctionne mais pas correctement : si le déplacement est horizontal ou vertical, pas de problème, par contre en oblique, le déplacement ne se fait pas à la bonne vitesse (il est plus lent)
voici comment je m’y prends
' distance à parcourir en metre
distanceX = Absolue( Destination.X - _Position.X)
distanceY = Absolue( Destination.Y - Position.Y)
' correction de la vitesse dans le cas ou la distance à parcourir est plus petite que la vitesse
cSpeed = _Speed
If (distanceX + distanceY) < _Speed Then
cSpeed = _Speed - (distanceX + distanceY)
End If
' On répartit la vitesse en mouvement vers les X et vers les Y :
' Plus la distance à parcourir est grande pour un axe par rapport à l'autre, plus cet axe obtiendra de points de vitesse
pourcentX = distanceX / (distanceX + distanceY)
pourcentY = distanceY / (distanceX + distanceY)
mouvementX = Arrondi(pourcentX * cSpeed))
mouvementY = Arrondir(pourcentY * cSpeed))
' Si l'on se deplace vers le haut ou vers la gauche, on remonte les axes, donc * -1
signeX = 1
signeY = 1
If Destination.X < Position.X Then
signeX = -1
End If
If Destination.Y < Position.Y Then
signeY = -1
End If
' Enfin, on applique le mouvement au sprite
Position.X = Position.X + mouvementX * signeX
Position.Y = Position.Y + mouvementY * signeY
d’après mois le problème vient du fait que lorsque le déplacement est oblique, je bouge d’un certain nombre de pixel vers le haut et d’un certain nombre de pixel vers la droite, ça fait un escalier et l’escalier est plus court que la ligne droite => déplacement ralentit.
Je n’ai pas bien compris ton code (et ta/tes procédures Arrondir/Arrondi) mais à mon avis ton explication est fiable.
Si tu avais simplement incrémenté l’axe X et l’axe Y de la vitesse désirée tu n’aurait sans doute pas eu se problème (à mon avis). En lisant ton code j’ai cru que tu avais voulu rendre les déplacements en diagonale plus lents !
Le truc le plus simple serait d’incrémenter directement les coordonnées de ton sprit sans calculer de pourcentage pour les déplacements sur X et sur Y.
Je sais pas si j’ai bien compris et répondu à ta question. (dis si je suis totalement à côté pour que je puisse me corriger :ane: )
Ce problème me semble assez générique (il est intéressant pour tout programmeur venant de n’importe quel langage de prog). Tu pourrais cependant mettre [Algo] à la place de [Math].
Et sinon mon poste précédent semble être correcte?
Puis ce sont des maths ou de l’algo, même si ici c’est du VB ou du Delphi, ça change rien.
Si on passe en vectoriel, tes deux déplacements sont équivalents; m’est avis que tu devras peut-être réfléchir à une solution spécifique au mouvement en diagonal (je n’ai pas d’idée …)
oui au départ c’est du VB.NET mais j’ai mis ça en forme pour que ça soit compréhensible par tout les programmeurs car c’est pas du code spécifique
Dusty, si j’incrémente l’axe X et l’axe Y alors la vitesse sera accélérée en diagonale, on sera à la boule rose à la place de la boule bleu ( http://users.skynet.be/cyse/dep2.JPG )
et pour mieux expliqué mon système de pourcentage, en faite je prend la vitesse comme des points de déplacement, que je répartis sur l’axe X et Y selon si ils en ont beaucoup besoin ou pas (si la destination finale est très haute mais pas très a droite, alors le code fournira plus de point à Y et moins à X jusqu’a ce qu’il rejoigne la bonne destination)
pas très bien compris ^^
Oui, j’ai une petite idée, genre absolue( mouvementX - vitesse) : j’obtient une valeur qui est grande qu’en diagonale (car en horizontal mouvementX vaut vitesse donc 0.
Donc si je multiplie ça par mouvementX y aurait moyen d’augmenter la vitesse juste en diagonale.
Et l’utilisation de coordonnées polaires (un angle, une distance) ?
Ca ne pourrait pas résoudre ton problème (avec l’utilisation de la trigo pour transmettre trouver la longueur du chemin de ton sprit) ? Le petit (gros?) problème après, c’est la précision de ton algo…
Ce que je proposait auparavant (si on prend le cercle trigonométrique) c’était d’incrémenter bêtement la positions du sprit sur les deux axes en même temps. Mais le chemin parcouru était de racine de 2, ma bille était trop rapide elle devait s’arrêter au cercle (chemin de 1), elle allait trop loin, elle était trop rapide.
Petite question: si tu fais aller ton sprit vers un point à 45 degré du point de départ es-ce que la vitesse est OK? Ou ça pose problème pour tout angle ]0;90[ ?
C’est normal, tu n’as pas de deplacement en diagonale mais uniquement horizontal ou vertical. La longueur d’une diagonale n’est pas la somme des longueurs horizontale ou verticale. La formule exacte pour determiner la longueur de la diagonale est : D^2 = X^2 + X^2
A partir de la tu calcules facilement pourcentX et pourcentY pour avoir un deplacement correct.
Très simple, tu as le point de depart (X,Y) et l’arrivée (DX,DY). Tu determines la distance de cette facon :
DI² = (DX - X)² + (DY - Y)².
Le nombre DI², tu en prend la racine carrée, ca te donne la distance à parcourir DI
En divisant DI par speed tu obtient la durée. Ici, pour toi, le nombre de boucles (attention, ce n’est pas un nombre entier), ce nombre nous l’appelerons T.
T = DI / Speed.
Tu divises ensuite la distance horizontale par T pour savoir combien de pixels tu rajoutes à X à chaque tour, idem pour Y.
dX = (DX - X) / T;
dY = (DY - Y) / T;
A chaque iteration tu fais maintenant :
X = X + dX
Y = Y + dX
Tu fais attention à la dernière iteration pour ne pas depasser ton point d’arrivée (à moins d’avoir arrondi T pour avoir une valeur entière).
Ce n’est pas l’algorithme le plus rapide, mais il a l’avantage d’être universel.
Pour être vraiment universel, il suffit d’obtenir, à partir du point d’origine et du point de destination, l’équation paramétrique de la droite (c’est à dire en fonction d’une variable t).
Soit le point de départ (x0,y0), le point d’arrivée (x1,y1).
On a la position de ton point à l’instant t:
x = x0 + at
y = y0 + bt
Où:
a = (x1-x0)/speed
b = (y1-y0)/speed
En définissant “speed” comme étant le temps que mettra ton point pour aller de (x0,y0) à (x1,y1).
Avec cette méthode, c’est vraiment universel, et tu n’as pas à te soucier d’arrondis.
edit: calcul quand t = speed:
x = x0 + (x1-x0)/speed*speed
donc x=x1, c’est pareil pour y :super:
edit 2: en règle générale, lorsqu’il s’agit de déplacer des trucs à l’écran selon une certaine trajectoire, on essaye d’éviter les itérations style x = x + delta, et de toujours calculer x en fonction de t (temps). Cela permet d’ajuster par exemple le framerate tout en conservant une représentation à l’écran qui soit cohérente avec le temps réellement écoulé. En d’autres termes, visuellement ça ira à la même vitesse quelle que soit la vitesse de l’ordinateur sur lequel le code est exécuté.
edit 3: bien sûr, il y a des cas où cela n’est pas possible, par exemple si tu simules (pour un screensaver par exemple) des boules qui s’attirent mutuellement par les forces gravitationnelles. Là, tu n’as pas d’autre choix que de découper le temps en tranches minuscules et de faire varier les coordonnées des différentes boules petit à petit (i.e. sans équation).
Entre temps j’ai trouvé la solution en utilisation la suggestion de sans-nom avec les vecteurs, mais d’après ce que j’ai lu c’est pas très performant en terme de vitesse.
merci en tout cas des réponses, ça me resservira par la suite
' correction de la vitesse dans le cas ou la distance à parcourir est plus petite que la vitesse
Si mouvementX > Absolue(X - Destination.X) Alors
mouvementX = Absolue(X - Destination.X)
End If
Si mouvementY > Absolue(Y - Destination.Y) Alors
mouvementY = Absolue(Y - Destination.Y)
Fin si
' Nouvelles coordonnées du sprite
X = X+mouvementX
Y = Y+mouvementY
Quand la vitesse prime, la formule n’est pas utilisable. Le calcul en utilisant la formule necessite une multiplicaiton et une addition pour chaque point alors que la methode iterative ne necessite qu’une addition pour chaque point. Le probleme de la precision peut etre compense par la methode de la virgule fixe, qui reste rapide en donnant de bons resultats.