Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: 2d tile system using 2d std::vectors.  (Read 3948 times)

0 Members and 1 Guest are viewing this topic.

natchos

  • Jr. Member
  • **
  • Posts: 97
    • View Profile
    • Email
2d tile system using 2d std::vectors.
« on: May 25, 2012, 11:35:56 am »
Hello everyone, I'm back and once again I need help from the wise persons on this forum. More specifically I need help with getting my 2d tiling system working.

I've been trying to use a 2d vector, but this stuff is fiendishly hard. I'm currently loading info from a txt file which i then put into a struct called Level which contains the type, length and height of the level. Then I try to put this info into a 2d vector, which I will then use to render.

Right now I'm am running into problem when resizing, and assigning values to the different elements of the vectors. The reason I am using a vector is that in the future I will most likely need to add more complicated backgrounds (as opposed to right now where I assume that every tile will use the same image).

Here is the code that I think is relevant.

Vector Dec
std::vector< std::vector <sf::Sprite> > BackGround(4, std::vector<sf::Sprite>(4,0));
std::vector< std::vector <sf::Sprite> >& BGPTR = BackGround;

Level LoadLevelFromTxt()
{
        int length,height,bg;
        std::ifstream FileStream("Levels.txt");
        if (FileStream.is_open())
        {
                if( FileStream.good())
                {
                        FileStream >> length;
                        FileStream >> height;
                        FileStream >> bg;
                }
                FileStream.close();
        }
        Level TheLocalLevel(length,height,(LevelType)bg);
        return TheLocalLevel;
}

void CreateBackground(Level& theLevel, std::vector<std::vector<sf::Sprite> >& BackgroundVector)
{
        BackgroundVector.resize(theLevel.Height);
        for (int i = 0; i < theLevel.Height; i++)
        {
                BackgroundVector[i].resize(theLevel.Length);
        }
        std::vector<std::vector<sf::Sprite> >::iterator iter;
        std::vector<std::vector<sf::Sprite> >::iterator itertwo;
        iter = BackgroundVector.begin();
        itertwo = BackgroundVector.at(0);
}

Currently I'm getting this error when compiling:
1>.\main.cpp(644) : error C2679: binary '=' : no operator found which takes a right-hand operand of type 'std::vector<_Ty>' (or there is no acceptable conversion)
1>        with
1>        [
1>            _Ty=sf::Sprite
1>        ]
1>        c:\Program Files\Microsoft Visual Studio 9.0\VC\include\vector(405): could be 'std::_Vector_iterator<_Ty,_Alloc> &std::_Vector_iterator<_Ty,_Alloc>::operator =(const std::_Vector_iterator<_Ty,_Alloc> &)'
1>        with
1>        [
1>            _Ty=std::vector<sf::Sprite>,
1>            _Alloc=std::allocator<std::vector<sf::Sprite>>
1>        ]
1>        while trying to match the argument list '(std::_Vector_iterator<_Ty,_Alloc>, std::vector<_Ty>)'
1>        with
1>        [
1>            _Ty=std::vector<sf::Sprite>,
1>            _Alloc=std::allocator<std::vector<sf::Sprite>>
1>        ]
1>        and
1>        [
1>            _Ty=sf::Sprite
1>        ]

If someone could help me, I would be extremly grateful!

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: 2d tile system using 2d std::vectors.
« Reply #1 on: May 25, 2012, 11:41:34 am »
From looking at the error messages I guess that line 644 of main.cpp is this one:
itertwo = BackgroundVector.at(0);

You assign a vector element (so a std::vector<sf::Sprite>) to an iterator. I don't know what you're trying to do because your code stops there.
Laurent Gomila - SFML developer

natchos

  • Jr. Member
  • **
  • Posts: 97
    • View Profile
    • Email
Re: 2d tile system using 2d std::vectors.
« Reply #2 on: May 25, 2012, 12:24:11 pm »
I removed the last line ^^ but then I get another error message namely:
1>c:\Program Files\Microsoft Visual Studio 9.0\VC\include\vector(528) : error C2440: 'type cast' : cannot convert from 'int' to 'sf::Sprite'
1>        No constructor could take the source type, or constructor overload resolution was ambiguous
1>        c:\Program Files\Microsoft Visual Studio 9.0\VC\include\vector(514) : see reference to function template instantiation 'void std::vector<_Ty>::_Construct<_Iter>(_Iter,_Iter,std::_Int_iterator_tag)' being compiled
1>        with
1>        [
1>            _Ty=sf::Sprite,
1>            _Iter=int
1>        ]
1>        .\main.cpp(107) : see reference to function template instantiation 'std::vector<_Ty>::vector<int>(_Iter,_Iter)' being compiled
1>        with
1>        [
1>            _Ty=sf::Sprite,
1>            _Iter=int
1>        ]


The function itself will be used to loop through a 2d vector of sf::sprites with the size [theLevel.length][theLevel.height]
Each sprite will have the image corresponding to the backgroundtype (which is an enum part of theLevel),
and a x,y position corresponding to it's position in [length] * sprite width and its position in y in [height] * sprite height.

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: 2d tile system using 2d std::vectors.
« Reply #3 on: May 25, 2012, 12:31:59 pm »
std::vector< std::vector <sf::Sprite> > BackGround(4, std::vector<sf::Sprite>(4,0));
0 is not a valid sf::Sprite instance.
Laurent Gomila - SFML developer

natchos

  • Jr. Member
  • **
  • Posts: 97
    • View Profile
    • Email
Re: 2d tile system using 2d std::vectors.
« Reply #4 on: May 25, 2012, 03:47:36 pm »
Huh yeah, that solved it. ^^ Now do you have any tips on how to iterate through the elements and set every sprite to the same image and/or modify the the position? I was thinking of a nested loop(similar to the init loop) would that work?

natchos

  • Jr. Member
  • **
  • Posts: 97
    • View Profile
    • Email
Re: 2d tile system using 2d std::vectors.
« Reply #5 on: June 01, 2012, 11:29:45 am »
Just replying to post my solution if someone else runs into this problem.

void rCreateBackground(Level& theLevel, std::vector<std::vector<sf::Sprite> >& BackgroundVector, sf::Image& bgtile)
{
        BackgroundVector.resize(theLevel.Height);
        for (int i = 0; i < theLevel.Height; i++)
        {
                BackgroundVector[i].resize(theLevel.Length);
        }
       
        for (int j = 0; j < theLevel.Height; j++)
        {
                for (int c = 0; c < theLevel.Length; c++)
                {
                        BackgroundVector[j][c].SetImage(bgtile);
                        BackgroundVector[j][c].SetPosition(c * bgtile.GetWidth(), j * bgtile.GetHeight());
                }
        }
}

Thank you Laurent, who takes the time to reply to my retarded questions :)

natchos

  • Jr. Member
  • **
  • Posts: 97
    • View Profile
    • Email
Re: 2d tile system using 2d std::vectors.
« Reply #6 on: June 07, 2012, 07:47:03 pm »
So I am back here, I am posting about an issue which is not the same, but is related to it.

The problem is that I am trying to read a .txt file of ints and bools to construct a level and tilemap from it. The place where I am running into problems is where I try to map a 16*48 grid of 0s and 1s to a tilemap of bools, meant to tell the engine what tiles should be collisible. Here is the function:

Level LoadLevelFromTxt(Level& LevRef)
{
        int length,height,bg;
        int stream = 1;
        bool maptrg = true;
        std::ifstream FileStream("Levels.txt");
        if (FileStream.is_open())
        {
                if( FileStream.good())
                {
                        FileStream >> length;
                        FileStream >> height;
                        FileStream >> bg;
                        LevRef.TileMap.resize(height);
                        for(int q = 0; q < height; q++)
                        {
                                LevRef.TileMap[q].resize(length);
                        }
                        for(int i = 0; i < height; i++)
                        {
                                for(int c = 0; c < length; c++)
                                {
                                        stream = FileStream.get();
                                        FileStream.ignore(2,' ');
                                        if(stream == 0)maptrg = false;
                                        else if(stream == 1)maptrg = true;
                                        LevRef.TileMap[i][c] = maptrg;
                                }
                        }
                }
                FileStream.close();
        }
        Level TheLocalLevel(length,height,(LevelType)bg);
        return TheLocalLevel;
}

Here is the Dec of the Level construct.

struct Level
{
        int Length;
        int Height;
        LevelType Background;
        LevelType AltBackground;
        std::vector< std::vector <bool> > TileMap;
        Level::Level(int nLength,int nHeight,LevelType nBackground)
        {
                Length = nLength;
                Height = nHeight;
                Background = nBackground;
                AltBackground;
        }
        Level::Level()
        {};
};

Here is the txt

48
16
0
1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

The issue I am running into is that the maptrg never changes. The TileMaps elements always evaluates to maptrgs initial state.

As usual, respond with tips or if there is a better way to do this, feel free to tell me all 'bout it!

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: 2d tile system using 2d std::vectors.
« Reply #7 on: June 07, 2012, 08:23:32 pm »
There's a difference between the character '1' and the number 1.

Your code would be cleaner, and the issue would be solved, if you used the >> operator to extract your numbers. It might even work directly with bool.

for(int i = 0; i < height; i++)
{
    for(int c = 0; c < length; c++)
    {
        FileStream >> LevRef.TileMap[i][c];
    }
}

Exercise: if you manipulate the file stream correctly, you can even remove the explicit width/height and deduce them from the number of rows and columns ;)
« Last Edit: June 07, 2012, 08:26:15 pm by Laurent »
Laurent Gomila - SFML developer

natchos

  • Jr. Member
  • **
  • Posts: 97
    • View Profile
    • Email
Re: 2d tile system using 2d std::vectors.
« Reply #8 on: June 07, 2012, 08:29:52 pm »
Yerr, nope. That won't work.

Got a goddamn long error message.

\main.cpp(624) : error C2679: binary '>>' : no operator found which takes a right-hand operand of type 'std::_Vb_reference<_Sizet,_Difft,_MycontTy>' (or there is no acceptable conversion)
1>        with
1>        [
1>            _Sizet=unsigned int,
1>            _Difft=__w64 int,
1>            _MycontTy=std::vector<bool,std::allocator<bool>>
1>        ]
1>        c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\istream(1144): could be 'std::basic_istream<_Elem,_Traits> &std::operator >><std::char_traits<char>>(std::basic_istream<_Elem,_Traits> &,signed char *)' [found using argument-dependent lookup]
1>        with
1>        [
1>            _Elem=char,
1>            _Traits=std::char_traits<char>
1>        ]
1>        c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\istream(1146): or       'std::basic_istream<_Elem,_Traits> &std::operator >><std::char_traits<char>>(std::basic_istream<_Elem,_Traits> &,signed char &)' [found using argument-dependent lookup]
1>        with
1>        [
1>            _Elem=char,
1>            _Traits=std::char_traits<char>
1>        ]
1>        c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\istream(1148): or       'std::basic_istream<_Elem,_Traits> &std::operator >><std::char_traits<char>>(std::basic_istream<_Elem,_Traits> &,unsigned char *)' [found using argument-dependent lookup]
1>        with
1>        [
1>            _Elem=char,
1>            _Traits=std::char_traits<char>
1>        ]
1>        c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\istream(1150): or       'std::basic_istream<_Elem,_Traits> &std::operator >><std::char_traits<char>>(std::basic_istream<_Elem,_Traits> &,unsigned char &)' [found using argument-dependent lookup]
1>        with
1>        [
1>            _Elem=char,
1>            _Traits=std::char_traits<char>
1>        ]
1>        c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\include\istream(155): or       'std::basic_istream<_Elem,_Traits> &std::basic_istream<_Elem,_Traits>::operator >>(std::basic_istream<_Elem,_Traits> &(__cdecl *)(std::basic_istream<_Elem,_Traits> &))'
1>        with
1>        [
1>            _Elem=char,
1>            _Traits=std::char_traits<char>
1>        ]
(it continues for about another page or two)

Anyhow, wouldn't I still ned the FileStream.ignore(2,' '); to make the function skip the spaces?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32504
    • View Profile
    • SFML's website
    • Email
Re: 2d tile system using 2d std::vectors.
« Reply #9 on: June 07, 2012, 08:32:46 pm »
Yeah, I said "it might work". Just use an int then.
int n;
FileStream >> n;
LevRef.TileMap[i][c] = (n != 0);

Quote
Anyhow, wouldn't I still ned the FileStream.ignore(2,' '); to make the function skip the spaces?
operator >> skips whitespaces.
Laurent Gomila - SFML developer

natchos

  • Jr. Member
  • **
  • Posts: 97
    • View Profile
    • Email
Re: 2d tile system using 2d std::vectors.
« Reply #10 on: June 07, 2012, 08:38:06 pm »
Huh, that worked. I wouldn't ever have though up something like that myself (I mean, I have used << before, just didn't know that it skipped whitespaces!)

Thanks alot Laurent!