Jump to content
  • Advertisement
Sign in to follow this  
Angelic Ice

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.

If you intended to correct an error in the post then please contact us.

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?

 

Thanks for taking your time to read through my thread : )!

Edited by Angelic Ice

Share this post


Link to post
Share on other sites
Advertisement
Wow! Thanks : ) I will give it a try!

About vector of vectors:
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 this post


Link to post
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.  

 

Perhaps I might start with this:

 

  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 this post


Link to post
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 this post


Link to post
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 this post


Link to post
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

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!