Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] [SFML 2.0] Range_error

Ostatnio zmodyfikowano 2013-07-10 22:16
Autor Wiadomość
kubawal
Temat założony przez niniejszego użytkownika
[C++] [SFML 2.0] Range_error
» 2013-07-10 21:34:27
Witam!

Mam grę, i w niej co jakiś czas losowo pojawiają się i znikają obiekty. Lecz nie w tym sprawa.
Do manipulacji nimi wykorzystuję pętle for (obiekty są w vectorze).
I po jakimś czasie program wywołuje wyjątek Range_error przy indeksie 0. Wnioskuję z tego, że program próbuje przejść po vectorze, który jest pusty
Oto fragmenty kodu odpowiedzialne za obiekty:
Objects.h:
C/C++
struct Object
{
    Sprite sp;
    Vector2f pos;
   
    Object( string filename, Vector2f p );
   
    void Do();
    void Draw( RenderWindow & win );
   
private:
    Texture tex;
};

//...

struct Map
{
    vector < Object > objs;
    //...
   
    void Draw( RenderWindow & win );
    void Objects();
   
    //...
};

Objects.cpp:
C/C++
// funkcje pomocnicze
const int ObjectsFilesCount = 1;

string ObjectsFileNames[ ObjectsFilesCount ] =
{
    "C:\\grafika\\samolocik\\obiekty\\kulka.png"
};

//////////////////////////////////////////////////////////////////

inline string RandObjectFileName()
{
    //return ObjectsFileNames[randint(1, ObjectsFilesCount) - 1]; // na razie jest tylko jeden obiekt, więc żeby uniknąć dzielenia przez 0:
    return ObjectsFileNames[ 0 ];
}

inline Vector2f RandObjectPos()
{
    int ub = 0 + UP_BOUND;
    int db = H - DOWN_BOUND;
   
    return Vector2f( - 10, randint( ub + 1, db + 1 ) - 1 ); // żeby uniknąć dzielenia przez 0
}

//...

// daję całą imp. klasy Object:
Object::Object( string filename, Vector2f p )
{
    tex.loadFromFile( filename );
    sp.setTexture( tex, true );
   
    pos = p;
    sp.setPosition( pos );
}

void Object::Do()
{
    sp.setPosition( pos );
}

void Object::Draw( RenderWindow & win )
{
    win.draw( sp );
}

//...

// tutaj funkcje klasy Map manipulujące obiektami
void Map::Objects()
{
    if( objs.size() < MAX_OBJS && randint( 0, 100 ) == 0 )
         objs.push_back( Object( RandObjectFileName(), RandObjectPos() ) );
   
    for( int i = 0; i < objs.size(); i++ )
    {
        if( objs[ i ].pos.x > w )
             objs.erase( objs.begin() + i );
       
        objs[ i ].pos.x += speed;
        objs[ i ].Do();
    }
}

void Map::Draw( RenderWindow & win )
{
    //...
   
    // narysuj obiekty
    for( int i = 0; i < objs.size(); i++ )
         objs[ i ].Draw( win );
   
}

Tutaj implementacja randint(). Korzystam także z ulepszonego, strostroup'owskiego wektora, także podam:
C/C++
// tu jest klasa wyrzucanego wyjatku
struct Range_error
    : out_of_range
{ // enhanced vector range error reporting
    int index;
    Range_error( int i )
        : out_of_range( "Range error: " + to_string( i ) )
        , index( i )
    { }
};

//...

// tu jest ulepszony wektor
template < class T > struct Vector
    : public std::vector < T >
{
    typedef typename std::vector < T >::size_type size_type;
   
    Vector() { }
    explicit Vector( size_type n )
        : std::vector < T >( n )
    { }
    Vector( size_type n, const T & v )
        : std::vector < T >( n, v )
    { }
    template < class I >
    Vector( I first, I last )
        : std::vector < T >( first, last )
    { }
   
    T & operator []( unsigned int i ) // rather than return at(i);
    {
        if( i < 0 || this->size() <= i ) throw Range_error( i );
       
        return std::vector < T >::operator []( i );
    }
    const T & operator []( unsigned int i ) const
    {
        if( i < 0 || this->size() <= i ) throw Range_error( i );
       
        return std::vector < T >::operator []( i );
    }
};

// disgusting macro hack to get a range checked vector:
#define vector Vector

//...

// a tu randint()
inline int randint( int max ) { return rand() % max; }

inline int randint( int min, int max ) { return randint( max - min ) + min; }

No, myślę że podałem wszystko. Sprawdzałem wszystkie for'y ale są w porządku. Może Wy czegoś się tu dopatrzycie :)

/edit:
Jak by był zły dział, to proszę Adminów, żeby przenieśli, bo w sumie to nie jest ściśle związane z grami 2D, ale... :)


P-87436
pekfos
» 2013-07-10 21:39:19
Po co ten Vector? Nie prościej użyć metody at(), zamiast operatora [], z std::vector, która sprawdza poprawność indeksu (a jeśli jest niepoprawny, wyrzuca std::out_of_range)?
P-87439
kubawal
Temat założony przez niniejszego użytkownika
» 2013-07-10 21:41:47
Po co używać at() jak już miałem go gotowego, lepszego vectora, ze sprawdzaniem zakresu (miałem go z książki stroustrupa) ?
P-87440
Monika90
» 2013-07-10 21:43:29
C/C++
for( int i = 0; i < objs.size(); i++ )
{
    if( objs[ i ].pos.x > w )
         objs.erase( objs.begin() + i ); //a co jesli to ostatni obiekt w wektorze?
   
    objs[ i ].pos.x += speed; //to i jest poza zakresem
    objs[ i ].Do();
}
P-87441
kubawal
Temat założony przez niniejszego użytkownika
» 2013-07-10 21:46:34
//a co jesli to ostatni obiekt w wektorze?
No co?
P-87444
pekfos
» 2013-07-10 21:50:40
No co?
..to następna linia wyrzuci wyjątek, bo nie będzie elementu o indeksie i?

Po co używać at() jak już miałem go gotowego, lepszego vectora, ze sprawdzaniem zakresu (miałem go z książki stroustrupa) ?
Zabawne. Po czym wnosisz, że jest lepszy?
P-87448
kubawal
Temat założony przez niniejszego użytkownika
» 2013-07-10 22:16:19
..to następna linia wyrzuci wyjątek, bo nie będzie elementu o indeksie i
No o tym to nie pomyślałem... Thx :)

Zabawne. Po czym wnosisz, że jest lepszy?
Choćby po tym, że piszesz o 2 znaki mniej :D
P-87455
« 1 »
  Strona 1 z 1