SFML community forums

Help => General => Topic started by: xx_Dan_xx on January 20, 2015, 05:28:28 pm

Title: Storing the array of RectangleShapes in an array
Post by: xx_Dan_xx on January 20, 2015, 05:28:28 pm
Hi, I started learning C++ in September and I am beginning to get to grips with SFML.

I have created four arrays of RectangleShapes as so:

RectangleShape Player1Board[10][10];
RectangleShape Player2Board[10][10];
RectangleShape Player3Board[10][10];
RectangleShape Player4Board[10][10];

I want to store these arrays in another array but I am not sure how to do that without referring to a particular element in one of the arrays.

Basically here is the non-code version of what I want;

Array Boards[4] = {Player1Board, Player2Board, Player3Board, Player4Board}

I want to do this so in another function I can manipulate one of the boards by passing one integer rather than all four boards and then determining which one I want to mess with.



Title: Re: Storing the array of RectangleShapes in an array
Post by: Hapax on January 20, 2015, 06:09:12 pm
That is 400 RectangleShapes and, because you are using an array, they're all stored on the stack, which is limited. You are risking overloading the stack and therefore causing a crash. You could (should) rewrite it to use an STL container; the standard choice of vector should work perfectly for you here. This uses the heap (or "free store") and is only limited really limited by the amount of RAM. Vectors can also be resized during runtime.

First, you need to #include <vector>
Then, you can create them as two-dimensional and initialised with your sizes like this:
std::vector<std::vector<sf::RectangleShape>> Player1Board(10, std::vector<sf::RectangleShape>(10));
std::vector<std::vector<sf::RectangleShape>> Player2Board(10, std::vector<sf::RectangleShape>(10));
std::vector<std::vector<sf::RectangleShape>> Player3Board(10, std::vector<sf::RectangleShape>(10));
std::vector<std::vector<sf::RectangleShape>> Player4Board(10, std::vector<sf::RectangleShape>(10));
You can access the elements in the same way as an array (e.g. Player1Board[2][4])
Then, you can create a vector of those boards like this:
std::vector<std::vector<std::vector<sf::RectangleShape>>> Boards;
Boards.push_back(Player1Board);
Boards.push_back(Player2Board);
Boards.push_back(Player3Board);
Boards.push_back(Player4Board);
Then, the original vectors Player1Board, Player2Board etc. are no longer needed and can be discarded.
Then, to access them, you would need three values. e.g. Boards[0][2][4] would access the same element as Player1Board[2][4] would have done.

That said, it's a lot of rectangle shapes to be drawn individually. It would be much better to use a vertex array (http://www.sfml-dev.org/tutorials/2.2/graphics-vertex-array.php). You will also find the part about Tile Map (http://www.sfml-dev.org/tutorials/2.2/graphics-vertex-array.php#example-tile-map) useful here.

Also, You may want to consider not using nested - or multi-dimensional - vectors (or arrays) as using a single dimensional one can be more appropriate.
Title: Re: Storing the array of RectangleShapes in an array
Post by: xx_Dan_xx on January 20, 2015, 11:30:03 pm
Hapax, thanks so much for you reply. It helped a great deal and performed exactly for my needs.

In regards to the amount of rectangles to be drawn, they are very basic and small and, as of right now, they are drawn instantly and see no block ahead. But I'll look into those links.

As for not using multi-dimensional arrays or vectors, I believe its necessary as they form a squared tiled board and as far as I am aware, it requires less lines of code to then drawn each board from a multi-d array than working out the single indexes belonging to each board.

Title: Re: Storing the array of RectangleShapes in an array
Post by: Hapax on January 21, 2015, 12:35:08 am
It's not the size of the rectangle that will cause the problem but the number of them. Each window.draw() is a separate draw call to OpenGL. A vertex array can display many shapes (rectangles, triangles, lines, points) all using one draw call.
A similar situation appeared on the forum very recently and I mentioned the same information. I also posted a piece of code (http://en.sfml-dev.org/forums/index.php?topic=17300.msg124472#msg124472) that displays lots of rectangle shapes (480 thousand!). If you run the code, you'll see that the window becomes a little sluggish. It still works but the window takes a second to respond to the mouse. If that code used a vertex array similar to the Tile Map example that I linked to earlier, it could do it in a single draw call and still be fully responsive. It's something you will want to investigate. Getting to grips with vertex arrays was probably my most freeing SFML moment.

One-dimensional arrays can easily store two-dimensional information. Row by row, column by column.
Instead of [4][3], you would simply just use a size of 12. They would probably lay out like this:

 0  1  2  3
 4  5  6  7
 8  9 10 11

and you would access the elements like this:
[y * sizeX + x % sizeX]

e.g. if you wanted [2][1], you can see from the layout above, it should be element number 6.
therefore:
x = 2, y = 1, sizeX = 4 (width of layout)
[1 * 4 + 2 % 4]
= [4 + 2]
= [6]

The other way around, if you knew it was element 6 but wanted to know the x and y position of it, it would be:
x = e % sizeX;
y = e / sizeX;

where e is the element number.