Finding and using data

Started by
11 comments, last by Captain P 14 years, 11 months ago
Hello, I have a recurring question that always seems to crop up when I'm working on a project. How do you go about accessing specific data that you need. Suppose I have a std::list<Sprite*> and I'm on the main menu and want to call NextFrame() on the play button when the mouse is over it. Now I could build up some sort of Id class that is used to access into this list, maybe even a handler class with a pointer to a specific sprite that is created from a string argument. What would be another way to do this? How do I take something generic and make it specific? Shouldn't I generally avoid doing it? And in cases like this, how? What is your solution?
Advertisement
Quote:Original post by livengood
How do you go about accessing specific data that you need.


This is a very general question.

Are you asking specifically about sprite animation, or...?

Apologies if I've misunderstood your post.
Let me go in a bit more depth.

All the sprites in this case are stored in a std::list, they have no notion of one another. I want to access my sprite "Play Button" and then call NextFrame() on this "Play Button" sprite. I can't simple call NextFrame() on any sprite. I need to call it on only the "Play Button" sprite. This sprite however has no notion that it's a play button, it remains generic, holding only it's texture ref and orientation data.

I was just asking in general, not specifically about sprite animation. This just happened to be the case at hand.

Hope this helps
look into using std::map
The problem here is that you're going too generic. That sprite is more than just a sprite - it's a button. Generalizing that away is not a smart idea. Why not write a Button class for it, that offers button-specific functionality, and that contains a Sprite internally for it's representation? Suddenly, it's much easier: a Button updates it's own Sprite whenever it changes state, and you just have to go and check a few buttons whenever you click somewhere, rather than running through every sprite.
Create-ivity - a game development blog Mouseover for more information.
Quote:Original post by Captain P
The problem here is that you're going too generic. That sprite is more than just a sprite - it's a button. Generalizing that away is not a smart idea. Why not write a Button class for it, that offers button-specific functionality, and that contains a Sprite internally for it's representation? Suddenly, it's much easier: a Button updates it's own Sprite whenever it changes state, and you just have to go and check a few buttons whenever you click somewhere, rather than running through every sprite.


This makes sense. What construct would then hold the buttons? My main menu in this case has say 6 buttons and each subsequent menu after that has 5 more buttons. I suppose this would be a reasonable place to employ an std::map. I understand what you mean by too generic. This is a 3d game so the large majority of sprites are in fact buttons, I suppose that's why I didn't make the distinction myself.

So to extend on this, in the situation I mentioned in my previous post, the sprites had a relationship as follows: Each Sprite was stored in a SpriteBatch, these batches consisted of sprites that should generally be grouped together, a common case would be the main menu sprite batch (which I could load in from xml), the SpriteBatch(s) were further stored in a SpritePool which is essentially a central update area for all Sprites in the game. In the case you describe this model would be represented more specifically. The 'Menu' would hold a container of 'UIElement' and each 'UIElement' would hold a sprite representation? How would I go about grouping and updating these menus? Would I gather all the menus into a vector for updating? Would I do it one at a time? Maybe make a small UI interface in the engine that can have menus added to it? Hmm, that brings up another question, how do I get this to the renderer. Before I could supply the renderer with a spritepool and it would go through rendering each sprite, in this case each sprite is individual. Do you then add a RenderQueue where each sprite is inserted everyframe? or make the sprite render itself then adding render specific code to each sprite...

Your post was excellent and I appreciate it. It's one of those things that you don't think about until someone else mentions it. I think it has become a syndrome of mine, generalizing like this, thanks.

[Edited by - livengood on May 1, 2009 6:32:23 PM]
Quote:Original post by livengood
The 'Menu' would hold a container of 'UIElement' and each 'UIElement' would hold a sprite representation?


That sounds like a good plan. You could even subclass UIElement and write LabelElement, ButtonElement, etc classes, with different behaviours.
Quote:Original post by beebs1
Quote:Original post by livengood
The 'Menu' would hold a container of 'UIElement' and each 'UIElement' would hold a sprite representation?


That sounds like a good plan. You could even subclass UIElement and write LabelElement, ButtonElement, etc classes, with different behaviours.



Yeah, this makes sense. Looks like I'm adding a GUI to the game. What do you think of the other questions I asked(sorry, edited them in without realizing how quickly you'd respond)
Ok.

Off the top of my head, something like this seems reasonable...

You could use a base GUI element, which defines methods for all the 'events' you're going to need. They're probably all going to be empty, but this gives you a common interface to use later on. Each element would likely also keep track of it's position, and maybe it's dimensions. For example:

class GUIElement{protected:   float x, y;    // Screen-space position.public:   virtual void setText(const std::wstring &text) {}   virtual void setSprite(const Sprite *sprite) {}   virtual void onClick() {}   virtual void onDraw() {}   // Any other actions you need...};


You can then subclass this, to create specific elements with different behaviours - maybe labels, buttons, or whatever you're game needs.

class GUIButton : public GUIElement{private:   Sprite *sprite;public:   void onClick()   {      // Button clicked...   }   void onDraw()   {      // However you draw you're sprite.   }};


To wrap it up, you could use a Menu class which owns a list/map of GUI elements. If you're loading menu layouts from file, for example, you could create and store each element in a map along with some ID. This might look like the following.

class Menu{private:   std::map<int, GUIElement*> elements;public:   // Reads the file and creates the specific elements.   Menu(const std::wstring &filename);   // Draws the menu...   void draw()   {      // Iterate over the std::map and call onDraw() on each element.   }   // Processes a mouse click...   void onClick(float x, float y)   {      // Iterate over the std::map and check if the click-coordinates hit      // any element. If so, call onClick()   }};


Is that any help?
Well yeah, that is about how I plan to do it, aside from changing the name of 'menu' to be more general and adding a SuperClass above all that for the whole jazz. I'm not sure how I can gather up the different sprites for rendering though, as they are all spread out amongst different classes. I mentioned that I could possible queue them up as an operation and then feed that into the rendering. How else would I go about getting all these sprites to render (I don't really want to have render specific code in each sprite)

This topic is closed to new replies.

Advertisement