# Painter-Class and Level-Structures

This topic is 686 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Hello dear forum : )

Using C++, but possible design patterns are probably not limited to the language, therefore no "C++"-tag,

I have a level-class with a vector of vectors (containing entity-game-objects) as structure for my level because the level is predictable; grid-based.

Each game-object owns a graphics-component, containing all required information by my rendered API.

Of course my level-class shall not be in charge to draw entities, therefore I would like to implement a painter-class.

However I'm not sure what would be the good-practice-way to tell my painter-class what to draw.

Additionally, there are also GUI-widgets that needs to be rendered. As they have no grid-based appearance, they just lie within a vector of widgets and show their coordinates.

Simple: Just pass a reference of the 2d-vector to the paint-class. This the easier route and should probably preferred over more complex code.

While this is sufficient for my needs, should a usual painter-class even have the necessity to know the level-format?

Alternative: Letting the painter-class have a vector of pointers to each graphics-component within an entity.

This removes one dependency of knowing the level-structure and leaves the dependency of knowing how the graphics-component works.

Removing the component-dependency: Implementing a wrapper-class containing texture-reference, coordinates and a link to the original graphics-component.

Of course, I would also require a second vector for GUI-widgets.

I thought about using a queue over a vector. But I'm not sure if the painter-class should dequeue/remove an item or if the level-(un)loader-class should trigger a flag to do this.

So thought I will save quite a few iterations if the painter-class does not need to remove elements once done.

Are there better ways to do this? How would you implement a painter-class?

Edited by Angelic Ice

##### Share on other sites
Wow! Thanks : ) I will give it a try!

I thought it might appropiate to simulate a level-grid.
Especially since collision of the mouse to grid-entities can be computed by coordinates. Which enables a vector[y][x]-access structure.
Would you recommend not to do this?
I thought it is quite convenient, maybe I should roll with a customised data structure or look for something prettier? Edited by Angelic Ice

##### Share on other sites
... 2d vector ... Especially since collision of the mouse to grid-entities can be computed by coordinates. Which enables a vector[y][x]-access structure. Would you recommend not to do this?

A 2D array is generally not best for this type of system.

In the rectangular array, the long single dimensional array is the same as an array of arrays is laid out sequentially.  One row, then another row, then another, each accessed individually. You can do this yourself with an array that is size width*height, and then access it either in row-major or column-major by accessing array[x+width*y] or array[y+height*x]. Once you decide the pattern you are storing your data you need to stick with it everywhere. In a classic 2D array that is exactly how array[y][x] worked out mathematically. The compiler would replace [y][x] with [x+width*y] behind your back.

In the container full of containers there is the potential for jagged arrays. That means the first item may be length 10, the second item may be length 45, the third may be length 3, the fourth may be length zero, etc. That takes more effort to work with.  Generally you should only use that if you intend to have a jagged array.

Personally I would pass around a data structure that handles a rectangular array.

uint_32 width; // number of pixels wide

uint_32 height; // number of pixels tall

uint_32 * data; // pixel data in RGBA format, row major starting in the upper left corner

}

Be aware that graphics work is generally best done on the GPU when possible. It is certainly possible to composite all the data on the CPU and work with all the items in main memory.  But if the only thing you are doing is displaying the result it is generally best to use the graphics drivers that will do the work on the video cards using hardware-accelerated methods.

Edited by frob
sorry, rectangular not square.

##### Share on other sites
Everything frob said.

A slightly more advanced concern with arrays-of-arrays is that the individual rows won't be allocated in memory together. One row might get allocated around address 0x1000 while the next might be around address 0x5500 and the third is near 0x1100. This makes copying the tile grid around much more expensive/complicated, makes accessing the tile data a little slower, etc.

The easiest setup for a tile grid is what frob described above, though I'd personally still use a vector or unique_ptr<[]> instead of a raw pointer. The fastest approach is to use a fixed "chunk" of tiles (say a 64x64 chunk) and then arrange those together in an octree or spatial hash. That is essential to supporting Really Large Worlds, and also just tends to be a faster way to structure tile data internally (e.g., that's closer to how your GPU stores textures in its memory, using zigzag layout for better cache usage).

That's all fairly advanced stuff to understand and not required for 99% of games, but it's the kind of stuff you should be aware of for when you start working on bigger projects. :)

##### Share on other sites

Thanks a lot! I will remove my vector of vectors. Just thought [y][x] would be a bit more "human-friendly", especially since I was not really worried about performance.

I was curious on what data structures you would use within the stage/scene/painter-class?

Since I have an edit mode that requires flexible editing (adding, removing and switching layers). At the moment, I did not include x- and y-coordinates in my game-objects, because I know the tile-grid-size and simply load them in order.

I considered these possible solutions: Just a normal vector that allocates max_width*max_height amount of empty slots that get populated - pretty much the same structure as in the level-wrapper-class.

Or start assigning x- and y-coordinates to every object.

The thing is, the renderer needs to know coordinates for GUI-widgets of course. But since I plan on putting them into another instance of a vector, it should be no problem to treat them differently.

What is common practice? Or is there even such? It probably depends quite a lot.

Every layer would have one vector or I consider something like a priority queue.

##### Share on other sites
Thanks a lot! I will remove my vector of vectors. Just thought [y][x] would be a bit more "human-friendly", especially since I was not really worried about performance.

Remember that you can always implement that functionality yourself:

struct TilemapData
{
uint_32 width; // number of pixels wide
uint_32 height; // number of pixels tall

uint_32 GetTile(uint_32 x, uint_32 y) const
{
return data[y * width + x];
}

uint_32 * data; // pixel data in RGBA format, row major starting in the upper left corner
}


Just a minor overhead, data.GetTile(x, y) vs data[x][y] (if even that, I consider [][] harder to type than (,)).

Edited by Juliean

1. 1
2. 2
3. 3
Rutin
22
4. 4
5. 5
khawk
14

• 9
• 11
• 11
• 23
• 12
• ### Forum Statistics

• Total Topics
633654
• Total Posts
3013168
×