Bonjour j'ai un problème et j'ai du mal comprendre ce qui se passe exactement, je souhaite crée une structure, et en faire un tableau, j'initialise les valeurs a 0, et ensuite affiche le contenu, pour une raison qui m'échappe les deux première valeur ne contienne pas 0,
en voyant ton code, je ne comprends pas pourquoi ça fait ça. Il n'y a pas de débordement visiblement.
Tu as mis tout le code, ou tu as épuré un peu ? Peut être que tu flingues la mémoire à un endroit que tu as épuré ?
Sinon, de manière propre, en C++ tu peux définir des constructeurs pour les structures (qui sont des classes publiques)
Ainsi, si tu mets un constructeur qui te met a=b=c=0 et pareil pour tes vec2, tu n'as plus besoin de faire ton premier for. Le simple fait de créer ton tableau va appeler les constructeurs par défaut de tous les éléments.
bonjour, Comme dit Fvirtman, il est mieux de définir un constructeur par défaut qui initialisera tes données à 0. Il apportera une meilleur garantit de ce qui se trouve dans tes variables et évitera des lignes en plus répétées inutilement à chaque création d'un objet Segment. Imagine que tu crée un segment mais malheureusement tu ne l'initialise pas, et bien dans ce cas les valeurs dans tes variables seront indéterminées et donc tu travailleras surement avec des données erronées. Pour le problème des valeurs différentes de 0, dans le code que tu as posté, n'a tu pas oublier d'écrire une instruction qui apparaît dans ton réel code ?. Pour la taille du tableau du tableau, tu peux la stocker dans une variable pour ne pas à chaque fois écrire 10. Car si un jour tu change de taille pour le tableau, tu devra copier à tout les endroits la nouvelle valeur. Comme tableau tu peux utiliser std::array qui est un tableau statique et fourni une interface simple d'utilisation: .size() pour avoir la taille du tableau.
Etre conscient que l'on est ignorant est un grand pas vers le savoir. [Benjamin Disraeli]
Le problème vient effectivement d'ailleurs. (j'ai testé ton code, sans avoir le soucis).
Par contre ton code montre une mauvaise habitude dont je te conseille de te débarrasser: "using namespace". Tu l'as fait pour std et pour glm. On n'importe pas tout et n'importe quoi dans l'espace global de nommage. Et si c'est pour en plus ajouter en commentaire ce que l'espace de nommage aurait explicité, je ne vois vraiment pas l'intérêt (cf. "vec2 A; //glm")
Si vous ne trouvez plus rien, cherchez autre chose.
En effet j'ai mi uniquement la partie du code qui concerne la structure, car le reste du code ne l'utilisais pas encore quand j'ai poster, j'ai signaler glm en commentaire pour que vous sachiez a quel libraire vec2 appartenais, Pour l'instant je n'ai jamais rencontré de souci intégrant std et glm dans l'espace global,
Fvirtman: je te remercie car je ne savais pas que les constructeurs étais utilisable pour les structures j'ai implémenté ça au code. blackProgrammeur: d'habitude j'utilise un define pour fixer les limites
je vous mets le code du main, il n'est pas optimisé car c'est plus un programme teste qui me permet de faire quelque expérience, je compte l'optimisé par la suite.
/*
Auteur: François Goorman
Titre: collision sphere
Description:
1 Créer une sphère et lui donner une physique
2 Tenté de lui donner une interaction physique avec un segment ou un tiangle
*/
#include <iostream>
#include <SDL2/SDL.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "sdlglutils.h"
#include "Input.h"
#include "Trigonometry.h"
#include <glm/glm.hpp>
#include <glm/gtx/transform.hpp>
#include <glm/gtc/type_ptr.hpp>
#define WINDOW_WIDTH 600
#define WINDOW_HEIGHT 400
#define TEMPS_PROGRAMME 16
#define TRAINER 10
#define RAYON 5
#define GRAVITE 0.11
#define CHUTE_MAX 16
#define ABSORPTION 60
#define NBR_SEGMENT 10
using namespace std;
using namespace glm;
struct Segment
{
int a;
int b;
int c;
vec2 A; //glm
vec2 B; //glm
Segment():a(0),b(0),c(0),A(vec2(0,0)),B(vec2(0,0))
{
}
};
void InitVersion();
float Trajectoir_Rebond(float angle1,float angle2);
bool Collision_Cercle_droite(vec2 A,vec2 B,vec2 centre_cercle,float rayon); // une droit est INFINIE pas de l'imite
bool Collision_cercle_segment(vec2 A,vec2 B,vec2 centre_cercle,float rayon);
vec2 ProjectionI(vec2 A,vec2 B,vec2 P);//permet de connaitre le point i dune collision par apport a un segment 2D
vec2 ProjectionI_Sphere(vec2 A,vec2 B,vec2 P,float rayon);//identique a ProjectionI en prenant en compte que c'est une cercle
vec2 Normal_segment(vec2 A,vec2 B,vec2 P);//normal (angle hortoconal) du segment
vec2 Calcule_Vecteur_trajectoir(vec2 v,vec2 N);
float norme(vec2 A,vec2 B,vec2 P);
int main(int argc, char *argv[])
{
bool continuer = true;
Input input;
vec2 trajectoir(6,3);
vec2 position(0,0);
Trigonometry tri;
float angleDroite=180;
float angleTrajectoir=45;
vec2 curseur(WINDOW_WIDTH/2,WINDOW_HEIGHT-5);
Segment segment[NBR_SEGMENT]; //PROBLEME table 0 du tableau ne veut pas signitialiser correctement
//segment[0].A = vec2(290,300);
//segment[0].B = vec2(350,360);
segment[1].A = vec2(280,300); /*obstacle*/
segment[1].B = vec2(350,360);
segment[2].A = vec2(0,WINDOW_HEIGHT);
segment[2].B = vec2(0,0);
segment[3].A = vec2(0,0);
segment[3].B = vec2(WINDOW_WIDTH,0);
segment[4].A = vec2(WINDOW_WIDTH,0);
segment[4].B = vec2(WINDOW_WIDTH,WINDOW_HEIGHT);
vec2 historique[TRAINER];
for(int i=0;i<=TRAINER;i++)
{
historique[i] = curseur;
}
vec2 _curseur; //cache
vec2 chute;//vecteur de force de la boule
vec2 pos_boule(WINDOW_WIDTH/2,WINDOW_HEIGHT-5);//vecteur de position de la boule
Uint32 start_time,elapsed_time;
bool gravite = true;
SDL_Window *fenetre;
SDL_Event event;
SDL_GLContext contextOpenGL(0);
InitVersion();
fenetre = SDL_CreateWindow("Collision sphere opengl",SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED, WINDOW_WIDTH,WINDOW_HEIGHT,SDL_WINDOW_SHOWN|SDL_WINDOW_OPENGL);
if(!fenetre)
{
cout<<"SDL_Error : " <<SDL_GetError()<<endl;
SDL_DestroyWindow(fenetre);
SDL_Quit();
return -1;
}
contextOpenGL = SDL_GL_CreateContext(fenetre);
if(contextOpenGL == 0)
{
cout<<"Erreur lors de l'initialisation du Context "<< SDL_GetError() <<endl;
SDL_DestroyWindow(fenetre);
SDL_Quit();
return -1;
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0,WINDOW_WIDTH,0,WINDOW_HEIGHT);
input.capturerPointeur(true);
for(int i=0;i<NBR_SEGMENT;i++)
{
cout<<i<<" "<<segment[i].a<<" "<<segment[i].b<<" "<<segment[i].c<<" "<<segment[i].A.x<<" "<<segment[i].A.y<<" "<<segment[i].B.x<<" "<<segment[i].B.y<<endl;
}
while(continuer)
{
start_time = SDL_GetTicks();
input.updateEvenements();
SDL_PollEvent(&event);
if(input.terminer() == true){continuer = false;}
if(input.getTouches(SDL_SCANCODE_ESCAPE)){continuer = false;}
if(input.getTouches(SDL_SCANCODE_LEFT)){angleDroite+=0.1;}
if(input.getTouches(SDL_SCANCODE_RIGHT)){angleDroite-=0.1;}
if(input.getBoutonSouris(SDL_BUTTON_LEFT))
{
curseur = vec2(WINDOW_WIDTH/2,WINDOW_HEIGHT-5);
chute = vec2(0,0);
}
if(input.getBoutonSouris(SDL_BUTTON_RIGHT))
{
gravite = !gravite;
}
angleTrajectoir += input.getYWheel()/10;
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
/*DROITE COLLISION*/
glPushMatrix();
glBegin(GL_LINES);
glColor3ub(0,150,150);
for(int i=1;i<NBR_SEGMENT;i++)
{
glVertex2d(segment[i].A.x,segment[i].A.y);
glVertex2d(segment[i].B.x,segment[i].B.y);
}
glEnd();
glPopMatrix();
/*CURSEUR CERCLE*/
_curseur = curseur;
if(gravite)
{
if(curseur.y <-CHUTE_MAX){curseur.y = WINDOW_HEIGHT;}// si on tombe plus bas que lécran être téléporter au desus de lécrans
if(chute.y <CHUTE_MAX) // continuer daccéléré tant que lon a pas depasser la vitesse de chute maximal
{
chute += vec2(0,GRAVITE);
}
else{chute.y = CHUTE_MAX;}
curseur -= chute;
}
else
{
curseur += vec2(input.getXRel(),-input.getYRel());
}
glPushMatrix();
/*COLLISION*/
for(int i=1;i<NBR_SEGMENT;i++)
{
if(tri.Collision_Cercle_Segment(segment[i].A,segment[i].B,curseur + ((curseur - _curseur)/vec2(2,2)),RAYON))//permet de tester si il ya collision entre le segment A et B pour eviter de passer a travers segment
{
curseur = ProjectionI_Sphere(segment[i].A,segment[i].B,curseur,RAYON);
glColor3ub(255,0,0);
/*TESTE DE TRAJECTOIR */
if(gravite)
{
vec2 Normal = Normal_segment(segment[i].A,segment[i].B,curseur);
chute -= vec2(0,chute.y/ABSORPTION);//perte de force du a la collision
chute = Calcule_Vecteur_trajectoir(chute,Normal);
}
}
else if(tri.Collision_Cercle_Segment(segment[i].A,segment[i].B,curseur,RAYON))
{
curseur = ProjectionI_Sphere(segment[i].A,segment[i].B,curseur,RAYON);
glColor3ub(255,0,0);
/*TESTE DE TRAJECTOIR */
if(gravite)
{
vec2 Normal = Normal_segment(segment[i].A,segment[i].B,curseur);
chute -= vec2(0,chute.y/ABSORPTION);//perte de force du a la collision
chute = Calcule_Vecteur_trajectoir(chute,Normal);
}
}
else{glColor3ub(255,255,255);}
}
glTranslated(curseur.x,curseur.y,0);
glBegin(GL_LINE_LOOP);
for(float i=0;i<=360;i+=360/10)
{
position = tri.Projection_Vecteur_Axe(vec2(0,1),i,RAYON);
glVertex3d(position.x,position.y,0);
}
//glTranslated(20,20,0);
glEnd();
glPopMatrix();
for(int i=0;i<TRAINER;i++)
{
historique[i]= historique[i+1];
}
historique[TRAINER] = curseur;
/*TRAINER TRAJECTOIR CERCLE*/
glPushMatrix();
glBegin(GL_LINES);
glColor3ub(30,30,255);
for(int i=0;i<TRAINER;i++)
{
if(historique[i]!= historique[i+1])
{
glVertex2d(historique[i].x,historique[i].y);
glVertex2d(historique[i+1].x,historique[i+1].y);
}
}
glEnd();
glPopMatrix();
glFlush();
SDL_GL_SwapWindow(fenetre);
elapsed_time = SDL_GetTicks() - start_time;
//cout<<TEMPS_PROGRAMME<<" - "<<elapsed_time<<" = "<<TEMPS_PROGRAMME - elapsed_time<<endl; //temps ecouler entre deux frame
if(elapsed_time < TEMPS_PROGRAMME)
{
SDL_Delay(TEMPS_PROGRAMME - elapsed_time);
}
//cout<<trajectoir.x<<" "<<trajectoir.y<<endl;
}
SDL_GL_DeleteContext(contextOpenGL);
SDL_DestroyWindow(fenetre);
SDL_Quit();
return 0;
}
void InitVersion()
{
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION,2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION,0);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER,1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE,24);
}
float Trajectoir_Rebond(float angle1,float angle2) // obsolette
{
float angle_Perpendiculaire = angle1 + 90;//par apport au mur
//cout<< angle1<<" + 90 = "<<angle_Perpendiculaire <<endl;
float differance = angle_Perpendiculaire - angle2;// calcule la différence entre l'angle 2 et l'angle perpendiculaire
//cout<< angle2<<" - "<<angle_Perpendiculaire<< " = "<<differance <<endl;
return angle_Perpendiculaire + differance;
}
vec2 ProjectionI(vec2 A,vec2 B,vec2 P)
{
vec2 u,AC;
u = B - A;
AC = P - A;
float ti = dot(u,AC)/dot(u,u);
vec2 I;
I = A + ti *u;
return I;
}
vec2 ProjectionI_Sphere(vec2 A,vec2 B,vec2 P,float rayon)
{
vec2 u,AC;
u = B - A;
AC = P - A;
float ti = dot(u,AC)/dot(u,u);
vec2 I;
I = A + ti *u;
I += (Normal_segment(A,B,P)*vec2(rayon,rayon));//ajoute une séparation de l'épaisseur (rayon) de la sphere
return I;
}
vec2 Normal_segment(vec2 A,vec2 B,vec2 P)
{
vec2 AC,u,N;
u = B - A;
AC = P - A;
float parenthesis = u.x*AC.y-u.y*AC.x; // calcul une fois pour les deux
N = vec2(-u.y*parenthesis,u.x*parenthesis);
//normalisation (1)
float norme = sqrt(N.x*N.x + N.y*N.y);
N/=norme;
return N;
}
vec2 Calcule_Vecteur_trajectoir(vec2 v,vec2 N)
{
vec2 v2;
float pscal = dot(v,N);
v2 = v-2*pscal*N;
return v2;
}
les namespace ne sont pas la pour faire joli (comme ça été déjà dit plus haut). `using namespace ...;` c'est l'anti-namespace (surtout pour des namespaces dont le nom est de 3 lettres...).
les macros c'est pas bien (à part quand on parle de poisson), utilises des constantes (`const ou mieux constexpr` en c++11 et +)
fais de surcouches RAII pour les bibliothèques C (SDL et autres)
utilises un constructeur avec des paramètres pour `Segment`
Ton problème à été résolu avec l'introduction des constructeurs pour `Segment` (normalement le constructeur doit résoudre ton problème) ?
boucle avec i<=TRAINER -> dépassement de tableau. N'importe quel analyseur dynamique le détecte, notamment ceux intégrés au compilateur et activable avec -fsanitize=address ou -fsanitize=undefined.
Je n'ai pas été plus loin, mais déjà:
N'utilise pas des defines pour définir des constantes, mais fait le à travers de vrai variable constante (constexpr).
On ne construit pas objet par l'intermédiaire d'un objet temporaire du même type A(vec2(0,0)) -> A(0,0). Même si je pense que le constructeur par de défaut initialisation suffit A{}
C'est pérrave de faire un constructeur comme ça, autant initialiser les membres au moment de leur déclaration. struct segment { vec2 A{}; ... };. En plus le virer permet de construire l'objet avec d'autre valeur.
Il y a le type std::size_t pour les tailles et les indices de tabeau.
les boucles range-for sont nettement plus simples qu'utiliser des indices et des tailles.
std::array est nettement plus sûr qu'un tableau C-style. En plus une assertion aurait fait crasher le prog avec la ligne qui fait l'overflow.
L'initialisation de tableau en plusieurs étapes, c'est moche. `Segment segment[NBR_SEGMENT]{{0,0,0,{290,300},{350,360}}, etc}; /obstacle/
Ne déclare pas les variables au début de fonction, mais au moment de leur utilisation. Au passage le main est trop grand.
nefas: le constructeur pour segment na pas résolut mon problème , Pourquoi ne faut t'il pas utiliser de define et plutôt des variable constante?
jo_link_noir: pour la construction du vec2 si je l'initialise en fessant "vec2 A(0,0)" ça marche si je fait comme tu a dit ça ne fonctionne pas la librarie glm le permet pas sinon je l'aurait fait bien avant crois moi le main est trop long oui tu a raison, j'ai bien expliquer que c'étais un programme teste, je me suis lancer avec un objectif mais aucune idée de comment faire donc y'a eu beaucoup de tatonement
EDIT: jo_link_noir Tu avais raison pour i <=TRAINER j'ai effectivement mi un = (par accident) et apparemment cet case débordait sur l'adresse de la structure sa ne serrait pas arriver si javais utiliser un tableau dynamique, le problème est résolut merci a tous.
- Edité par la colombe noir 21 août 2016 à 5:35:10
Pourquoi ne faut t'il pas utiliser de define et plutôt des variable constante?
Parce que les define ne sont pas typés, mais les variables constantes si De plus les macros n'ont pas de scope, et ne peuvent pas être mises dans des namespaces (polluant ainsi l'espace de nommage global).
la colombe noir a écrit:
jo_link_noir: pour la construction du vec2 si je l'initialise en fessant "vec2 A(0,0)" ça marche si je fait comme tu a dit ça ne fonctionne pas la librarie glm le permet pas sinon je l'aurait fait bien avant crois moi
Le constructeur par défaut des glm::vec2 met bien x et y à 0.
Si vous ne trouvez plus rien, cherchez autre chose.
ha oui effectivement il les mets à 0, c'est mon habitude de toujours préciser a l'initialisation, je pensais que tu parlais de l'operateur =, qui lui ne prend qu'une variable de type vec2.
@Dalfab : pas nécessairement, c'est ça qui est "agréable" avec les UB.
@la colombe noir : ton code n'est pas du tout robuste aux exceptions, les éléments de la SDL étant désalloués manuellement, crée une capsule RAII pour ces machins.
Par contre, est ce que tu gères l'éventuelle recopie ? Ou alors tu l'interdis ?
C'est dans le code .
@dragonjoker : ce serait peut être pas mal que le deleter fasse partie intégrante du type vu qu'il n'y a priori qu'un deleter par ressource si je me souviens bien. Les "inline" ne sont pas nécessaires, ce sont des fonctions membres directement définie dans la classe : elles sont implictement inline.
@dragonjoker: ce serait peut être pas mal que le deleter fasse partie intégrante du type vu qu'il n'y a priori qu'un deleter par ressource si je me souviens bien. Les "inline" ne sont pas nécessaires, ce sont des fonctions membres directement définie dans la classe : elles sont implictement inline.
- Edité par Ksass`Peuk il y a moins de 30s
Oué, pour les inline, c'est une habitude que j'ai de toujours le spécifier quand je le souhaite (même si ce n'est pas nécessaire, i.e. le cas présent). Par contre, comment tu verrais le deleter en partie intégrante du type? Et quel serait l'intérêt?
Si vous ne trouvez plus rien, cherchez autre chose.
(2) Pas de pointeur stocké pour le deleter donc moins d'espace occupé sur la pile et pas d'indirection au moment de l'appel de deleter puisque c'est dans le type.
Intéressant effectivement, bon je peux pas l'inclure à ma (vraie) classe (qui est censée fonctionner avec GCC 3.4 ^^') mais pour l'exemple, et pour plus tard, c'est bon à savoir.
EDIT:
En tout cas pas sous cette form, mais sinon ça doit quand même pouvoir se faire, faut juste que j'y réfléchisse.
- Edité par dragonjoker 24 août 2016 à 12:04:08
Si vous ne trouvez plus rien, cherchez autre chose.
Pour le deleter des objets SDL_, je verrais bien une résolution automatique en fonction du type. À la manière d'une spécialisation de std::default_delete pour unique_ptr.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Si vous ne trouvez plus rien, cherchez autre chose.
Si vous ne trouvez plus rien, cherchez autre chose.
En recherche d'emploi.
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
Si vous ne trouvez plus rien, cherchez autre chose.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
Si vous ne trouvez plus rien, cherchez autre chose.
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
Si vous ne trouvez plus rien, cherchez autre chose.
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C
git is great because Linus did it, mercurial is better because he didn't.
Si vous ne trouvez plus rien, cherchez autre chose.
Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C