Bien le bonjour à tous !
Voilà, bon je culpabilise un peu de poster encore une question idiote, mais sincèrement je ne sais pas ce qu'il se passe !
J'ai un sprite que j'anime et déplace en utilisant les touches du clavier. Pour garantir la vitesse de ce sprite, j'ai suivi tout bêtement une méthode trouvée sur le net, simplement il arrive que mon personnage ralentisse (très fortement) pendant quelques secondes, avant de reprendre sa vitesse normale.
Je me demande donc ce que j'ai fait de mal !
Comme du code vaut mieux qu'un long discours, je vous recopie les parties en question.
Moteur.cpp où la classe Personnage est instanciée et où les touches du clavier sont récupérées :
#include "Moteur.h"
Moteur::Moteur() {
m_fenetre = new sf::RenderWindow;
}
Moteur::~Moteur() {
delete m_fenetre; // m_fenetre est alloué dynamiquement, on le détruit ici.
}
void Moteur::init()
{
m_fenetre->create(sf::VideoMode(800, 600), "La fenetre");
}
void Moteur::boucleJeu()
{
Personnage Personnage;
while (m_fenetre->isOpen()) // Boucle de jeu
{
sf::Event event; // La variable event reçoit tous les événements utilisateur
while (m_fenetre->pollEvent(event)) { // Tous les événements sont traités à la suite
switch (event.type) {
case sf::Event::Closed:
m_fenetre->close();
break;
default:
break;
}
}
clavierDetect(Personnage);
m_fenetre->draw(Personnage.getSprite()); // On affiche le sprite à l'écran
m_fenetre->display();
m_fenetre->clear();
}
}
void Moteur::clavierDetect(Personnage & PersonnageADeplacer) {
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
PersonnageADeplacer.animPerso(1, -1, Droite);
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
PersonnageADeplacer.animPerso(-1, -1, Gauche);
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
PersonnageADeplacer.animPerso(0, 1, Bas);
else
PersonnageADeplacer.animPerso(0, -1, Haut);
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
PersonnageADeplacer.animPerso(1, 1, Droite);
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
PersonnageADeplacer.animPerso(-1, 1, Gauche);
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
PersonnageADeplacer.animPerso(0, -1, Haut);
else
PersonnageADeplacer.animPerso(0, 1, Bas);
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
PersonnageADeplacer.animPerso(1, 0, Droite);
else
PersonnageADeplacer.animPerso(-1, 0, Gauche);
}
else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
{
if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
PersonnageADeplacer.animPerso(-1, 0, Gauche);
else
PersonnageADeplacer.animPerso(1, 0, Droite);
}
}
Et enfin Personnage.cpp (qui contient donc la fameuse méthode "animPerso()"
#include "Personnage.h"
Personnage::Personnage() : m_nom("John Malkovitch"), m_spritePersonnage(), m_frameCounter(0), m_frameSpeed(500), m_frameSwitch(100), m_frameClock(), m_frameUpdate(true), m_mvtClock(), m_mvtCounter(0), m_mvtSpeed(10000), m_mvtSwitch(10), m_mvtUpdate(true)
{
if (!m_texturePersonnage.loadFromFile("texturePersonnage.png")) {
std::cout << "Erreur : texturePersonnage ne s'est pas chargé." << std::endl;
}
/* On charge du fichier, l'instruction sf::IntRect permet de découper à la volée dans notre texture celle qui nous intéresse */
m_spritePersonnage.setTexture(m_texturePersonnage); // On charge la texture dans le sprite
m_source.x = 1;
m_source.y = Bas;
}
void Personnage::animPerso(short x, short y, short dir) {
m_source.y = dir;
m_mvtCounter = (m_mvtUpdate) ? m_mvtCounter + m_mvtSpeed * m_mvtClock.restart().asSeconds() : 0;
if (m_mvtCounter >= m_mvtSwitch) {
m_mvtCounter = 0;
m_spritePersonnage.move(x, y);
}
m_frameCounter = (m_frameUpdate) ? m_frameCounter + m_frameSpeed * m_frameClock.restart().asSeconds() : 0;
if (m_frameCounter >= m_frameSwitch) {
m_frameCounter = 0;
m_source.x++;
if (m_source.x * 32 >= m_texturePersonnage.getSize().x) {
m_source.x = 0;
}
}
}
sf::Sprite Personnage::getSprite()
{
m_spritePersonnage.setTextureRect(sf::IntRect(m_source.x * 32, m_source.y * 32, 32, 32));
return m_spritePersonnage;
}
En me relisant j'ai l'impression que ce que je raconte est incompréhensible. N'hésitez pas à me le dire ! Je préciserai !
Bon et une fois de plus désolé pour la question pas intelligent, promis, promis avec le temps j'en poserai moins.
Et merci d'avance !
Ta méthode Moteur::boucleJeu() ne gère pas le temps dans le while.
rajouter un sf::sleep devrait régler le problème.
(et soulager ton processeur :) )
Voici un lien vers le tutoriel correspondant : Tutoriel - Système - Gérer le temps (http://www.sfml-dev.org/tutorials/2.0/system-time-fr.php).
Jette aussi un coup d'œil à sf::Clock (http://www.sfml-dev.org/documentation/2.0/classsf_1_1Clock.php).
EDIT :
Pour être plus précis :
while(m_fenetre->isOpen()){
//stuff
}
s’exécutera le plus vite possible.
sf::sleep() fait une pause dans l'exécution du programme :
/!\ Attention/!\
sf::sleep() prends un sf::Time en argument avec la SFML2.
while(m_fenetre->isOpen()){
//stuff
sf::sleep(sf::seconds(1.f/60.f))
}
Avec le code ci-dessus tes FPS seront légèrement inférieures à 60 du à la durée d’exécution de //stuff
pour corriger ça je te propose de chronométrer la durée de ta boucle et de l'ôter à sf::sleep() :
sf::Clock chrono;
while(m_fenetre->isOpen()){
//stuff
sf::sleep(sf::seconds(1.f/60.f - chrono.getElapsedTime().asSeconds()));
chrono.restart();
}
Tu peux désormais considérer qu'il se passe toujours la même durée entre deux frames;
/!\ Attention /!\
Si ton code met plus de 1/60ème de seconde à s’exécuter sf::sleep() ne servira à rien;
tu devras considérer un FPS plus bas. (1/20ème est encore correct pour un jeu ;) )
Protip 8)
const sf::Time FRAME__TIME = sf::seconds(1.f/60.f);
float time_delta; //temps écoulé durant la dernière frame (en secondes)
while(m_fenetre->isOpen()){
//stuff
time_delta = chrono.getElapsedTime().asSeconds();
sf::sleep(FRAME_TIME - chrono.restart());
}
sf::Time possède un opérateur - ;
sf::Clock::restart() retourne un sf::Time ;
utilise les pour simplifier ton code;
Et time_delta permet d'obtenir des mouvements "parfaitement" chronométrés quelque-soit les FPS :
déplacement en 1 seconde * fraction de seconde = déplacement durant une fraction de seconde
PS : J'en ai peut-être fait un peu trop.
J’espère avoir été utile.
et bonne journée. :)