Communauté

Comment faire en so...
 
Notifications
Retirer tout

Comment faire en sorte que la vitesse diagonale de notre joueur soit la même que pour les 4 directions classiques (up,down,left,right) ?

5 Posts
4 Utilisateurs
0 Reactions
397 Vu
0
Début du sujet

Salut tout le monde:), je suis inscrit depuis 2 mois à la formation de Gamecodeur, j'avance plutôt bien et je vois que je progresse; mais je bloque sur un point depuis une semaine maintenant...

Comme indiqué dans le titre je souhaite que mon personnage ait la même vitesse en ligne droite qu'en diagonale. J'ai compris que d'après le théorème de Pythagore, la vitesse est plus élevée car elle est égale à vitesse * math.sqrt(2) et qu'il faudrait la normaliser, j'ai donc compris la théorie mais j'ai du mal à la mettre en pratique même en connaissant les formules😅.

 

Je précise aussi qu'avant de poser ma question, j'ai essayé plusieurs solutions, chercher sur stackoverflow,github,etc..., sur le forum de Gamecodeur, suivi l'atelier Maths pour jeux vidéos mais je n'ai rien trouvé pour l'instant. Si la question a déjà été posée et qu'il y a les réponses quelque part d'autre, je m'excuse d'avance du dérangement.

 

Samy.

4 Réponses
0

@samy_the_grappler Bonsoir,

Il faut jouer avec les cos() et sin() de l'angle du personnage.

Dans un cercle trigonométrique ça donnerai ceci:

Par exemple, pour un déplacement basique, en pseudo code:

Si la touche pour avancer est active alors
		abscisse du personnage = abscisse du personnage + cos(angle du personnage)
		ordonnée du personnage = ordonnée du personnage + sin(angle du personnage)
Fin si

afficher le personnage (en abscisse du personnage, ordonnée du personnage)

 

De tête et à la volée, ça me semble fonctionner.

En espérant que ça aide.

Bonne soirée.

 

Ce message a été modifié Il y a 1 an parMythicMike@1984
0
Début du sujet

Salut @MythicMike@1984 😁,

 

Merci pour ta réponse, effectivement la trigo. marche même si je fixe des valeurs à 45°, et j'ai réussi à trouver une autre solution (en utilisant le théorème de Pythagore) juste après avoir lu ton message, je vais la poster car ça pourra toujours servir pour d'autres personnes.

function love.load()
 
player = {}
player.x = 200
player.y = 200
player.speed = 3
 
end
 
 
function love.update(dt)

local dx, dy = 0, 0

if love.keyboard.isDown("left") then
    dx = dx - 1
end
if love.keyboard.isDown("right") then
    dx = dx + 1
end
if love.keyboard.isDown("up") then
    dy = dy - 1
end
if love.keyboard.isDown("down") then
    dy = dy + 1
end

if dx ~= 0 or dy ~= 0 then
local length = math.sqrt(dx^2 + dy^2)
  player.x = player.x + (dx / length) * player.speed
  player.y = player.y + (dy / length) * player.speed
end

end
 
function love.draw()
love.graphics.circle("fill",player.x,player.y, 15)
end

Mon WE aura été productif ahah, encore merci à toi.

0

You're welcome ...

Merci pour le partage de ton implémentation.

L'utilisation des angles et des cos() et sin() associés permet par exemple de contrôler un déplacement de type de celui du vaisseau dans "asteroids" (i.e. pivoter à gauche, pivoter à droite et propulsion), alors qu'il me semble que ton implémentation adresse un déplacement su 8 directions (i.e. haut, haut-gauche, gauche, gauche-bas, bas, bas-droite, droite et droite-haut).

A chaque tour de boucle on va avoir les alternatives suivantes:

  1. dx = 0 et dx = 0, facile, dans ce cas on ne bouge pas (on ne rentre pas dans la condition "if dx ~= 0 or dy ~= 0"),
  2. dx = 1 et dy = 0, mouvement horizontal, on rentre de la condition "if dx ~= 0 or ..." , sqrt(1) = 1 et donc dx/sqrt(1) = 1
  3. dx = 1 et dy = 1, mouvement diagonal (45°), on rentre de la condition "if dx ~= 0 or ...", sqrt(2) = 1.414213xxxx et donc dx/sqrt(2) = dy/sqrt(2) = 1/1.414213xxxx = 0.707106xxx (soit le même résultat que cos(45) ou sin(45))
  4. dx = 0 et dy = 1, mouvement vertical, on rentre de la condition "if dx ~= 0 or ..." , sqrt(1) = 1 et donc dy/sqrt(1) = 1

Pour optimiser, dans ce cas de figure (i.e. déplacement 8 directions) on peut stocker en constante la valeur 0.707106xxx qui n'aura besoin d'être calculée qu'une seule fois et on pourra se passer du calcul systématique de la racine carrée et de la division par cette dernière.

C'est d'ailleurs vrai pour un déplacement de type "asteroids" également. On peut imaginer ne pivoter que sur un nombre déterminé d'angles, calculer une seule fois les valeurs des cos() et sin() pour chacun des angles et les stocker dans un tableau dont on pourra accéder aux valeurs par l'intermédiaire de l'index qui représenterai les fameux angles.

Bonne fin de journée.

 

 

 

 

 

 

 

 

AlbanR 04/04/2023 7:50

@mythicmike1984 Oui, le problème est que lorsque tu fais un déplacement dans une seule direction (verticale ou horizontale), la norme de ton vecteur direction est de 1. Mais dès que tu te déplace d'un vecteur qui est une combinaison de ces deux déplacements, tu obtiens une norme supérieure à 1, typiquement racine carrée de 2 pour un angle à 45°.

Pour normer un vecteur, c'est à dire conserver sa direction mais en faisant en sorte que sa norme soit toujours 1, il suffit de le diviser par sa norme.

Calculer la norme d'un vecteur revient à calculer une distance et c'est donc une application directe du théorème de Pythagore.

Si le vecteur a pour coordonnées (x, y), alors sa norme vaut: l = sqrt(x*x + y*y).

Les coordonnées du même vecteur normalisé: (x/l, y/l).

Attention au cas où la norme vaudrait 0 ...

ça marche en 3D aussi.

0

Le plus simple :

local norm = math.sqrt(dX * dX + dY * dY)
dX = dX / norm
dY = dY / norm
Répondre
Share:

Dialoguez avec les autres membres de la gamecodeur school.

Accédez maintenant à notre serveur Discord privé : Entraide, Game Jams, Partage de projets, etc.

Vous devez être membre de la Gamecodeur School Premium pour être autorisé à accéder au serveur.