Advertisement

Component based GameObject sprite sheet loading and render

Started by December 27, 2016 10:10 AM
1 comment, last by CrazyCdn 8 years ago

Hi All,

I am getting to grips with component based game objects (heavily using the example from game programming gems GPG 6), but run into implementation problems. I am using the DirectX toolkit for graphics rendering, and modifying the sample to prototype my design.

Right now, I am just trying to get one 'sprite' on screen, first I need to load the texture the sprite will use. Using the directX toolkit this is done by calling CreateDDSTextureFromFile(device, L"windowslogo.dds", nullptr, m_texture.ReleaseAndGetAddressOf()).

Where is the correct place to load the sprite sheet? Is it loaded inside a component? Or is the whole sprite sheet loaded at once (in say Game::init(), and components use the bits they need?

Then, when it comes to rendering, GPG 6 doesn't actually provide implementation details of virtual void render(); (inside the visual Component). DirectX TK draws with m_sprites->Draw(m_texture.Get(), XMFLOAT2(10, 75), nullptr, Colors::White); So again, I am a bit stuck. To draw like this, I need the std::unique_ptr<DirectX::SpriteBatch> m_sprites; Does this belong in a components private member?

This would mean my visual Component would look as follows:

class gocVisualCircle : public gocVisual
{
public:
virtual const goc_id_type& componentID() const {
return goc_id_type("gocVisualCircle");
}

virtual void render() const {
m_sprites->Draw(m_texture.Get(), XMFLOAT2(10, 75), nullptr, Colors::White);
};

gocVisualCircle(Microsoft::WRL::ComPtr<ID3D11ShaderResourceView> m_texture) {
CreateDDSTextureFromFile(device, L"windowslogo.dds", nullptr, m_texture.ReleaseAndGetAddressOf());
};

private:
std::unique_ptr<DirectX::SpriteBatch> m_sprites;
};

Am I on the right track? I am worried that this is too closely coupled to the directX toolkit objects.

Thanks for your time and help.

While not knowing how the DirectX TK works …; from a principle point of view: Separate different tasks into different objects! Well, from your question it seems me that your experience is low (no offending), and hence a full blown solution may be too heavy. So feel free to simplify the one or other aspect … but you should at least wrap your head around the principles, because almost all solutions suggested here in the forums are of that complex kind (due to a reason, of course).

a) The sprite sheet is a resource. It may contain clips of several sprites and/or clips of several motions, so it is often shared. To have a clearly defined responsibility for the lifetime of a (shared) resource, it is usually managed by some interrelated objects. Interrelated objects for a specific task are often called a sub-system. Here we can speak of the resource management sub-system. Its front object, i.e. the one that is "seen" from the others, provides an interface to get a named resource. If that happens, then a cache (a simple map, for example) is requested whether it already contains the resource. If not, then a loader is requested to load the resource from a file, and the result is both stored in the cache and returned to the calling object outside.

So: The component should not load the sprite sheet. It should request the resource management sub-system to return access to a sheet with a name that is known to the sprite component.

b) What exactly is rendered for the sprite? Exactly one image clip. Next frame it may be the same clip or another clip. So the visual component is just a specification which one image clip is currently active, i.e. it is like a variable that stores a reference to the sprite sheet and the clip co-ordinates. This "variable" can be set by e.g. the animation sub-system, so the look of the sprite will change over time. However, when it is time to render the sprite, the rendering just takes the relevant data from the visual component and pushes that (perhaps after some preparation) to the render batch. Which is the correct batch? The sprite does not know, because the render sub-system is out of its scope (again: separate the tasks).

So: The component should not have a member to the batch. At most, if it really has a render() method, the batch should be passed as argument to it. (However: In my understanding, the visual component would provide all necessary data but does not render by itself.)

c) Regarding the coupling to DirectX TK: It depends on the goal. If the goal is getting something done, and the result and any "derived work" is restricted to an area where the TK is available, then its IMO okay. After been done, the next trial can then be a bit more abstract, if you wish.

Advertisement

If my game object has a mesh (invisible traps do not, let's say) then it is registered with the render system. Loading material(s) is done by the material system which the render system calls into when needed. When the logic is done running (I'm always one frame behind logic) it passes all the transformed and visible objects to the render system to deal with. It passes ID's of any entities visible and the render system goes through those ID's looking for mesh's to display. Hope that makes sense. But the render system should have no knowledge of how to load a texture in my opinion. Leave that for textures/materials.

"Those who would give up essential liberty to purchase a little temporary safety deserve neither liberty nor safety." --Benjamin Franklin

This topic is closed to new replies.

Advertisement