Bienvenue, Invité. Merci de vous connecter ou de vous inscrire.
Avez-vous perdu votre e-mail d'activation ?

Auteur Sujet: Probleme de repositionnement  (Lu 4420 fois)

0 Membres et 1 Invité sur ce sujet

Geeque

  • Newbie
  • *
  • Messages: 13
    • Voir le profil
Probleme de repositionnement
« le: Juin 02, 2016, 01:41:04 pm »
Bonjour, toujours dans le cadre de mon projet mario, j'arrive désormais à detecter mes collisions avec mon tileset. J'ai donc tenter de repositionner mon sprite de 32 pixels vers le haut via le void Repositionnement() , avec des cout je constate qu'il le prend bien en compte mais n'arrive pas à comprendre pourquoi mon sprite ne se repositionne pas par la suite. C'est pourquoi je viens sur le forum afin de trouver de l'aide. Voici le code de ma classe personnage.hpp .
#ifndef PERSONNAGE_HPP
#define PERSONNAGE_HPP

#include <stdio.h>

using namespace std;

// Objet inerte pour le personnage
class Personnage
{
// Attributs
private:
        sf::Texture _Mario;
        sf::Sprite _spriteMario; //Personnage du joueur
        int blockSize=32; // taille du personnage
        enum Direction{Down,Left,Right,Up};
        sf::Vector2i anim;
        sf::Clock time;
       
        // Acceleration du personnage
        float accX = 0.2f;
        float speedX = 0.f;
        float speedY = 0.f;
       
        // Acceleration maximale
        float maxSpeedX = 5.0f;
        float maxSpeedY = 10.0f;
       
        // Vitesse du saut
        float jumpSpeed = 10.0f;
       
        // Gravité
        float gravity = 0.5f;
       
        bool jumping = false;           //saut initialisé à faux
        bool moveRequest = false;       //Requete de mouvement (si on appui sur une touche) initialisé à faux
       
        sf::FloatRect   _headboxPerso;
       
// Méthodes
public:

        Personnage() :
                _spriteMario()
        {
                if(!_Mario.loadFromFile("./src/graphics/SpriteMario.png"))
                        cout << ">> Erreur lors du chargement SpriteMario.png"<<endl;
                _Mario.setSmooth(true);
                _spriteMario.setTexture(_Mario);
               
                // Initialisation du personnage
                _spriteMario.setPosition(0,0);
               
                anim.x=1;
                anim.y=Right;
        }
       

        ~Personnage()
        {}

        void processEvent(const sf::Event& event)
        {
        }

        void update()
        {
                _spriteMario.move(speedX, speedY);
               
                moveRequest = false;
               
                // Gestion des touches Gauche et Droite
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left)){
                        anim.y=Left;
                        speedX -= accX;
                        moveRequest = true;
                }
                if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right)){
                        anim.y=Right;
                        speedX += accX;
                        moveRequest = true;
                }
       
                // Gestion de la touche Haut
                if ((sf::Keyboard::isKeyPressed(sf::Keyboard::Up)) && !jumping){
                        speedY = -jumpSpeed;
                        jumping = true;
                }
               
                // Si le _spriteMario arrive au niveau du sol  
                if (_spriteMario.getPosition().y >= 544) {
                        _spriteMario.setPosition(_spriteMario.getPosition().x, 545);
                        jumping = false;
                }
               
                // Blocage de la vitesse maximale du _spriteMario
                if (speedX > maxSpeedX) speedX = maxSpeedX;
                if (speedX < -maxSpeedX) speedX = -maxSpeedX;
                if (speedY < -maxSpeedY) speedY = -maxSpeedY;
               
                // Acceleration de la vitesse pour retomber au sol
                speedY += gravity;
               
                if (!moveRequest){
                        if (speedX<0) speedX += accX;
                        if (speedX>0) speedX -= accX;
                       
                        if (speedX > 0 && speedX < accX) speedX = 0;
                        if (speedX < 0 && speedX > -accX) speedX = 0;
                }
               
               
                if (moveRequest){
                        // Animation du _spriteMario
                        if ((time.getElapsedTime().asMilliseconds())>=50){
                                anim.x++;
                                if(anim.x*blockSize>=(signed)_Mario.getSize().x)
                                        anim.x=0;time.restart();
                        }
                }
               
                if(_spriteMario.getPosition().x+blockSize<0)
                        _spriteMario.setPosition(800,_spriteMario.getPosition().y);
                if(_spriteMario.getPosition().x>800)
                        _spriteMario.setPosition(0-blockSize,_spriteMario.getPosition().y);
       
       
                // Découpage du sprite
                _spriteMario.setTextureRect(sf::IntRect(anim.x*blockSize,anim.y*blockSize,blockSize,blockSize));
               
                _headboxPerso=_spriteMario.getGlobalBounds();
        }
       
        void Reposition()
        {
                _spriteMario.setPosition(_spriteMario.getPosition().x,_spriteMario.getPosition().y-31);
        }
       
        sf::FloatRect Headbox()
        {
                update();
                return _headboxPerso;
        }
       
        void draw(sf::RenderWindow& _window)
        {
                // Affichage du personnage
                _window.draw(_spriteMario);
        }
};

#endif
 

Cpl.Bator

  • Hero Member
  • *****
  • Messages: 540
    • Voir le profil
Re : Probleme de repositionnement
« Réponse #1 le: Juin 02, 2016, 02:34:34 pm »
- J'ai pas vu d'appel à ta méthode.
- Utilise un sf::Vector2f pour stocker la position de ton personnage.
- Évite les Set/Get dans tout les sens sur la position de ton sprite. un seul SetPosition suffit avec le Vector2f précédemment cité.

G.

  • Hero Member
  • *****
  • Messages: 1593
    • Voir le profil
Re : Probleme de repositionnement
« Réponse #2 le: Juin 02, 2016, 02:34:48 pm »
On ne voit même pas où tu appelles Reposition() (et encore moinsRepositionnement()) donc dur à dire ce qu'il se passe.

Geeque

  • Newbie
  • *
  • Messages: 13
    • Voir le profil
Re : Probleme de repositionnement
« Réponse #3 le: Juin 02, 2016, 02:55:56 pm »
Je ne vois pas comment contrer les Set/get du fais que je veux remonter mon personnage de 32 pixels,
j'appelle Reposition() dans mon application.hpp comme ceci :
if(_headboxPerso.intersects(_headboxRect)){
        _rectangle[y][x].setFillColor(sf::Color(0,255,0,128)); // Filtre si le personnage rentre en collision
        _perso.Reposition();
}
« Modifié: Juin 02, 2016, 03:01:47 pm par Geeque »

Geeque

  • Newbie
  • *
  • Messages: 13
    • Voir le profil
Re : Probleme de repositionnement
« Réponse #4 le: Juin 02, 2016, 06:59:11 pm »
Afin de mieux comprendre le soucis, voici le application.hpp

#ifndef APPLICATION_HPP
#define APPLICATION_HPP

#include <iostream>
#include <fstream>
#include <SFML/Graphics.hpp>
#include "scene.hpp"
#include "map.hpp"
#include "personnage.hpp"

class Application
{
        // Graphique
        sf::RenderWindow                _window;
       
        sf::Texture                             _background;
        sf::Sprite                              _spriteBackground;
       
        sf::FloatRect                   _headboxPerso;
       
        sf::RectangleShape              _rectangle[19][26];
        sf::FloatRect                   _headboxRect;
       
        // Logique
        Scene                                   _scene;
        TileMap                                 _map;
        Personnage                              _perso;

public:
        Application():
        _window(sf::VideoMode(800, 600), sf::String(L"Projet Mario")),
        _scene(_window)
        {
                if(!_background.loadFromFile("./src/graphics/background.jpg"))
                        cout << ">> Erreur lors du chargement background.jpg"<<endl;
                _spriteBackground.setTexture(_background);
               
                int level_string[19][26] = { 0 };
                int level[19][26] = { 0 };

                fstream fichier("./src/graphics/map.txt");
                if (!fichier)
                        cout << "niveau inexistant" << endl;
                else
                {
                        int y = 0;
                        string ligne;
                        while (!fichier.eof())
                        {
                                getline(fichier, ligne); // On recupere une ligne dans le fichier sous la forme d'une string
                                for (int x = 0; x<(signed)ligne.length(); x++)
                                {
                                        //ligne[i] renvoit le caractère placer a la i ème position.
                                        level_string[y][x] = ligne[x];
                                }
                                y++;
                        }
                }
                for (int y = 0; y < 19; y++) {
                        for (int x = 0; x < 26; x++) {

                                switch (level_string[y][x]) {
                                case 'X':
                                        _rectangle[y][x].setSize(sf::Vector2f(32,32));
                                        _rectangle[y][x].setPosition(x*32,y*32);
                                        level[y][x] = 0;
                                        break;
                                case 'P':
                                        _rectangle[y][x].setSize((sf::Vector2f(32,32)));
                                        _rectangle[y][x].setPosition(x*32,y*32);
                                        level[y][x] = 2;
                                        break;
                                default :
                                        level[y][x] = 30;
                                }
                        }
                }
                               
                // on crée la tilemap avec le niveau précédemment défini
                if (!_map.load("./src/graphics/tileset.png", sf::Vector2u(32, 32), level, 26, 19))
                        cout<<"erreur chargement tileset"<<endl;
        }

        void run()
        {
                sf::Clock clock;
                while (_window.isOpen())
                {
                        processEvents();
                        update();
                        render();      
                }
        }

protected:
        // Boucle événementielle
        void processEvents()
        {
                sf::Event event;
                while (_window.pollEvent(event))
                {
                        _scene.handleEvent(event);

                        if (event.type == (sf::Event::Closed) || (sf::Keyboard::isKeyPressed(sf::Keyboard::Escape)))
                                _window.close();                       
                }
        }

        void update()
        {
                _headboxPerso=_perso.Headbox();
                for(int y=0;y<19;y++){
                        for(int x=0;x<25;x++){
                                _headboxRect=_rectangle[y][x].getGlobalBounds();
                                if(_headboxPerso.intersects(_headboxRect)){
                                        _rectangle[y][x].setFillColor(sf::Color(0,255,0,128)); // Filtre si le personnage rentre en collision
                                        _perso.Reposition();
                                }
                                else
                                {
                                        _rectangle[y][x].setFillColor(sf::Color(255,0,0,128)); // Filtre par defaut
                                }
                        }
                }
                _scene.update();
        }

        void render()
        {              
                _window.clear();
                _window.draw(_spriteBackground);
                _map.draw(_window);
               
                for(int y=0;y<19;y++){
                        for(int x=0;x<25;x++){
                                _window.draw(_rectangle[y][x]); // Visualiser les collisions avec le systeme de filtre
                        }
                }
                _scene.draw();
                _window.display();
        }
};

#endif
 

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Probleme de repositionnement
« Réponse #5 le: Juin 02, 2016, 08:24:12 pm »
Donc lorsque ton personnage se trouve sur une case de la map (ce qui est normalement toujours le cas non ?), il collisionne et bouge de 31 pixels vers le haut. A partir de là, comment pourrait-il ne pas rester coincé tout en haut de la map, si chacune des cases le pousse violemment vers le haut jusqu'à ce qu'il soit en dehors ?

Ici il manque visiblement deux choses :
- tester si la tile est "collidable" ou non
- repousser le personnage dans la direction d'où il vient plutôt qu'arbitrairement vers le haut

Ensuite, drôle de façon de gérer les collisions. Pas la peine de parcourir toutes les tiles alors que tu sais très bien que celle sur laquelle se trouve le personnage a pour indices [perso_y / tile_height][perso_x / tile_width].
Laurent Gomila - SFML developer

Cpl.Bator

  • Hero Member
  • *****
  • Messages: 540
    • Voir le profil
Re : Re : Probleme de repositionnement
« Réponse #6 le: Juin 02, 2016, 10:25:13 pm »
Je ne vois pas comment contrer les Set/get du fais que je veux remonter mon personnage de 32 pixels,

pseudo code :

void update(float dt) {
 
  monPersoPos.x = ...  /* membre sf::Vector2f */
  monPersoPos.y = ...

 if ( monPersoPos.x >= ... ...

 if ( monPersoPos.y <= ... ...

}

void methodeBizarre(){
  monPersoPos.y -= 32;
}

void draw(renderTarget & target) {

  monPersoSprite.setPosition(monPersoPos); /* 1 seul set */
  target.draw(monPersoSprite);

}
 

Geeque

  • Newbie
  • *
  • Messages: 13
    • Voir le profil
Re : Probleme de repositionnement
« Réponse #7 le: Juin 02, 2016, 10:59:18 pm »
Bonsoir et merci de vos réponse , en revanche mon sprite ne se met pas toujours en collision , en fait il teste avec les rectangleShape et ceux ci ne contiennent uniquement que les plateformes et mon sol

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Probleme de repositionnement
« Réponse #8 le: Juin 03, 2016, 06:21:56 am »
Donc les _rectangle de cases "vides" sont crées, testés et dessinés, mais avec une taille et position nulle ? Et... ces instances de sf::RectangleShape ne te servent qu'à faire les collisions ??

Déjà c'est un gaspillage monumental, mais ensuite un rectangle de taille nulle est tout de même un point, qui peut entraîner des collisions.
Laurent Gomila - SFML developer

Geeque

  • Newbie
  • *
  • Messages: 13
    • Voir le profil
Re : Probleme de repositionnement
« Réponse #9 le: Juin 03, 2016, 08:26:32 am »
Les rectangles sont initialisé avec une taille de 32*32, en fait le soucis est que j'arrive à détecter cette fameuse collision en revanche mon sprite ne se positionne pas corectement

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Probleme de repositionnement
« Réponse #10 le: Juin 03, 2016, 08:49:04 am »
Citer
Les rectangles sont initialisé avec une taille de 32*32
Seulement les rectangles collidables, non ? Les autres (ni 'X' ni 'P') restent avec leurs attributs par défaut -- qui d'ailleurs pourraient être n'importe quoi, autre que taille et position nulles.

Sinon, plutôt qu'on passe des jours à essayer de comprendre comment fonctionne la logique de ton programme, tu devrais commencer à debugger le truc de ton côté, tu iras bien plus vite. Fais des exécution pas à pas avec ton debugger, ou bien dump les valeurs des variables pertinentes dans la console aux moments clés. Parfois scruter du code ne suffit pas à comprendre ce qui va de travers, il faut regarder ce qui se passe réellement durant l'exécution pour comprendre.
Là ça ne devrait pas être bien compliqué : regarde comment évolue la position de ton personnage lors d'une collision. Tu devrais tout de suite trouver à quel moment sa position dévie de ce à quoi tu t'attends.
Laurent Gomila - SFML developer

Geeque

  • Newbie
  • *
  • Messages: 13
    • Voir le profil
Re : Probleme de repositionnement
« Réponse #11 le: Juin 05, 2016, 12:21:26 am »
Bonsoir, voilà après debuggage je constate que dans le voir Reposition () le sprite se remet bien à la position, or, lors du update () mon personnage n'as pas bouger et je constate également que si je fait un booléen de sorte à le repositionner autre part que dans la fonction celui ci je cesse de rebasculer en faux même s'il est initialisé à rien et que dans reposition() je le passe à true