Jump to content
  • Advertisement
Sign in to follow this  
PumpkinPieman

Loader class dependencies.

This topic is 4887 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

I've been thinking recently about the dependence of smaller objects on their loaders. For example my sprite animation class right now is self-dependant, it loads the animation file and is able to play it. The next evolution of this class will extend to animation instances, where I have an animation loader which stores an animation sequence and frames. The instance handles a specific sequence of frames all at different times relative to other instances. This is quickly how it works now.
cSprAniLoader loader;
loader.create(&graphics, "myspr.spr");
loader.action("idle");

DWORD timedif = 0;
timer.start();
while(1){
timedif = timer.timedifference();
loader.update(timediff);
loader.draw();
timer.present();
};

This is kind of how I want it to work.
cSprAniLoader loader;
cSprAni	sprani1;
cSprAni	sprani2;
loader.create(&graphics, "myspr.spr");

sprani1.create(&loader);
sprani2.create(&loader);

sprani1.action("idle");
sprani2.action("walk");

DWORD timedif = 0;
timer.start();
while(1){
timedif = timer.timedifference();
sprani1.update(timediff);
sprani2.update(timediff);
sprani1.draw();
sprani2.draw();
timer.present();
};


My question is, in cases where there are loaders how 'attached' should the object instances be to them? Should the instances be updating themselves, or should they be passed to the loader to get updated? If neither, is there a better or more efficient way of doing something like this? Thanks. :)

Share this post


Link to post
Share on other sites
Advertisement
Why do you need a separate class for the loaders? I just have a Load() member function and that works ok. Sometimes it's cleaner to implement it as a static factory method but I've never felt a need to use a separate class.

Share this post


Link to post
Share on other sites
Well, I'm not an expert, but the way I've been doing it is I have a seperate interface for loading read-only resources like images, sounds, and config files. Basically, when a Sprite object is created, it asks my Resource system for the appropriate images, which are specified in my config file. My Resource system takes care of all the loading and cacheing of data, and nothing else. My Sprite object does all the updating; if it needs a new image, it asks the Resource system for it.

Share this post


Link to post
Share on other sites
Let me make sure I understand you correctly. You are trying to separate the properties and graphics of sprites that are used across all sprite instances from the actual sprite instances themselves, so you can individually control the sprite instances without having multiple copies of the never-changing properties and graphics.

I use the term sprite base as the class that holds the never-changing properties and graphics that are used across multiple sprite instances. A sprite instance I call the unique unit in the game. So if you have 50 soldiers, all using the same graphics, you have 50 sprite instances but only one sprite base. The sprite base would contain the graphics, animation sequences, etc that all of the instances reference. The sprite instances would contain the position and current animation state of the unit soldier.

You are definitely on the right track by recognizing the difference. I see you have a loader which the sprites use to get their graphics from. Realize, however, that the loader does more than just load. It STORES the graphics and frees them when you are done. Loader sounds temporary, when, in fact, your Loader should be stored for the same duration of time as the sprite instances, if not longer.

Now when you go to program this all, one of your questions involved who should update what. If you think of a sprite base as an omnipresent access point for the sprite instances, and nothing else, it doesn't make much sense for the sprite base to do the updating. After all, the sprite base really should have no knowledge of the sprite instances. The instances are like little creatures that leech off of the base. All of the updating code, therefore, should be done in the instances.

Now, it's possible to take this concept even further. The original idea was to have a Loader which only loads the graphics once. However, it's possible that another part of the code will load the same graphics for another purpose, say the GUI. So you may also want to have a surface manager that keeps track of all the surfaces themselves and checks if multiple copies of the same surface are being loaded. The sprite bases would have ways to reference their graphics in the surface manager. Therefore, the sprite bases would be leeches to another set of resources.

Once you start coding it, it will all fall together nicely. Just don't stop thinking about ways to better your code.

Share this post


Link to post
Share on other sites
Alright, that's exactly what I was thinking. I just wasn't sure if the method I was using was an effective choice.

I have a resource class right now that has an inhertiable base class and is inhertied by the texture, sound and other resource classes. The SpriteAnimation class already utilizes this code to make sure that there is no duplicate textures when loading.

I have another class for static sprites, which I'm thinking of converting in to a multipurpose class for static and animated sprites.


class cSprite
{
protected:
cGraphics* graphics;
cTexture* texture;
RECT pSrcRect;
D3DXVECTOR2 m_view;
D3DXVECTOR2 m_scale;
D3DXVECTOR2 m_position;
D3DXVECTOR2 m_center;
float m_rotation;
D3DCOLOR m_colour;

public:
cSprite();
~cSprite();

bool Create(cGraphics* pGraphics, D3DXVECTOR2* pViewWindow );
void Free();

void Mask(long left, long top, long right, long bottom);
void Scale(float ScaleX, float ScaleY);
void Move(float PosX, float PosY);
void Center(float CenterX, float CenterY);
void CenterMask();
void Rotate(float radians);
void Colour(uint8 Red, uint8 Green, uint8 Blue, uint8 Alpha);

bool Texture(cTexture* pTexture);
bool Draw(float value = 0.0f);

float GetXScale();
float GetYScale();
float GetXPos();
float GetYPos();
float GetXCenter();
float GetYCenter();
float GetRotation();
DWORD GetColour();

};





I'll try it and see what I get.

Quote:
Original post by Kylotan
Why do you need a separate class for the loaders? I just have a Load() member function and that works ok. Sometimes it's cleaner to implement it as a static factory method but I've never felt a need to use a separate class.

The loader has all of the animation sequences and animation frames, the sprites will just have a pointer to the animation seqence so this way I can use the same sprite at different time intervals.

Share this post


Link to post
Share on other sites
I guess I just don't understand your terminology - the word 'Loader' to me implies a class that reads data from disk, creates a data structure from it, and then disappears.

If your loader class is just a sort of central store for all the frames for a given character, I'd probably structure the code very differently to make it look more like typical C++ paradigms:


cSprAniLoader loader(&graphics, "myspr.spr");
cSprAni sprani1 = loader.create("idle");
cSprAni sprani2 = loader.create("walk");

Share this post


Link to post
Share on other sites
One of the things that I don't want is having to update each of the sprite objects by their loaders, what if I had 300 loaders? I'd be better off having a pointer in the sprite object that points to the loader, that would eliminate a lot of problems.

Share this post


Link to post
Share on other sites
Quote:

One of the things that I don't want is having to update each of the sprite objects by their loaders, what if I had 300 loaders? I'd be better off having a pointer in the sprite object that points to the loader, that would eliminate a lot of problems.


Have a sprite 'manager'. When you load a sprite, you add it to the sprite manager and then you update the manager. The manager will then update each of the sprites it is managing. eg:


cSprAniLoader loader;
cSprManager manager;
cSprAni sprani1;
cSprAni sprani2;
loader.create(&graphics, "myspr.spr");

sprani1.create(&loader);
sprani2.create(&loader);

sprani1.action("idle");
sprani2.action("walk");

manager.addSprite(&sprani1);
manager.addSprite(&sprani2);

DWORD timedif = 0;
timer.start();
while(1)
{
timedif = timer.timedifference();
manager.update(timedif);
manager.draw();
timer.present();
};



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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!