-
Bonjour,
Je suis sous Ubuntu 14.04.
J'affiche une image pour remplacer le curseur de la souris(que je cache donc). Le problème, c'est que sf::Mouse::getPosition(window) a l'air d'être en retard...
En effet, je trouvais que mon curseur n'était pas fluide, j'ai donc rafficher le curseur du système pour voir la différence, et en effet, mon image traînais toujours derrière mon curseur... J'ai trouver ça bizarre et j'ai d'abord penser que ça venais de mon application qui devait avoir des problèmes d'optimisation, puis j'ai créer un nouveau projet et j'ai tester ce code:
#include <iostream>
#include <SFML/System.hpp>
#include <SFML/Graphics.hpp>
using namespace std;
int main()
{
sf::Texture m_mouse_texture;
m_mouse_texture.loadFromFile("cursor.png");
sf::Sprite m_mouse_sprite;
m_mouse_sprite.setTexture(m_mouse_texture);
m_mouse_sprite.setTextureRect(sf::IntRect(0,0,30,30));
sf::RenderWindow window(sf::VideoMode(800, 600), "My window");
// on fait tourner le programme jusqu'à ce que la fenêtre soit fermée
while (window.isOpen())
{
// on inspecte tous les évènements de la fenêtre qui ont été émis depuis la précédente itération
sf::Event event;
while (window.pollEvent(event))
{
// évènement "fermeture demandée" : on ferme la fenêtre
if (event.type == sf::Event::Closed)
window.close();
}
window.clear(sf::Color(255,255,255));
m_mouse_sprite.setPosition(sf::Mouse::getPosition(window).x,sf::Mouse::getPosition(window).y);
window.draw(m_mouse_sprite);
window.display();
}
return 0;
}
Et toujours le même problème. Quelqu'un aurait une idée pour résoudre ce problème?
Merci d'avance!
-
Peut-être que c'est trop lourd de récupérer la position de la souris à chaque boucle.
-
Pour provoquer un tel ralentissement, avec un code aussi basique que ça? Je ne pense pas. De plus l'application tourne à 60fps sans soucis, donc ce n'est pas un problème de ralentissement. C'est plutôt comme si la fonction pour récupérer la position de la souris n'actualisais celle-ci que de temps en temps. D'où le retard entre mon curseur et mon image...
Edit: Je tiens à préciser qu'on obtient le même problème en utilisant l'event MouseMoved.
-
Minuscule amélioration :
Au lieu d'appeler la fonction getPosition de la souris deux fois, pour x et pour y, crée une variable avant ta boucle et remplie-la à chaque tour. Ensuite, tu envoies les composantes x et y de cette variable au setPosition de ton image. Comme ça tu calcule une bonne fois pour toute les coordonnées, au lieu de le faire deux fois.
-
Toujours le même problème :/
Avec MouseMoved mon code donne ça:
#include <SFML/Graphics.hpp>
int main()
{
// création de la fenêtre
sf::RenderWindow window(sf::VideoMode(800, 600), "My window");
sf::Texture m_mouse_texture;
m_mouse_texture.loadFromFile("cursor.png");
sf::Sprite m_mouse_sprite;
m_mouse_sprite.setTexture(m_mouse_texture);
m_mouse_sprite.setTextureRect(sf::IntRect(0,0,30,30));
int mouse_x = 0;
int mouse_y = 0;
// on fait tourner le programme tant que la fenêtre n'a pas été fermée
while (window.isOpen())
{
// on traite tous les évènements de la fenêtre qui ont été générés depuis la dernière itération de la boucle
sf::Event event;
while (window.pollEvent(event))
{
// fermeture de la fenêtre lorsque l'utilisateur le souhaite
if (event.type == sf::Event::Closed)
window.close();
if (event.type == sf::Event::MouseMoved)
{
mouse_x = event.mouseMove.x;
mouse_y = event.mouseMove.y;
}
}
// effacement de la fenêtre en noir
window.clear(sf::Color::Black);
m_mouse_sprite.setPosition(mouse_x,mouse_y);
window.draw(m_mouse_sprite);
// fin de la frame courante, affichage de tout ce qu'on a dessiné
window.display();
}
return 0;
}
Et toujours le même problème :/
-
Pas le choix, le temps que tu dessines ton sprite le vrai curseur géré par l'OS est déjà ailleurs.
Y'a des méthodes pour modifier le curseur directement avec des méthodes spécifiques à l'OS, mais je ne les connais pas. Y'a eu des discussions à ce sujet (avec du code il me semble) sur le forum anglais.
-
C'est bizarre car je n'ai pas ce problème sous un autre pc sous windows(pc moins puissant qui plus est) et je n'avais aucun problème à l'époque sous ubuntu avec la SFML 1.6 :/
On ne peux pas dire que ce problème soit vraiment gênant, mais ça donne l'impression que l'application rame, alors que pas du tout >_<
De plus, il me semblais que sf::Mouse::getPosition faisait directement appel à l'os pour connaitre la position du curseur. Avec une application qui tourne à 60fps et le fait qu'on récupère la position de la souris à chaque frame, ça nous donne 60 déplacements du sprite possible pour suivre le curseur. Donc en théorie, on ne devrais pas voir un aussi gros décalage entre les deux :/
-
C'est peut-être un problème avec ubuntu. Ou c'est juste comme disai G. que l'affichage du sprite est long.
-
Essaie ça :
sf::Vector2i mouse_pos;
// on fait tourner le programme tant que la fenêtre n'a pas été fermée
while (window.isOpen())
{
// on traite tous les évènements de la fenêtre qui ont été générés depuis la dernière itération de la boucle
sf::Event event;
while (window.pollEvent(event))
{
// fermeture de la fenêtre lorsque l'utilisateur le souhaite
if (event.type == sf::Event::Closed)
window.close();
}
// effacement de la fenêtre en noir
window.clear(sf::Color::Black);
// C'est peut-être mieux de prendre la pos de la souris après le clear
mouse_pos = sf::Mouse::getPosition(window);
// ça je suis pas sur, mais ça permettrait de placer le curseur de l'OS sur ta pos enregistrée :
sf::Mouse::setPosition(mouse_pos);
m_mouse_sprite.setPosition(mouse_pos.x, mouse_pos.y);
window.draw(m_mouse_sprite);
// fin de la frame courante, affichage de tout ce qu'on a dessiné
window.display();
}
-
Merci pour votre aide mais le problème persiste :/
Le fait de redonner la position de l'image au curseur fait que la souris est bloquée dans le coin gauche de l'écran. Et c'est tout à fait normal. En fait, mouse_pos = sf::Mouse::getPosition(window); vaut, au début du programme 0,0. Juste après avoir récupérer ces valeurs, on repositionne directement la souris à cet emplacement sans qu'elle ait u le temps de bouger entre deux. Du coup, elle reste coincée dans le coin haut gauche de l'écran. Bien sur, on aurait le même résultat pour n'importe qu'elle autre valeur.
TheKingArthur, j'y ai réfléchis, et j'ai modifier l'image de mon sprite pour ne contenir que le curseur. L'image est donc un simple carrer de 30x30. J'ai retenter, et j'ai toujours le même problème.
Je pense en effet que ça vient d'ubuntu, mais apparemment je ne suis pas le seul à avoir le problème :/
-
J'ai vérifié sur Windows, il y a aussi un décalage, mais très léger, c'est peut-être du à un changement de contexte pour la récupération de la position de la souris via l'OS, entre l'enregistrement des coordonnées, l'effaçage de la fenêtre, et l'affichage du sprite... Quoiqu'il-en-soit, je pense pas que tu puisses y remédier, sauf si Laurent n'est pas de mon avis, et si le décalage n'est que de quelques pixels, ça sera pas trop gênant, généralement quand on clique c'est pas à la volée :)
-
Il y a à peu près deux ans, j'ai créer la base d'un éditeur de map iso avec la sfml 1.6 sous windows. J'ai encore le programme et je l'ai tester. Et j'ai 0 décalage entre mon curseur et le sprite de ma souris :/
-
Il y a peut-être une solution, mais par contre je suis désolé, j'ai pas le temps de te donner un code.
Je t'explique :
- Tu replaces à chaque tour de boucle ton curseur au centre de ta fenêtre.
- Dès que tu récupères un event correspondant à un mouvement de souris, tu calcules le vecteur, la distance, enfin un truc comme ça, je pense que tu vas comprendre, entre la nouvelle position et le centre de la fenêtre.
- Tu déplaces ton sprite selon ce vecteur.
(En gros ton sprite ne suit plus directement le curseur, il ne fait que respecter son mouvement)
Ça devrait améliorer tout ça :)
-
ça m'a l'air de fonctionner, mais ça ne donne pas trop l'impression d'être fluide :/
#include <iostream>
#include <SFML/Graphics.hpp>
using namespace std;
int main()
{
// création de la fenêtre
sf::RenderWindow window(sf::VideoMode(800, 600), "My window");
window.setMouseCursorVisible(false);
sf::Texture m_mouse_texture;
m_mouse_texture.loadFromFile("cursor.png");
sf::Sprite m_mouse_sprite;
m_mouse_sprite.setTexture(m_mouse_texture);
m_mouse_sprite.setPosition(0,0);
sf::Vector2i mouse_pos;
// on fait tourner le programme tant que la fenêtre n'a pas été fermée
while (window.isOpen())
{
// on traite tous les évènements de la fenêtre qui ont été générés depuis la dernière itération de la boucle
sf::Event event;
while (window.pollEvent(event))
{
// fermeture de la fenêtre lorsque l'utilisateur le souhaite
if (event.type == sf::Event::Closed)
window.close();
if (event.type == sf::Event::MouseMoved)
{
mouse_pos.x = event.mouseMove.x-400; // -400 et -300 car le curseur est centrer dans la fenêtre.
mouse_pos.y = event.mouseMove.y-300; // Cela permet d'avoir directement les distances du vecteur
}
}
m_mouse_sprite.move(mouse_pos.x,mouse_pos.y);
// effacement de la fenêtre en noir
window.clear(sf::Color::Black);
window.draw(m_mouse_sprite);
// fin de la frame courante, affichage de tout ce qu'on a dessiné
window.display();
sf::Mouse::setPosition(sf::Vector2i(window.getPosition().x+400,window.getPosition().y+300)); // Pour centrer le curseur dans la fenêtre
}
return 0;
}
sf::Mouse::setPosition n'est pas trop gourmand?
Edit: J'ai essayer dans mon programme principale, et c'est juste une horreur :/ Le sprite ne se déplace que de temps en temps, et j'ai aussi remarquer que MouseMoved vallait toujours true.
A mon avis, le fait d'utiliser sf::Mouse::setPosition met MouseMoved à true(ce qui serait compréhensible)
-
C'est possible. Au pire, au lieu de passer par les event, tu stockes la position précédente de la souris, et si la position en cours est différente, tu calcules la différence, le vecteur machin, et tu fais la même chose... :)
-
Toujours le même problème :/
Mais vue que j'ai le même problème sous windows, ça ne vient pas de l'os mais bien de la sfml :/
-
Si c'est un bug de la sfml tu devrais le signaler au cas ou il pourrait être réglé dans un future version.
-
Up, j'ai exactement le même problème, et aucune solution ne s'offre à moi :/
-
Il faudrait essayer dans la version 2.2 voir si le problème est toujours présent :/