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

Author Topic: Error with multidimensional array  (Read 2766 times)

0 Members and 1 Guest are viewing this topic.

Dante12129

  • Newbie
  • *
  • Posts: 24
    • View Profile
Error with multidimensional array
« on: June 22, 2013, 04:28:39 am »
I am having trouble accessing a one-dimensional vector as a multi-dimensional one.
I have a MultiArray template class, and it is accessed using the function operator. It accesses elements through the expression row * m_columns + col. The row and col are the two inputs to the operator while the m_columns is the width/number of columns in the array. There is also a version that accesses the array with one number. Its underlying representation is a one-dimensional vector.

The problem is when I try to load a level:
void Map::LoadFromFile(const std::string& filename)
    {
        std::ifstream map_file(filename);

        std::cout << m_map.GetHeight() << ", " << m_map.GetWidth() << std::endl;
        std::cout <<  m_map_dimensions.y << ", " <<  m_map_dimensions.x << std::endl;
        if(map_file.is_open())
        {
            for(unsigned int i = 0; i < m_map_dimensions.y; i++)
            {
                for(unsigned int j = 0; j < m_map_dimensions.x; j++)
                {
                    int current_tile;
                    map_file >> current_tile;

                    try
                    {
                            m_map(i, j) = current_tile;
                    }
                    catch(std::exception& e)
                    {
                        std::cerr << "Vector overflow in map loading." << std::endl;
                        exit(EXIT_FAILURE);
                    }
                }
            }
        }
        else
            std::cerr << "Couldn't load map file: " << filename << "." << std::endl;
    }

(The m_map is a MultiArray<int> and the m_map_dimensions an sf::Vector2u)

The dimensions of the level are 20 * 15 (screen dimensions divided by height dimensions), so I made a map file that looks like this:
Quote
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00


but it loads it skewed and only ever accesses up to element 229 in the MultiArray.

This is how it loads the file:
Quote
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0
1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

The graphical output code is outputting this messed-up array in the graphical representation of this using a spritesheet, so I know it is working correctly.
« Last Edit: June 22, 2013, 04:31:56 am by Dante12129 »

Nexus

  • SFML Team
  • Hero Member
  • *****
  • Posts: 6287
  • Thor Developer
    • View Profile
    • Bromeon
Re: Error with multidimensional array
« Reply #1 on: June 22, 2013, 08:33:45 am »
Check the stream validity after the input operator, for example as follows:
int current_tile;
while (map_file >> current_tile)
{
    // compute indices, or directly store to 1D vector
}

Why doesn't your code load the dimensions of the map? Are they constant?

And does your MultiArray class work correctly? Is the input correct if you load it directly into a std::vector?
Zloxx II: action platformer
Thor Library: particle systems, animations, dot products, ...
SFML Game Development:

Dante12129

  • Newbie
  • *
  • Posts: 24
    • View Profile
Re: Error with multidimensional array
« Reply #2 on: June 22, 2013, 06:05:01 pm »
I tried changing my code to use a normal vector but is still giving me messed up output. This is my new code:

int current_tile, i = 0, j = 0;
            while(map_file >> current_tile)
            {
                try
                {
                    //m_map.at(i * m_map_dimensions.y + j) = current_tile;
                    m_map.push_back(current_tile);
                }
                catch(std::exception& e)
                {
                    std::cerr << "Vector overflow in map loading. Error: " << e.what() << std::endl;
                }

                if(j < m_map_dimensions.y)
                    j++;
                else
                {
                    j = 0;
                    if(i < m_map_dimensions.x)
                        i++;
                    else
                        i = 0;
                }
            }

I also did a comparison between my MultiArray and a normal vector and they both worked the same (with MultiArray's one and two parameter access operator).

Dante12129

  • Newbie
  • *
  • Posts: 24
    • View Profile
Re: Error with multidimensional array
« Reply #3 on: June 23, 2013, 02:19:33 am »
I've gone back to my original code as it gets me closest to what I intend to do, but I did add a check to see if the input operation succeeds. And by modifying my map file I discovered that it is loading the 16th-20th tiles as the first few tiles of the next line.
« Last Edit: June 23, 2013, 03:35:25 am by Dante12129 »

Dante12129

  • Newbie
  • *
  • Posts: 24
    • View Profile
Re: Error with multidimensional array
« Reply #4 on: June 23, 2013, 03:38:20 am »
I have now determined that it isn't my loading code that is messing up, but my drawing code. I used the debugger and saw that it was putting the correct numbers in the correct spot in the array. I also added some debugging output to the loops to confirm this. Now here's my drawing code:

void Map::draw(sf::RenderTarget& target, sf::RenderStates states) const
    {
        sf::Sprite current_sprite;
        static int once_flag = 0;

        if(!once_flag)
        {
            std::cout << m_map.GetHeight() << ", " << m_map.GetWidth() << std::endl;
            std::cout <<  m_map_dimensions.x << ", " <<  m_map_dimensions.y << std::endl;
            for(unsigned int i = 0; i < m_map_dimensions.y; i++)
            {
                for(unsigned int j = 0; j < m_map_dimensions.x; j++)
                {
                    std::cout << m_map(i, j) << " ";
                }
                std::cout << std::endl;
            }
            std::cout << std::endl;
            once_flag = 1;
        }

        for(unsigned int i = 0; i < m_map_dimensions.y; i++)
        {
            for(unsigned int j = 0; j < m_map_dimensions.x; j++)
            {
                try
                {
                    current_sprite.setTexture(m_spritesheet.GetTexture());
                    current_sprite.setTextureRect(m_spritesheet.GetRect(m_map(i, j)));

                    current_sprite.setPosition(j * m_tile_dimensions.x, i * m_tile_dimensions.y);

                    target.draw(current_sprite, states);
                }
                catch(std::exception& e)
                {
                    std::cerr << "Vector overflow in map drawing. Error: " << e.what() << std::endl;
                }
            }
        }
    }

As far as I can see, the loops are the same as the loading loop, but they both produce the same output, which is the skewed version of the map.

 

anything