Les membres ayant 30 points peuvent parler sur les canaux annonces, projets et hs du chat.

Forum Casio - Autres questions


Index du Forum » Autres questions » [C][RESOLU] Moteur physique (trajectoire)
Kirafi Hors ligne Membre Points: 2174 Défis: 10 Message

[C][RESOLU] Moteur physique (trajectoire)

Posté le 03/02/2017 16:58

Salut .

J'ai du mal à créer un moteur physique basique...
Mes connaissance de physique remonte à loin.
M'enfin, j'ai tout de même retrouver des formules.

Le soucis c'est que en C je n'arrive pas à faire quelques choses de correct (alors que j'ai réussi en basique) !

J'aimerais obtenir des fonctions permettant donner et gérer des trajectoires à des objets, en fonction d'une vitesse et d'un angle initial.
La collision seulement objet / sol, avec une constante de gravité.
Et en bonus des rebonds et des masses (c'est la que je bloque surtout).

Pour l'instant j'avais un truc de la forme :
// Retourne VRAI si l'objet o possède une trajectoire (mouvement)
int trajectory(const struct Obj *o);

// Termine la trajectoire de l'objet o (stoppe l'objet, généralement au sol)
void end_trajectory(struct Obj *o);

// Initialise la trajectoire de l'objet o, en fonction des vitesse d'abscisse vx et d'ordonnée vy
void start_trajectory(struct Obj *o, const double vx, const double vy);

// Actualise les coordonnées de l'objet o en fonction de sa trajectoire (vx, vy)
// Seule la gravité est prise en compte (unique accélération verticale)
void refresh_trajectory(struct Obj *o);


La dernière fonction est donc celle qui est appelée à chaque frame dans mon moteur, qui tourne à... hum 25fps ?
#define MS_ENGINE 25
SetTimer(ID_USER_TIMER1, MS_ENGINE, engine);


Dans un premier temps déjà je pense modifier les paramètres de "start_trajectory" pour remplacer par l'angle et la vitesse .

Malheureusement tout ça ne fonctionne pas correctement.
J'effectue actuellement mes tests avec un personnage qui saute.
Avec des paramètres d'angle de 90 degrés = PI/2 radian, saut vertical donc, ça, ça marche.
Pas là peine que je parle de la vitesse car ça par contre, ça fait n'importe quoi...

En fait au final j'aimerais que le personnage saute, enfin, se déplace verticalement de 4 pixels vers le haut lors de la première frame de sa trajectoire, puis commence à chuter lors de la 2nd frame.
Il faut donc choisir une constante de gravitation correcte, et choisir la vitesse qui correspond à ce mouvement.
Et effectuer les bons calculs pour obtenir tout ça.

Voilà voilà, votre aide serait la bienvenue, au plaisir .


Lephenixnoir Hors ligne Administrateur Points: 20789 Défis: 143 Message

Citer : Posté le 03/02/2017 18:29 | #


Ton timer s'actualise toutes les 25 ms là, soit 40 FPS. Note que le délai ne peut être que multiple de 25 (il est arrondi -tronqué ?- sinon) donc tu as soit 40 FPS, soit 20 FPS pour les fréquences les plus élevées.

Il faut nous montrer ton code si tu veux plus de détails. On pourrait te sortir un programme préfait mais je suis pas sûr que ça t'aide.
Kirafi Hors ligne Membre Points: 2174 Défis: 10 Message

Citer : Posté le 03/02/2017 18:36 | #


Alors J'ai fais quelques modification, mais en réalisant quelques calculs à la main, ce n'était pas logique d'avoir ce mouvement de saut de 4 pixels pour retomber instantanément, au final pour le personnage j'ai fait une exception, le moteur n'agit pas vraiment sur lui.

Par contre je vais en avoir besoin pour les principaux objets concerné.

Voici mes fonctions concernées en l'état actuel des choses
#define GRAVITY 4

#define ANGLE_CONVERT 0.01745329252 // PI/180

double rad(const int a)
{
    return a*ANGLE_CONVERT;
}

// Retourne VRAI si l'objet est au sol, FAUX sinon
int obj_grounded(const struct Obj *o)
{
    const char height[] = {12, 15, 7};

    return (o->y >= 52 - height[o->t]);
}

// Retourne VRAI si l'objet o possède une trajectoire (mouvement)
int trajectory(const struct Obj *o)
{
    return o->vx || o->vy;
}

// Retourne VRAI si l'objet o possède une trajectoire (mouvement)
int trajectory(const struct Obj *o)
{
    return o->vx || o->vy;
}

// Initialise la trajectoire de l'objet o, en fonction de l'angle a et de la vitesse v
void start_trajectory(struct Obj *o, const int a, const int v)
{
    double vx, vy;

    vx = v*cos(rad(a));    // Calcul de la vitesse initiale en abscisse
    vy = v*sin(rad(a));    // ________________________________ ordonnée

    obj_vx(o, vx);
    obj_vy(o, vy);
}

// Actualise les coordonnées de l'objet o en fonction de sa trajectoire (vx, vy)
// Seule la gravité est prise en compte (unique accélération verticale)
void refresh_trajectory(struct Obj *o)
{
    if(trajectory(o))
    {
        // Prise en compte de l'accélération gravitationnelle (baisse de vitesse en ordonnée)
        obj_vy(o, o->vy + GRAVITY);
        
        // Modification des coordonnées en fonction de la vitesse
        obj_x(o, o->x + (int)o->vx);
        obj_y(o, o->y + (int)o->vy);
    
        if(obj_grounded(o))
        {
            while(obj_grounded(o)) obj_y(o, o->y - 1);
            obj_y(o, o->y + 1);
            end_trajectory(o);
        }
    }
}

// Fait sauter le personnage (trajectoire verticale)
void perso_jump(struct Obj *p)
{
    obj_y(p, 36);
    start_trajectory(p, -90, 4);
}


Dans ce cas, le personnage est initialisé à un saut de 4 pixel de manière brute, mais il descend suivant le moteur, de manière à ce que cela se fasse dans la fonction de callback.

Et cela fonctionne d'ailleurs.
J'ai pas encore testé avec d'autres objets.
iPod
Pour des parties rapides
Jusqu'où pourras-tu aller dans ce jeu "partie rapide" qu'est Dextris (élu Jeu Du Mois)
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
Autres
Franchement ils valent le coups
Deviens l'amiral de la marine dans SeaRush (jeu concours) (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)
Lephenixnoir Hors ligne Administrateur Points: 20789 Défis: 143 Message

Citer : Posté le 03/02/2017 18:53 | #


Je raconte ce que je vois dans un ordre aléatoire...
- Le coup de passer l'angle initial et la vitesse en int, c'est fourbe. Je ne te le conseille pas.
- Si tu veux sauter vers le haut, l'angle qu'il te faut c'est 90°, pas -90° a priori.
- De même, si tu veux faire descendre ton personnage la gravité devrait être négative.

Je crois comprendre que tu as fait ça parce que le système de l'écran est de bas en haut. Mais si tu veux un moteur physique, à un moment il va falloir arrêter de plaisanter et te fournir un système de coordonnées digne de ce nom. Donc le sol c'est y = 0 et rien d'autre, la gravité est négative, le haut c'est dans le sens trigo... sinon tu t'en sortiras pas, honnêtement.

Sinon ça a l'air correct, honnêtement. T'as oublié de donner end_trajectory() (t'as donné deux fois trajectory()) mais j'imagine que tu y annules les vitesses.
Dark storm Hors ligne Labélisateur Points: 11538 Défis: 176 Message

Citer : Posté le 03/02/2017 18:55 | #


J'ai envie de dire, utilise les constantes réelles.

Avec la méthode d'Euler, x(t+dt) = x(t) + dx(t)/dt
Donc si t'as une accélération de 9.81 m⋅s^-2, sur un dt de 25ms ça fait 0.24525.

Attention aussi à ne pas mélanger le moteur physique et le moteur graphique ! L'un est dépendant de l'unité physique (mètre), l'autre de l'unité d'affichage (pixel). Entre les deux, t'as non seulement une inversion de l'axe Y, mais en plus éventuellement une homotécie + translation (zoom + déplacement de la caméra).

Ajouté le 03/02/2017 à 18:58 :
En fait, je me rend compte que la première partie du message est à coté de la plaque. Mais le passage sur moteur graphique et physique est très adapté à la situation.
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Kirafi Hors ligne Membre Points: 2174 Défis: 10 Message

Citer : Posté le 03/02/2017 19:08 | #


Okay l'angle et la vitesse en double .
// Initialise la trajectoire de l'objet o, en fonction de l'angle a et de la vitesse v
void start_trajectory(struct Obj *o, const double a, const double v)
{
    obj_vx(o, v*cos(rad(a)));
    obj_vy(o, v*sin(rad(a)));
}


Hum non en fait c'est la subtilité que j'ai expliqué au dessus pour l'angle de -90 .
En fait un tel saut (4 pixels vers le haut puis redescendre instantanée de 4 pixels à la frame suivante) c'est impossible pour garder la logique des trajectoires sur les autres objets. Et j'ai besoin que mon perso puisse enchaîner les sauts extrêmement vite, c'est pour ça qu'en réalité, "sauter", initialise sa hauteur à 4 pixel de haut lors de l'appuis sur une touche (frame 1), pour ensuite lui donner une trajectoire de "chute", pour le faire redescendre de manière automatique avec le moteur (à la frame 2) .

Et bon pour les coordonnées, à partir du moment où j'ai la fonction "obj_grounded", ça défini un sol, et donc, faire chuter les trucs "à l'envers" ne se résume qu'à mettre la gravité à l'envers c'est vrai .
Au final c'est pareil que si j'avais fais tout un bousin pour changer le sens et ça évite des calculs aussi.
Car retourner l'axe implique de faire une convertion (64 - y) pour l'affichage , or mon jeu aura besoin de pas mal de ressources en calculs car il est voué à faire apparaître beaucoup d'objets simultanément à l'écran, tout en calculant leur trajectoire.

Et sinon voilà la fugitive (c'est ce que tu a dis).
// Termine la trajectoire de l'objet o (stoppe l'objet, généralement au sol)
void end_trajectory(struct Obj *o)
{
    obj_vx(o, 0);
    obj_vy(o, 0);
}


Bref donc ça a l'air correct cool , je peux pas encore tester d'autres objets, je dois d'abord coder d'autres trucs, mais j'y reviendrais pour le coup .
Là j'ai la bases des bases.
Maintenant j'aimerais implémenter la masse, pour que les objets lourds tombent plus vite quoi.
Et également le rebond, ça part contre j'ai aucune connaissances...

Ajouté le 03/02/2017 à 19:10 :
Dark je me suis dis que les mesures pouvait se faire en pixel, étant donné que c'est en 2D et que la cam ne se déplace jamais.

Ou alors je fais simple : 1 pixel = 1 mètre .
iPod
Pour des parties rapides
Jusqu'où pourras-tu aller dans ce jeu "partie rapide" qu'est Dextris (élu Jeu Du Mois)
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
Autres
Franchement ils valent le coups
Deviens l'amiral de la marine dans SeaRush (jeu concours) (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)
Lephenixnoir Hors ligne Administrateur Points: 20789 Défis: 143 Message

Citer : Posté le 03/02/2017 19:12 | #


Calculer un repère potable n'est pas un problème pour tes performances. Quand j'aurai testé les perfs' de gint, et si tout se passe comme je le pense, vous verrez que c'est pas ça qui bouffe de la puissance. Vraiment.

Pour le rebond, c'est une force de rappel. Quand tu tombes au sol, tu renvoies une vitesse verticale dans l'autre sens : en gros, tu l'inverses de signe. Il serait intelligent de la multiplier par un coefficient d'amortissement pour que le joueur s'arrête de rebondir un jour.

Accessoirement si tu décides de ne pas mettre d'amortissement, je suis prêt à parier que le joueur s'arrêtera quand même -- enfin.
Dark storm Hors ligne Labélisateur Points: 11538 Défis: 176 Message

Citer : Posté le 03/02/2017 19:13 | #


Mouais, alors pour le calcul des trajectoires et la performance, t'es pas encore à ça près. Disons, "beaucoup" ~ 500, faire 1000 additions c'est relativement rapide pour le proco, donc faire une soustraction en plus, ça lui change pas grand chose. x)
Tu perdra beaucoup, beaucoup plus de temps à l'affichage.
Finir est souvent bien plus difficile que commencer. — Jack Beauregard
Kirafi Hors ligne Membre Points: 2174 Défis: 10 Message

Citer : Posté le 03/02/2017 19:22 | #


Okay cimer je note pour le rebond coef d'amortissement .

Ouai bon d'accord pour le changement d'axe, mais là... J'ai vraiment la flemme de changer ça alors que mon truc fonctionne et que je le maîtrise , enfin je veux dire pa là, que je l'ai réfléchie et que je sais comment ça marche et comment l'utiliser .

Par contre c'est à dire "perdre" plus de temps à l'affichage ? Tu veux plutôt dire que c'est l'affichage qui prend le plus de temps dans ce genre de configuration ?

Meh, le truc dommage c'est que ça passe trop mal les déplacement de mon perso à cause de la rémanence ...
iPod
Pour des parties rapides
Jusqu'où pourras-tu aller dans ce jeu "partie rapide" qu'est Dextris (élu Jeu Du Mois)
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
Autres
Franchement ils valent le coups
Deviens l'amiral de la marine dans SeaRush (jeu concours) (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)
Lephenixnoir Hors ligne Administrateur Points: 20789 Défis: 143 Message

Citer : Posté le 03/02/2017 22:27 | #


Le dessin est, je serais prêt à le parier, ce qui bouffe plus de la moitié du temps de calcul dans la plupart des jeux. (D'où l'accent que j'ai mis sur l'optimisation de ce point précis...)

Quant à la rémanence, tu peux la diminuer en ajustant le contraste. Cependant, le contenu de l'écran sera moins visible. Pour le gris c'est encore pire puisque changer le contraste détériore le gris. On est donc coincé avec la rémanence, et honnêtement pour TLT c'est l'aspect graphique qui me gêne le plus.
Kirafi Hors ligne Membre Points: 2174 Défis: 10 Message

Citer : Posté le 04/02/2017 01:15 | #


La seule chose à faire pour ça c'est de trouver une bonne fréquence par rapport au mouvement quoi , j'ai réussi à rendre le truc un peu meilleur en modifiant quelques trucs dans l'affichage. Bref.
iPod
Pour des parties rapides
Jusqu'où pourras-tu aller dans ce jeu "partie rapide" qu'est Dextris (élu Jeu Du Mois)
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
Autres
Franchement ils valent le coups
Deviens l'amiral de la marine dans SeaRush (jeu concours) (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)
Ninestars Hors ligne Membre Points: 2384 Défis: 22 Message

Citer : Posté le 04/02/2017 10:26 | #


Salut ! Je confirme les propos de Lephé, si tu veux avoir un moteur physique propre, crée toi un vrai repère. Tu as le repère du monde (en mètre, x à droite et y en haut) et le repère de ta caméra (en pixel, x à droite et y en bas). Faire cette dissociation est importante sinon tu vas mettre des coefficients à la louche pour combler le manque de réalisme dans tes trajectoires et tu vas perdre le fil.

J'ajoute un autre point à ce que disais Dark un peu plus haut, utilise les équations du mouvement de Euler (ou Verlet c'est plus precis).
Mais completement ! Parce que je vois que tu veux ajouter la masse à tes objets.
Quand tu veux bouger un objet, tu lui appliques une force qui va modifier l'acceleration.
F = m x a donc a = F / m
Ensuite à chaque frame tu recalcules la position (dt est le temps entre deux frames, et V0 et X0 la vitesse/position actuelle)
V = a * dt + V0
X = v * dt + X0

La gravitée s'ajoute en ajoutant 9.8 à l'acceleration. Il y a un peu de bricolage à ce niveau car la pesenteur est tout le temps appliquée et pas les forces...
Kirafi Hors ligne Membre Points: 2174 Défis: 10 Message

Citer : Posté le 04/02/2017 12:31 | #


Bon bon... Okay je ferais ces changement plus tard ...
Donc ma structure Objet, possédera les x, y du repère... comme j'ai codé pour l'utiliser comme un private... hum ce sera pas si compliqué si j'fais ça... puis ça... etc...
iPod
Pour des parties rapides
Jusqu'où pourras-tu aller dans ce jeu "partie rapide" qu'est Dextris (élu Jeu Du Mois)
Pourras-tu survivre plus de 20 secondes dans ce fameux tunnel appelé Graviton
Rebondis entre les murs en évitant les piques dans SpikeBird
Pourras-tu éviter de te faire écraser dans FallBlocs (élu Jeu Du Mois)
Autres
Franchement ils valent le coups
Deviens l'amiral de la marine dans SeaRush (jeu concours) (élu Jeu Du Mois)
La version 2048 tactile amélioré au plus haut point : 2048 Delux !
Pars à la recherche des morceaux d'étoile dans Lumyce (élu Jeu Du Mois)

LienAjouter une imageAjouter une vidéoAjouter un lien vers un profilAjouter du codeCiterAjouter un spoiler(texte affichable/masquable par un clic)Ajouter une barre de progressionItaliqueGrasSoulignéAfficher du texte barréCentréJustifiéPlus petitPlus grandPlus de smileys !
Cliquez pour épingler Cliquez pour détacher Cliquez pour fermer
Alignement de l'image: Redimensionnement de l'image (en pixel):
Afficher la liste des membres
:bow: :cool: :good: :love: ^^
:omg: :fusil: :aie: :argh: :mdr:
:boulet2: :thx: :champ: :whistle: :bounce:
valider
 :)  ;)  :D  :p
 :lol:  8)  :(  :@
 0_0  :oops:  :grr:  :E
 :O  :sry:  :mmm:  :waza:
 :'(  :here:  ^^  >:)

Σ π θ ± α β γ δ Δ σ λ
Veuillez donner la réponse en chiffre
Vous devez activer le Javascript dans votre navigateur pour pouvoir valider ce formulaire.

Si vous n'avez pas volontairement désactivé cette fonctionnalité de votre navigateur, il s'agit probablement d'un bug : contactez l'équipe de Planète Casio.

Planète Casio v42 © créé par Neuronix et Muelsaco 2004 - 2021 | Il y a 54 connectés | Nous contacter | Qui sommes-nous ? | Licences et remerciements

Planète Casio est un site communautaire non affilié à Casio. Toute reproduction de Planète Casio, même partielle, est interdite.
Les programmes et autres publications présentes sur Planète Casio restent la propriété de leurs auteurs et peuvent être soumis à des licences ou copyrights.
CASIO est une marque déposée par CASIO Computer Co., Ltd