Bonjour,
j'ai le message "this application has requested to terminate it in an unusual way. Please contact etc..." dès que je clique en dehors de ma fenetre SFML.
je vous montre la boucle de gestion des events mais je ne sais pas si ça peut venir de là, c'est plus par intuition :
while (fenetre->isOpen() && compteurCoups != 0 && !partieTerminee)
{
sf::Event event;
while (fenetre->pollEvent(event))
{
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Q)
fenetre->close();
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
{
if (ModifierGrille(Contenu::CROIX, sf::Mouse::getPosition(*fenetre).x/100, sf::Mouse::getPosition(*fenetre).y/100))
{
compteurCoups--;
partieTerminee = PartieTerminee();
if (compteurCoups > 0 && !partieTerminee)
{
compteurCoups--;
partieTerminee = IA();
}
}
}
}
fenetre->clear();
DessinerContenuGrille();
fenetre->display();
}
merci d'avance pour votre aide ;)
EDIT : gdb me dit :
(gdb) r
Starting program: C:\Program Files (x86)\CodeBlocks\Projets\morpion\b
[New Thread 6440.0x1b58]
[New Thread 6440.0x1aa8]
warning: Invalid parameter passed to C runtime function.
warning: Invalid parameter passed to C runtime function.
[Inferior 1 (process 6440) exited with code 03]
(gdb) bt
No stack.
(gdb)
(je pige pas pourquoi il y'a deux thread...)
voici le code complet minimal qui reproduit l'erreur
#include <vector>
#include <SFML/Graphics.hpp>
using namespace std;
class Morpion
{
typedef enum {VIDE, CROIX, ROND} Contenu;
vector<vector<Morpion::Contenu>> grille;
sf::Texture* tGrille;
sf::Sprite* sGrille;
sf::Texture* tCroix;
sf::Sprite* sCroix;
sf::Texture* tRond;
sf::Sprite* sRond;
sf::RenderWindow* fenetre;
int compteur;
bool partieTerminee;
bool aGagne;
public :
Morpion();
~Morpion();
void Jouer();
bool ModifierGrille(Morpion::Contenu contenu, int i, int j);
bool PartieTerminee();
void Init();
bool IA();
std::pair<int,int> EvaluerColonnes(Morpion::Contenu c);
std::pair<int,int> EvaluerLignes(Morpion::Contenu c);
std::pair<int,int> EvaluerDiagonales(Morpion::Contenu c);
int GetCompteur() {return compteur;}
bool AGagne() {return aGagne;}
sf::RenderWindow* GetFenetre() {return fenetre;}
};
Morpion::Morpion() :
grille(3, vector<Morpion::Contenu>(3)),
tGrille(new sf::Texture()),
sGrille(new sf::Sprite()),
tCroix(new sf::Texture()),
sCroix(new sf::Sprite()),
tRond(new sf::Texture()),
sRond(new sf::Sprite()),
fenetre(new sf::RenderWindow(sf::VideoMode(300,300,32), "Test", sf::Style::None)),
compteur(9),
partieTerminee(false),
aGagne(false)
{
grille = {{VIDE, VIDE, VIDE},{VIDE, VIDE, VIDE},{VIDE, VIDE, VIDE}};
tGrille->loadFromFile("grille.png");
sGrille->setTexture(*tGrille);
tCroix->loadFromFile("croix.png");
sCroix->setTexture(*tCroix);
tRond->loadFromFile("rond.png");
sRond->setTexture(*tRond);
fenetre->setFramerateLimit(60);
srand(time(NULL)); // initialisation de rand
}
Morpion::~Morpion()
{
delete tGrille;
delete tCroix;
delete tRond;
delete sGrille;
delete sCroix;
delete sRond;
delete fenetre;
}
void Morpion::Jouer()
{
while (fenetre->isOpen() && compteur!= 0 && !partieTerminee)
{
sf::Event event;
while (fenetre->pollEvent(event))
{
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Q)
fenetre->close();
//C'est la ligne qui vient qui fait planter quand on clique en dehors de la fenetre
if (sf::Mouse::isButtonPressed(sf::Mouse::Left))
ModifierGrille(Contenu::CROIX, sf::Mouse::getPosition(*fenetre).x/100, sf::Mouse::getPosition(*fenetre).y/100);
}
fenetre->clear();
fenetre->display();
}
}
bool Morpion::ModifierGrille(Morpion::Contenu contenu, int i, int j)
{
if (grille[i].at(j) == Contenu::VIDE)
{
grille[i].at(j) = contenu;
return true;
}
else return false;
}
int main()
{
Morpion m;
m.Jouer();
return 0;
}
je pensais que renseigner la fenetre dans getPosition permettait de ne pas tenir compte des clics en dehors du programme...mais aparremment ça fonctionne pas comme ça ^^
Donc quand je clique en dehors getPosition(*fenetre) plante pas vraiment mais renvoit des coordonnées négatives je supposes, ce qui créé un segfault à l'affectation de la grille...
en fait je n'arrive pas à déduire de la doc ni du forum une bonne façon d'utiliser sf::Mouse, classe avec laquelle je ne suis pas du tout familier (même sous 1.6 jamais utilisé)
et j'ai fait un truc qui me bouffe 3 à 6% du proc quand j'effectue une action (bouger la souris), 50% sinon :
while (m->GetFenetre()->pollEvent(event))
{
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Q)
m->GetFenetre()->close();
if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Button::Left)
{
if ((sf::Mouse::getPosition(*m->GetFenetre()).x <= 150) && (sf::Mouse::getPosition(*m->GetFenetre()).y > 150))
{
//on veut rejouer
rejouer = true;
choixFait = true;
}
else if ((sf::Mouse::getPosition(*m->GetFenetre()).x > 150) && (sf::Mouse::getPosition(*m->GetFenetre()).y > 150))
{
//on ne veut pas rejouer
rejouer = false;
choixFait = true;
}
}
m->GetFenetre()->clear();
m->DessinerContenuGrille();
m->GetFenetre()->draw(*sRejouer);
m->GetFenetre()->display();
}
Merci Laurent, j'ai suivi tes instructions, et c'est vrai que c'est plus cool de récupérer des infos dans des objets que l'on a déjà à disposition ^^
Sinon, pour l'histoire des performances, c'est vraiment étrange, j'ai du oublié un détail, car je n'arrive pas à détecter l'erreur que j'ai commis pour obtenir ceci :
ici, 0-1% du proc (quoi que je fasse) :
void Morpion::Jouer()
{
while (fenetre->isOpen() && compteurCoups!= 0 && !partieTerminee)
{
sf::Event event;
while (fenetre->pollEvent(event))
{
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Q)
fenetre->close();
if (event.type == sf::Event::MouseButtonPressed)
{
if (ModifierGrille(Contenu::CROIX, event.mouseButton.x/100, event.mouseButton.y/100))
{
compteurCoups--;
partieTerminee = PartieTerminee();
if (compteurCoups > 0 && !partieTerminee)
{
compteurCoups--;
partieTerminee = IA();
}
}
}
}
fenetre->clear();
DessinerContenuGrille();
fenetre->display();
}
}
ici par contre, 50% du proc si je ne bouge pas la souris...dès que je bouge la souris je retombe à 0-1% du proc... je ne comprends pas pourquoi et ne vois pas d'erreurs de ma part (mais il y en a forcément une) :
while (m->GetFenetre()->isOpen() && !choixFait)
{
sf::Event event;
while (m->GetFenetre()->pollEvent(event))
{
if (event.type == sf::Event::KeyPressed && event.key.code == sf::Keyboard::Q)
m->GetFenetre()->close();
if (event.type == sf::Event::MouseButtonPressed && event.mouseButton.button == sf::Mouse::Button::Left)
{
if ((event.mouseButton.x <= 150) && (event.mouseButton.y > 150))
{
//on veut rejouer
rejouer = true;
choixFait = true;
}
else if ((event.mouseButton.x > 150) && (event.mouseButton.y > 150))
{
//on ne veut pas rejouer
rejouer = false;
choixFait = true;
}
}
m->GetFenetre()->clear();
m->DessinerContenuGrille();
m->GetFenetre()->draw(*sRejouer);
m->GetFenetre()->display();
}
}
y a-t-il une évidence que j'ai raté ?