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

Auteur Sujet: Probleme intersection / list.erase  (Lu 1502 fois)

0 Membres et 1 Invité sur ce sujet

Kargan

  • Newbie
  • *
  • Messages: 2
    • Voir le profil
Probleme intersection / list.erase
« le: Mars 08, 2017, 04:25:46 pm »
Bonjour
Pour apprendre à utiliser la SFML, je suis entrain de réaliser un shoot em up trés simple mais j'ai un léger probleme.
Lorsque je touche le premier bloc ( je peux toucher les autres sans probleme ) , la fonction erase se déclenche et au lieu de supprimer le bloc, elle change les coordonnées x de tout mes blocs ce qui cause la fin de la partie.
Ce probleme n'arrive que lors du lancement de l'appli. Si je relance une partie sans fermer l'appli tout se passe correctement.

#include <SFML/Graphics.hpp>
#include <SFML/Audio.hpp>
#include "iostream"
#include <list>
#include <time.h>

using namespace sf;
using namespace std;

const int width = 1600;
const int height = 900;
const int shipRad = 3;
const int shipSize = 30;
const int INTRO=1;
const int JEU=2;
const int FIN=3;

bool intersects (const RectangleShape & rect1,const RectangleShape & rect2)
{
    FloatRect r1=rect1.getGlobalBounds();
    FloatRect r2=rect2.getGlobalBounds();
    return r1.intersects (r2);
}

int fRand(int fMin, int fMax)
{
    int f = (int)rand();
    f=f%fMax;
    return f;
}

int main()
{
    int gameState = INTRO;
    int score;
    char* scoreStr;
    srand(time(NULL));


    Clock clock;
    Clock blocClock;
    Clock moveClock;
    Time time, blocTime, moveTime;
    double speed;


    VideoMode videoMode(width, height);
    RenderWindow window(videoMode,"TOAST");

    CircleShape ship(shipSize,shipRad);
    ship.setPosition(300,200);
    ship.setFillColor(Color::Blue);
    ship.rotate(90);

    list<RectangleShape> laser,bloc;

    Font font;
    font.loadFromFile("OutrunFutureBold.otf");

    Text intro;
    intro.setString("SPACE SHOOTER !!!\n PRESS ENTER TO PLAY");
    intro.setFont(font);
    intro.setPosition(width/15,height/4);
    intro.setCharacterSize(100);
    intro.setColor(Color::White);

    Text fin;
    fin.setFont(font);
    fin.setPosition(width/4,height/4);
    fin.setCharacterSize(100);
    fin.setColor(Color::White);

    Text scoreTxt;
    scoreTxt.setFont(font);
    scoreTxt.setPosition(10,10);
    scoreTxt.setCharacterSize(30);
    scoreTxt.setColor(Color::White);

    while (window.isOpen())
    {
      window.clear(Color::Black);
      if(gameState==INTRO)
      {
          window.draw(intro);
          Event event;
          while (window.pollEvent(event))
          {
              if ( (event.type == Event::Closed) ||
              ((event.type == Event::KeyPressed) && (event.key.code==Keyboard::Escape)) )
                  window.close();

                if((event.type == Event::KeyPressed) && (event.key.code==Keyboard::Return))
                  {
                  laser.clear();
                  bloc.clear();
                  blocClock.restart();
                  score = 0;
                  gameState=JEU;
                }
          }
      }

      if(gameState==JEU){
          Event event;
          while (window.pollEvent(event))
          {
              if ( (event.type == Event::Closed) ||
              ((event.type == Event::KeyPressed) && (event.key.code==Keyboard::Escape)) )
                {
                  window.close();
               }


                if((event.type == Event::KeyPressed) && (event.key.code==Keyboard::Space)){
                  time = clock.getElapsedTime();
                  if(time.asSeconds()>0.25){
                    clock.restart();
                    RectangleShape shoot;
                    shoot.setSize(Vector2f(50,2));
                    shoot.setFillColor(Color::Red);
                    shoot.setPosition(ship.getPosition().x,ship.getPosition().y+30);
                    laser.push_front (shoot);
                  }
              }
          }
          moveTime = moveClock.getElapsedTime();
          moveClock.restart();
          speed = moveTime.asSeconds();

          sprintf(scoreStr, "%d", score);
          scoreTxt.setString(scoreStr);
          window.draw(scoreTxt);

          if(Keyboard::isKeyPressed(Keyboard::Up) && ship.getPosition().y>0)
            {
                ship.move(0,-500*speed);
            }

            if(Keyboard::isKeyPressed(Keyboard::Down) && ship.getPosition().y<height-(shipSize*2))
            {
                  ship.move(0,500*speed);
            }

            if(Keyboard::isKeyPressed(Keyboard::Left) && ship.getPosition().x>shipSize*2)
            {
                ship.move(-500*speed,0);
            }

            if(Keyboard::isKeyPressed(Keyboard::Right) && ship.getPosition().x<width/4)
            {
                ship.move(500*speed,0);
            }

          blocTime = blocClock.getElapsedTime();
          if(blocTime.asSeconds()>1)
          {
            blocClock.restart();
            double y = fRand(0,height-50);
            printf("%f\n",y);
            RectangleShape b;
            b.setSize(Vector2f(40,40));
            b.setFillColor(Color::Green);
            b.setPosition(width,y);
            bloc.push_front (b);
          }


          window.draw(ship);
          for (list<RectangleShape>::iterator it=laser.begin(); it!=laser.end(); ++it)
          {
            window.draw(*it);
          }


          for (list<RectangleShape>::iterator it=laser.begin(); it!=laser.end(); ++it)
          {

            it->move(800*speed,0);
          }

          for (list<RectangleShape>::iterator itBloc=bloc.begin(); itBloc!=bloc.end(); ++itBloc)
          {
            window.draw(*itBloc);
          }


          for (list<RectangleShape>::iterator it=bloc.begin(); it!=bloc.end(); ++it)
          {
            it->move(-350*speed,0);
            if(it->getPosition().x<0 ){
               gameState=FIN;
            }
          }

        for (list<RectangleShape>::iterator it=laser.begin(); it!=laser.end(); ++it)
          {
             for (list<RectangleShape>::iterator itBloc=bloc.begin(); itBloc!=bloc.end(); ++itBloc)
            {
                if(intersects(*itBloc,*it))
                {
                  it = laser.erase(it);
                  itBloc = bloc.erase(itBloc); //Ligne du probleme
                  score++;
                }
            }
          }
        }

       if(gameState==FIN)
        {
          Event event;
          while (window.pollEvent(event))
          {
              if ( (event.type == Event::Closed) ||
              ((event.type == Event::KeyPressed) && (event.key.code==Keyboard::Escape)) )
                  window.close();

                if((event.type == Event::KeyPressed) && (event.key.code==Keyboard::Return))
                {
                  blocClock.restart();
                  gameState=INTRO;
                }
          }


          sprintf(scoreStr, "%d", score);
          fin.setString("GAME OVER\nSCORE : " + string(scoreStr));
          window.draw(fin);


        }

       window.display();
    }

    return EXIT_SUCCESS;
  }
 
 

PS : je sais que le code est très salle et que ce n'est surement pas les bonnes techniques, ce sont juste des essais :)

icone salut

  • Newbie
  • *
  • Messages: 9
    • Voir le profil
Re : Probleme intersection / list.erase
« Réponse #1 le: Mars 11, 2017, 09:23:55 am »
salut Kargan , j’aimerai bien t'aider mais pourrait tu simplifié ton code et rajouter des commentaires pour nous expliqué qui correspond à quoi ;) (car perso je suis un peu largué)

Laurent

  • Administrator
  • Hero Member
  • *****
  • Messages: 32498
    • Voir le profil
    • SFML's website
    • E-mail
Re : Probleme intersection / list.erase
« Réponse #2 le: Mars 11, 2017, 12:16:44 pm »
Ta boucle pour effacer des éléments est incorrecte. it = c.erase(it) fait avancer l'itérateur à l'élement suivant. Ensuite tu reboucles et tu fais it++ : ton itérateur a avancé de deux éléments en un seul tour de boucle, ce qui fait qu'il peut dépasser c.end(). Et là tu es dans le comportement indéterminé.

Une boucle d'erase typique doit être comme ça :
for (auto it = c.begin(); it != c.end(); )
{
    if (must_erase)
        it = c.erase(it);
    else
        it++;
}
Laurent Gomila - SFML developer