Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411512 Posts in 69376 Topics- by 58430 Members - Latest Member: Jesse Webb

April 27, 2024, 12:35:41 AM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Relation between game objects<->sprites, "is a" or "has a"?
Pages: [1] 2
Print
Author Topic: Relation between game objects<->sprites, "is a" or "has a"?  (Read 4762 times)
HannesP
Level 0
***


View Profile WWW
« on: January 07, 2009, 05:58:08 PM »

As I've mentioned in other threads, I'm new to game programming (though not to programming in general) and I have encountered a design issue: a typical game contains a lot of "game object" (the player, bullets, enemies, bosses) etc and the screen is (hopefully) filled with graphical representations of them, but what is the relation between the two? Is a game object in fact a sprite with custom behaviour, or should the "logical" part of an object be treated as a separate object which has a sprite that it uses to draw its visual representation on the screen?

In Cocoa, which is the environment in which I have done most of my programming, subclassing is generally avoided in favor of delegation, composition etc., but since this is a game, I suppose the premises are a bit different.

Probably there's no "right" or "wrong" way to do it, since the important thing is whether it works or not, so I just want to hear your thoughts on it and how you usually design your games in this regard (from a pragmatic point of view; rants about design patterns and about what D. Knuth would have done don't help me much Wink).
Logged
Problem Machine
Level 8
***

It's Not a Disaster


View Profile WWW
« Reply #1 on: January 07, 2009, 06:04:39 PM »

I definitely wouldn't keep any bitmap data in your class, as that would make duplicate enemies remarkably inefficient.
Logged

HannesP
Level 0
***


View Profile WWW
« Reply #2 on: January 07, 2009, 06:08:27 PM »

That is not a problem -- the framework I plan to use distinguishes between images (which contain the data) and sprites (position, rotation, transparency etc.). Thanks for your answer though Smiley
Logged
aschearer
Level 1
*



View Profile WWW
« Reply #3 on: January 07, 2009, 06:42:25 PM »

It sounds like what you're really asking is what's the right way to implement MVC in your game. In my experience I've found that simply creating a single game object (such as a bullet) which handles both its behavior (read model) and its sprites (read view) is the most effective and sane way to do things.

I tend to have a top level interface such as "Animatable" which contains an update and render method and have each game object implement that. My game loop is then broken up into the more traditional MVC model. I find that I have three classes: a collection of game objects (read models) which fall under some common interface, a "view" class which gets passed a collection of Animatable's to render (and possibly some other things), and a "game loop" (read controller) which manages the model and view.

The benefits of this are that my view class can incorporate any special rendering logic without impacting the rest of the application, for instance calls to OpenGl. That said I delegate rendering the game objects to the objects themselves as it usually requires most or all of their state anyway.

I hope this helps answer your question and if you want some actual code as an example let me know.
Logged

My site: Spotted Zebra
Core Xii
Level 10
*****


the resident dissident


View Profile WWW
« Reply #4 on: January 07, 2009, 11:03:54 PM »

A sprite is just an image. An object has a sprite (or to be precise, a reference to one), which it draws onto the screen. (alternatively, depending on your rendering style, is drawn by something else)
Logged
Tiny
Level 0
**

TGD


View Profile WWW
« Reply #5 on: January 08, 2009, 01:50:01 AM »

I always use "has a" when it comes to entity <-> sprite relationship. I tend to have the base as an Entity object which everything else is derived from. In the Entity object I have the position/rotation/etc of the sprite and also a reference to the actual image data.

But like people say, it's really a personal design choice. If you can make it work without any unnecessary overhead, it really doesn't matter Smiley
Logged

Javilop
Level 2
**



View Profile
« Reply #6 on: January 08, 2009, 02:13:23 AM »

Quote
I always use "has a" when it comes to entity <-> sprite relationship. I tend to have the base as an Entity object which everything else is derived from. In the Entity object I have the position/rotation/etc of the sprite and also a reference to the actual image data.

Yep, that's what I like too. And I'm using it on... well you know Tongue


Logged
BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #7 on: January 08, 2009, 03:56:40 AM »

Nthing "has-a". Aside from good defense against future changes, I like having a seperate "namespace" for graphics methods and for game logic. I go into a bit more detail here, but it's not all relevant.
Logged
bateleur
Level 10
*****



View Profile
« Reply #8 on: January 08, 2009, 05:16:14 AM »

I too vote for "has a".

The usual test for drawing this distinction is to wonder whether it would make sense for the object to have more than one of the thing.

Could a game object have two sprites? Yes, indeed it could. To provide a nice simple example: a mutant in the classic arcade game Defender might appear both on the main screen and on the mini map.

Compare with "Knight is a Character". Would it make sense for the Knight to be more than one Character? No, not really.
Logged

J.G. Martins
Level 2
**


AKA anvilfolk


View Profile WWW
« Reply #9 on: January 08, 2009, 06:17:26 AM »

Yep, that's what I like too. And I'm using it on... well you know Tongue
:D

On a conceptual level, I do much prefer the has-a relationship, especially because of multi-sprite characters. Take Aquaria, legs and arms are clearly different sprites than the body.

However, and with the risk of going slightly off-topic:

Would there be any low-level considerations regarding this? If you have a has-a relationship, then you have two separate entities, possibly in totally different memory locations. If you have a is-a, then quite possibly, every data needed is bunched together. Is there any possibility that using an is-a relationship could decrease cache misses by any noticeable amount?

Obviously, even if this happened, it would only be when you'd have insane amounts of on-screen objects.
Logged

Gold is for the mistress -- silver for the maid --
Copper for the craftsman cunning at his trade.
"Good!" cried the Baron, sitting in his hall,
"But iron, cold iron, is the master of them all."
--- Rudyard Kipling
BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #10 on: January 08, 2009, 06:42:38 AM »

Is there any possibility that using an is-a relationship could decrease cache misses by any noticeable amount?
I'm not really qualified to speak on this, but I imagine you could theoretically get better cache response with has-a. As you could put all the game logic in one place, and image logic in another. But I'm only likely to want one list or the other for a given loop, so I can fit more of the things I want into the cache.

I.e. I mean
DoGameUpdate()
DrawGraphics()
might be faster.
Logged
Michelle Disraeli
Level 0
**


View Profile
« Reply #11 on: January 08, 2009, 08:24:33 AM »

A model-viewer-controller setup is probably the best way to go. It gets more complex initially, but allows greater freedom of editing in the end. Take a look at this for how one group of professionals implemented it. I felt it was too complex the first time I saw it, but the more I read, the more it made a lot of sense.

Other advantages of an MVC system include easier testing, and far easier porting to different platforms.

As for the containment/inheritance discussion on it's own, I found this a useful discussion on the subject. In general, look to use containment. An important thing to look out for is when something actually has a IS-NOT-A relationship, which was something I hadn't considered before reading that article.
Logged
bateleur
Level 10
*****



View Profile
« Reply #12 on: January 08, 2009, 09:52:51 AM »

As for the containment/inheritance discussion on it's own, I found this a useful discussion on the subject.

Good link, but it's worth noting that some of what the author says is debateable. For example:

"If a class relationship can be expressed in more than one way, use the weakest relationship that's practical."

Erm... no thanks! Two cases:

Case 1) If either class might change in the future I'll express their relationship using whatever software structure best models their conceptual relationship to minimise the possibility of some future change breaking my implementation.

Case 2) If neither class will change in the future I'll express their relationship using whatever software structure gives me the best tradeoff between implementation time and runtime resource use.

I realise Herb Sutter is a C++ genius second to none, but I suspect his priorities differ from mine (and, more importantly, for those of most OO beginners).
Logged

nihilocrat
Level 10
*****


Full of stars.


View Profile WWW
« Reply #13 on: January 08, 2009, 11:09:50 AM »

A model-viewer-controller setup is probably the best way to go.

The more I program, the more I realize that separation of concerns is probably one of the hallmarks of good code.

It is certainly tempting to want to centralize everything into a God Object or some big bad Manager class, but as your code gets more complicated and you want to do more things, you will realize that keeping all your parts separate is a huge boon.

As for the original topic, I usually choose the path of "has" (containment). As for worrying about loading the same image 20 times for 20 instances of the same enemy, I think it's best to code your resource manager to cleverly pass references/pointers to an already-loaded image when you ask it to load the same image 20 times.
Logged

Michelle Disraeli
Level 0
**


View Profile
« Reply #14 on: January 08, 2009, 02:37:32 PM »

Case 1) If either class might change in the future I'll express their relationship using whatever software structure best models their conceptual relationship to minimise the possibility of some future change breaking my implementation.
Three common practices mitigates this concern somewhat. Firstly, when working according to interface specifications (which you should), it is a good idea to define the scope of any class such that major changes to an interface should not be needed, and any internal changes should not be exposed to the outside world. Secondly, although this does not directly fix the problem, unit testing helps to quickly identify exactly where the fault lies, allowing even major revisions to be quickly done, checked, and corrected for. Finally, there is a very old adage that is hard to work to, but a very good idea - design for the present. It is easier to work in new features to a well-built product, than it is to try and both think of every possible usage and to keep the implementation solid.

If there are any problems, remember that the facade or proxy design patterns could be used to easily fix the problem whilst following good design practices.

Quote
Case 2) If neither class will change in the future I'll express their relationship using whatever software structure gives me the best tradeoff between implementation time and runtime resource use.
Of course, however remember that optimisation should be a last-stage process. Depending upon your compiler, however, there could well be little difference (remember that virtual function calls have greater overheads than non-virtual).
Logged
HannesP
Level 0
***


View Profile WWW
« Reply #15 on: January 08, 2009, 03:20:39 PM »

Thanks a lot for sharing your thoughts; it has been really helpful. I think I've come up with a working solution; I'll let you know how well it worked if it turns out to be a good method Wink
Logged
J.G. Martins
Level 2
**


AKA anvilfolk


View Profile WWW
« Reply #16 on: January 08, 2009, 03:37:10 PM »

Those were some awesome articles!

I especially enjoyed the article from Gamasutra. This general structuring of the program is precisely what I'd been missing on. I'd never thought much of MVC, even though it dogmatically seems like a correct principle. Seeing a more concrete example of a possible implementation really helped cement things Smiley

The low-level stuff is rather moot though. If you have sprites as separate objects from game objects, all you have to do is iterate the sprites. No need to access the game-objects at all.
Logged

Gold is for the mistress -- silver for the maid --
Copper for the craftsman cunning at his trade.
"Good!" cried the Baron, sitting in his hall,
"But iron, cold iron, is the master of them all."
--- Rudyard Kipling
Impossible
Level 3
***



View Profile
« Reply #17 on: January 09, 2009, 12:49:29 AM »

Definitely has-a.  I have seen is-a used for the game object sprite relationship in some games, its common in engines and frameworks where a "sprite" blurs the line between an image or animated image and a base game object.  For example, in pygame the "sprite" class not only handles rendering but also has a variety of collision and update methods.
Logged
Glaiel-Gamer
Guest
« Reply #18 on: January 09, 2009, 01:39:18 AM »

My current structure of what I'm working on is:

object IS A sprite HAS A animation HAS A texture

actually sprites have multiple animations and some other functions.
Logged
bateleur
Level 10
*****



View Profile
« Reply #19 on: January 09, 2009, 03:12:28 AM »

Of course, however remember that optimisation should be a last-stage process.

This is good advice. But actually, I'm increasingly finding that micro-optimisation is something I don't so much do last as never. Back when the Acorn Archimedes first came out I used to write most of my code in ARM assembler and would regularly gain perceptible performance improvements by optimising small numbers of instructions. Now I write mostly in heavyweight, high-level languages and its extremely rare that making an optimisation of this kind (as opposed to an algorithmic improvement) is even perceptible in terms of its impact.

Quote
Depending upon your compiler, however, there could well be little difference (remember that virtual function calls have greater overheads than non-virtual).

Indeed, but again computing has changed such that if I find myself caring about the difference, my biggest problem is that I'm making way too many function calls.

It's just a feature of the sort of code I work on, though. I daresay micro-optimisation is still relevant to people writing graphics engines and the like.
Logged

Pages: [1] 2
Print
Jump to:  

Theme orange-lt created by panic