Bonjour/Bonsoir,
Je travail actuellement sur un jeu de combat entre 2 joueurs, chacun disposant de son gamepad.
Je suis confronté à un problème assez difficile (pour moi) à résoudre, en effet j'essaie de lire le joystick de chacun des joueurs pour pouvoir traiter leurs mouvement indépendamment de l'autre.
J'entends par là cet exemple : Si le joueur 1 effectue un saut (en comptant l'animation du saut cela durera un certain temps) alors le joueur 2 doit aussi être capable d'effectuer son mouvement indépendamment du mouvement du joueur 1.
C'est justement cette condition de gameplay que je n'arrive pas à réalisé.
Précision pour la suite : Je lis les valeurs du pavé directionnel du Joystick uniquement pour le moment, afin de déplacer le joueur.
Voici comment j'ai tenté la chose :
1 - Créer un personnage (j'ai nommé class Character),
disposant de l'ID du joystick à entrer dans le constructeur et de pleins d'autres informations au sujet du personnage.
2 - Un thread nommé : controllerThreaded à l'intérieur de l'objet Character lance par la suite ma méthode "Move()".
(1)Cette méthode lis les informations du pavé directionnel du joystick et les insèrent dans un Vector2f nommé m_controller.
(2)La méthode "Move()" utilise par la suite une méthode privé qui "filtrera" les données et me renverra une valeur (0,1,2,ect...) correspondant à un état de mouvement.
Exemple : La méthode qui filtre les données me renvoie "1", je considère cette valeur comme faisant référence à un "saut". Tout cela à été parfaitement défini en commentaire dans mon code.
(3)Une fois cette valeur renvoyé je peux commencé à traité le mouvement, en fonction de ce qui ma été renvoyé un mouvement s'effectuera et le personnage bougera.
3 - Dans le main.cpp je créé un Thread nommé tw1 qui lancera (en principe) le thread programmé dans mon objet
C'est ici que le problème arrive, ayant testé ces méthode au cours du développement avec un unique personnage, aucun problème en vue, tout bougeaient parfaitement.
Mais maintenant que je veux adapter cela pour 2 joueurs l'utilisation du Thread ma paru obligatoire, le programme se comporte assez bizarrement, parfois il se bloque et ne fait plus rien, parfois il plante.
C'est là que j'ai besoin de vous, chère communauté ! - Est-ce que je tente de résoudre le problème correctement en passant à un Thread la méthode Move() ?
- Est-ce que l'appel de la seconde méthode qui filtre les valeurs lue par le Joystick pose problème ?
- Ai-je autre chose à faire en plus (voir code) pour que cela fonctionne ou ma façon d'utiliser les Thread sont un peu bancal ?
Je vous avouerai que je ne suis pas très à l'aise avec l'utilisation des Thread surtout avec l'utilisation d'un objet, même après avoir pas mal lu d'informations et exemples à ce sujet.
Je vous remercie d'avance avoir lu jusqu'ici et pour l'aide que vous pouvez m'apportez pour résoudre ce problème.
Pour les intéressé voici visuellement ce que j'expliquais plus haut :Character.hpp
#include <SFML\Graphics.hpp>
#include <thread>
#include <iostream>
class Character : public sf::Drawable
{
public:
Character(sf::RenderWindow & window, float const xPosition, float const yPosition, int8_t const joystickNumber); // Pour positionner le sprite et avoir l'ID du Joystick
void Move(); // Méthode qui effectue le mouvement du personnage + lecture des données Joystick
std::thread controllerThreaded() { // Le thread qui lance la méthode "Move()"
return std::thread([this] { this->Move(); });
}
~Character();
private:
virtual void draw(sf::RenderTarget & target, sf::RenderStates states) const {
target.draw(m_sprite); // Permettra d'afficher le sprite via le main.cpp
}
short m_movementFilter(sf::Vector2f & controller); // Le filtre en question pour savoir quel mouvement est effectué
// Des attributs...
};
Character.cpp
#include "Character.hpp"
Character::Character(sf::RenderWindow & window, float const xCharacterPosition, float const yCharacterPosition, int8_t const joystickNumber)
: m_speedMovement(0.0f), m_maxSpeed(3.0f),
m_right(false), m_left(false), m_jump(false), m_crouch(false), m_rightCrouch(false), m_leftCrouch(false), m_rightJump(false), m_leftJump(false),
m_joystickNumber(joystickNumber)
{
// Rien qui nous intéresse
}
void Character::Move()
{
// Lis les données du Joystick et les stockent dans m_controller
m_controller.x = sf::Joystick::getAxisPosition(m_joystickNumber, sf::Joystick::PovX);
m_controller.y = sf::Joystick::getAxisPosition(m_joystickNumber, sf::Joystick::PovY);
// Moyen de voir dans la console si la méthode fonctionne et lit bien les données du Joystick
std::cout << m_controller.x << " | " << m_controller.y << "\n";
// Le fameux filtre qui me renvoie ladite valeur correspondant au mouvement
short movementType = Character::m_movementFilter(m_controller);
// Interprétation du mouvement
switch (movementType) {
case 0:
{ // Saut + droite
}
case 1:
{ // Saut + gauche
}
case 2:
{ // Saut
}
case 3:
{ // Accroupi + droite
}
case 4:
{ // Accroupi + gauche
}
case 5:
{ // Accroupi
}
case 6:
{ // Droite
}
case 7:
{ // Gauche
}
case 8:
{ // Debout
}
}
}
main.cpp
#include <SFML/Graphics.hpp>
#include <thread>
#include "Character.hpp"
int main()
{
// ##### INITIALISATION DE LA FENÊTRE #####
sf::RenderWindow gameWindow(sf::VideoMode(800, 600, 32), "Game ISN", sf::Style::Default);
gameWindow.setVerticalSyncEnabled(true); // Active la synchronisation vertical (60 fps en général)
// ##### CRÉATION PERSONNAGES #####
Character firstPlayer(gameWindow, 100.0f, 140.0f, 0); // fenêtre, positionX, positionY, ID Joystick
Character secondPlayer(gameWindow, 150.0f, 300.0f, 1); // fenêtre, positionX, positionY, ID Joystick
// C'est LÀ que je lance ce fameux Thread tw1 qui est supposé résoudre mon problème de mouvement indépendant.
std::thread tw1 = firstPlayer.controllerThreaded();
// ##### BOUCLE DU JEU #####
sf::Event event;
while (gameWindow.isOpen())
{
// Gestion des événements
while (gameWindow.pollEvent(event))
{
switch (event.type) {
case sf::Event::EventType::Closed:
{
gameWindow.close();
break;
}
} // Fin : switch(event.type)
} // Fin : boucle événements
gameWindow.clear();
gameWindow.draw(firstPlayer);
gameWindow.draw(secondPlayer);
gameWindow.display();
}
return 0;
}