Problème d'animation d'un sprit

Mon objet heritant de sf::Sprit disparait...

L’auteur de ce sujet a trouvé une solution à son problème.
Auteur du sujet

Bonjours a vous, Apres avoir suivis un tuto pour débuter la sfml, j’ai décider d’animer un petit personnage, le fessant bouger avec les touches ZQSD, tous allait bien quand tous le code ce trouvait dans le fichier main, mais après avoir creer une class "player" heritant de sf::Sprit, mon petit personnage disparait a la pression des touches Q & Z, j’ai tester de supprimer le setTextureRect, le changement de direction, la verification de hors map, l’animation, rien n’y fait Le code : main

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <SFML/Graphics.hpp>
#include <iostream>
#include <array>
#include "player.h"


#pragma region define
#define SPEED 10
#pragma endregion define

#pragma region prototype
void Management_Keyboard(Player &target);
#pragma endregion prototype

int main()
{
    int screenW(640); //Largeur fenetre
    int screenH(480); //Hauteur fenetre
    const size_t tileSize(48);
    sf::Vector2f positionPlayer;
    sf::View view;

    Player player(tileSize);

    sf::RenderWindow window(sf::VideoMode(screenW, screenH, 32), "Test ^.^"); //Creation de la fenetre
    window.setFramerateLimit(20);
    window.setVerticalSyncEnabled(true);
    view.reset(sf::FloatRect(0, 0, screenW, screenH));

    sf::RectangleShape rect;
    rect.setSize(sf::Vector2f(tileSize, tileSize));
    rect.setFillColor(sf::Color::Red);
    rect.setPosition(100, 100);


    while (window.isOpen()) //Boucle evenement
    {
        sf::Event event;
        while (window.pollEvent(event))
        {
            if (event.type == sf::Event::Closed) {
                window.close();
            }   
        }


        Management_Keyboard(player);

        positionPlayer.x = player.getPosition().x + (tileSize / 2) - (screenW / 2);
        positionPlayer.y = player.getPosition().y + (tileSize / 2) - (screenH / 2);
        if (positionPlayer.x < 0) { positionPlayer.x = 0; }
        view.reset(sf::FloatRect(positionPlayer.x, positionPlayer.y, screenW, screenH));


        window.setView(view);
        window.clear(); //Efface la fenetre
        window.draw(player);
        window.draw(rect);
        std::cout << "Dessine le rect" << std::endl;

        std::cout << "Dessine le player" << std::endl;
        window.display(); //Affiche la fenetre
    }

    return 0;
} 

void Management_Keyboard(Player &target){


    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Z)) { target.moove(sf::Vector2u(0, -SPEED)); }

    else if (sf::Keyboard::isKeyPressed(sf::Keyboard::S)) { target.moove(sf::Vector2u(0, SPEED)); }

    else if (sf::Keyboard::isKeyPressed(sf::Keyboard::Q)) { target.moove(sf::Vector2u(-SPEED, 0)); }

    else if (sf::Keyboard::isKeyPressed(sf::Keyboard::D)) { target.moove(sf::Vector2u(SPEED, 0)); }
}

player.h

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#ifndef PLAYER_H_INCLUED
#define PLAYER_H_INCLUDED
#include <SFML\Graphics.hpp>

class Player : public sf::Sprite
{
public:
    Player(size_t tileSize);
    void update(bool update);
    void moove(sf::Vector2u movement);
    void inMap();
    ~Player();

private:
    size_t _tileSize;
    enum _direction { Down, Left, Right, Up };
    sf::Vector2i _animation;
    sf::Texture _texturePlayer;

};

#endif

player.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include "player.h"
#include <iostream>

Player::Player(size_t tileSize) : _animation(1, Down), _tileSize(tileSize)
{
    if (!_texturePlayer.loadFromFile("Ressource/Sprite/Player.bmp")) { std::cout << "Load texture player failed" << std::endl; }
    setTexture(_texturePlayer);
    setPosition(0, 0);
    Player::update(false);
}


void Player::update(bool update)
{
    if (update == true) {
        _animation.x++;
        if (_animation.x * _tileSize >= _texturePlayer.getSize().x) {
            _animation.x = 0;
        }
    }

    setTextureRect(sf::IntRect(_animation.x * _tileSize, _animation.y * _tileSize, _tileSize, _tileSize));

    std::cout << "Je suis mis a jour" << std::endl;
}

void Player::moove(sf::Vector2u movement)
{

    if (movement.x == 0) {
        if (movement.y < 0) { _animation.y = Up; }
        if (movement.y > 0) { _animation.y = Down; }
    }
    if (movement.y == 0) {
        if (movement.x < 0) { _animation.y = Left; }
        if (movement.x > 0) { _animation.y = Right; }
    }

    move(movement.x, movement.y);

    std::cout << "Je bouge" << std::endl;

    Player::inMap();

    Player::update(true);
}

void Player::inMap()
{
    if (getPosition().x < 0) {
        setPosition(0, getPosition().y);
    }
    else { std::cout << "Je suis dans la map" << std::endl; }
}


Player::~Player()
{
}

`

(NOTE : - Le sf::RectangleShape disparait en même temps que le personnage - Tous les std::cout sont des verifications, et tous sont present dans la console (hormis pour le fail de chargement de texture) )

Voila, ceci est mon premier post sur ce forum, je suis debutant et preneur de toute remarque et conseil

Merci d’avance pour votre aide

(EDIT : Code clarifier)

Édité par K4kugen

+0 -0

Cette réponse a aidé l’auteur du sujet

Salut,

Tu dis que le personne disparaît à la pression des touches Q & Z, donc cela fonctionne correctement avec les touches S&D ?

Je ne me suis jamais servir de SFML, donc je ne peux pas voir si il y a un problème de compréhension de la bibliothèque.

Mais sinon, une bonne étape pour trouver le problème, plutôt que de mettre juste des cout, il est intéressant de connaitre la valeur de tes attributs/variables pour trouver pourquoi ça coince : quand ton programme ne fait pas ce que tu veux, tu as de fortes changes que ça puisse venir de données qui sont mal calculées.

Un debugger est pratique pour ça, mais sinon au moins afficher la valeur de movement.x et movement.y quand tu bouges. Si les valeurs sont cohérentes par rapport à ce que tu attends, c’est que le problème vient de plus loin (méthode inMap() ou méthode update ?). Si les données de player sont toutes cohérentes, tu peux aller regarder dans le main si positionPlayer.x et positionPlayer.y correspondent à tes attentes. Il faut jouer au détective ! :zorro:

Tu as dis que cela fonctionnait avant de faire du refactoring, donc qu’est-ce que tu as changé entre temps, uniquement la création d’une classe intermédiaire player ? Il doit manquer un petit quelque chose…


Sinon, quelques remarques sur ton code, afin d’améliorer sa lecture.

  • Ça manque de cohérence, en général il est appréciable d’utiliser des conventions de nommage. Il en existe plusieurs, qui peuvent changer en fonction des langages. Mais l’idée, c’est que d’un simple coup d’œil on puisse différencier un type, d’une fonction, et d’une variable.
    • Un exemple de convention pourrait-être qu’une classe commence par une majuscule (Player), qu’un attribut private commence par un _ (_animation), et les constantes/defines en majuscules SPEED.
  • Choisis si tu nomme en Anglais ou en français, mais ne mélange pas les deux (Gestion_clavier et screenW ou player par exemple)
  • moove ? move c’est mieux :euh:
  • Attention à la position des accolades, je trouve ça plus lisible quand on les met toujours, au même endroit. On est pas à une ligne prêt, pas la peine de compacter comme dans la fonction Gestion_clavier, ou dans le main ligne 43.
  • les this-> ne sont pas indispensable. this n’est qu’un pointeur sur l’objet courant, mais ne pas les mettre fonctionne de la même manière. Le this est indispensable quand il te faut le pointeur de ton objet, mais ce n’est pas le cas ici.

Édité par satenske

+0 -0
Auteur du sujet

Oui, mon personnage bouge pour les touches S & D, d’ou mon trouble Pour les fonction inMap ou update, le problème ne viens pas de la car j’ai essayer de les supprimer, sans succes. Je vais aller vérifier la valeur des variables, histoire d’etre au point (j’editerais ce message avec les resultats) par ailleurs, peut on debugger le programme et envoyer des entrer clavier au programme ? (Dans ce cas, debugger et faire bouger mon perso ?) "positionPlayer" est charger du scrolling, je vais donc l’enlever le temps de trouver la solution, erreur de ne pas l’avoir fait plus tot. Oui j’ai juste creer ma classe, beaucoup du code de player.cpp est d’ailleurs un simple copier coller

Pour la lisibilité : Je vais enlever les this, je les pensais nécessaire , et modifier le noms de mes variables Le "moove" etait pour eviter d’entrer en conflit avec une fonction de sf::Sprit : "move" Les accolades, main ligne 43 je suis d’accord, mais dans Gestion_clavier, je pensais cela plus lisible, sachant qu’une seule action est realiser

Je pars donc ameliorer tous cela, et regarder les valeurs de mes variables, un grand merci a toi pour ton messages, j’appliquerais tous cela a l’avenir

Édité par K4kugen

+0 -0

Cette réponse a aidé l’auteur du sujet

Pour debugger, tu as plusieurs solutions, mais en général, on met un point d’arrêt à l’endroit ou le code t’intéresse, tu utilise ton programme normalement, et en l’occurrence, quand tu appuieras sur une touche de ton clavier, le programme s’arrêtera automatiquement à la ligne correspondante: tu auras tout le loisir de regarder les données de ton programme.

Si le programme est simple, et ne comporte pas énormément de données, une technique qui fonctionne aussi est de faire de simple cout comme tu l’as fait : mais en ajoutant les variables à analyser pour voir leurs valeurs.

La différence entre les instructions S&D et Q&Z, c’est que dans un cas tu fais passer speed dans l’autre cas -speed (respectivement pour x & y), voir si ça vient pas d’un dépassement de la map ou je ne sais quoi.

Les this-> sont toujours facultatifs, le mot clé this n’est utile que pour donner la référence vers ton objet (en paramètre d’une méthode si nécessaire par exemple)

si une méthode move existe déjà dans le contexte, mais avec des paramètres différents, ce n’est pas gênant, la méthode appelée sera celle avec le bon matching de type. Si une méthode virtual avec strictement les même paramètres existe dans la classe mère, elle sera surchargée.

Bon courage en tout cas :pirate:

+0 -0
Auteur du sujet

Je vais modifier la fonction moove en move, l’une prenant un sf::Vector2f, et l’autre un sf::Vector2u, je la surchergerais en cas de problème Tu avais raison, j’ai un gros problème de dépassement : Touche D : movement.x = 10, movement.y = 0 Touche S : movement.x = 0, movement.y = 10 Touche Z : movement.x = 0, movement.y = 4294967286 Touche Q : movement.x = 4294967286, movement.y = 0 Ce qui est un peu hors ecran, cela proviens de mon vecteur prenant des unsigned int, donc les négatifs, il aime pas ca… xd

Pour la solution : la fonction "moove" doit prendre en paramètre un sf::Vector2i

Merci a toi pour l’aide fourni et les conseils donner satenske ^^

J’ai un dernier problème, en renomant ma fonction moove en move, player.cpp ligne 39, je me retrouve avec un code voulant utiliser ma version de move, alors que je veut la version de sf::Sprit xd Une solution ?

Édité par K4kugen

+0 -0

Pour appeler une méthode parente, tu peux faire sf:Spirit:move(…) ;-)

D’ailleurs, dans ton constructeur, Player::update(false);, le Player:: est facultatif : implicitement ça appelle toujours les méthodes de l’objet courant.

+0 -0
Vous devez être connecté pour pouvoir poster un message.
Connexion

Pas encore inscrit ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte