14
\$\begingroup\$

This is a design question... I'm sure this could be generalized more, but I'm having a hard time with it. I am wondering about design for game object interactions - here is my example (2D puzzle-platformer).

Say the player is trying to progress through a level. There are many lights that can be pointed in different directions. Here is an example of how these light objects might interact...

  • One light projects a platform that allows the player to cross a gap
  • One light decreases the friction coefficients of anything it touches, another increases it
  • One light nulls the effects of all lights, which would make the platform disappear while that light is on and null the friction modifiers
  • Etc...

What is the best way to approach this problem when using a component architecture? Components for each major object seem obvious, as well as a clean way to define their effects on the environment. A class to "resolve" interaction (seems like that could become a mess quickly)? Some usage of the decorator pattern to create combined objects for those that are interacting at a given time? A data structure that lends itself to this?

Also, connecting audio to these interactions? It seems like connecting audio to the system would be just like connecting any other property, like visibility or player movement/collision.

Obviously as more components are added it would be nice if there was a robust system that could handle new ones with little modification, but I am not familiar with how to go about designing this.

Other Information: The engine I am using is an XNA engine called IceCream.

\$\endgroup\$
4
  • \$\begingroup\$ possible duplicate of Component-Based System Information \$\endgroup\$
    – user744
    Sep 27, 2010 at 21:10
  • 2
    \$\begingroup\$ There is an actual question here, though, as opposed to the "question" at the link that Joe gives. \$\endgroup\$ Sep 27, 2010 at 22:12
  • 2
    \$\begingroup\$ don't see the dupe, the question is about how to design a specific game's requirements in code, using a component system (@Christopher: mentioning which one would help though, are you using Unity? Torque? Proprietary?) \$\endgroup\$
    – CodeSmile
    Sep 27, 2010 at 22:14
  • 2
    \$\begingroup\$ I like your gameplay idea by the way =) \$\endgroup\$
    – Nailer
    Sep 28, 2010 at 12:26

4 Answers 4

5
\$\begingroup\$

In an object oriented system, the only real answer to the question of what's the best way to do X is that you should just do it the most straight forward way you can think of to get something up and running, and then change it when an easier expression becomes apparent. Concerning yourself with choosing the right pattern before you've written any code is a good way to saddle yourself with the wrong answer from the get go; let all thoughts of patterns and components melt away and just follow these steps, starting from where you are today (assuming you have implemented a light component):

  1. Add code to the light component to project platforms. (Get this working.)
  2. Copy that component into a new component, remove the platform stuff and add code to decrease friction of appropriate objects. (Get this working, verify that #1 still works.)
  3. Copy that component into a new component, removing the "new" code and add stuff to disable the other components' effects. (Get this working, then verify that #1 and #2 still work.)

At this point, you will (probably) have a ton of duplicated code. Extract common code into functions or another class (maybe a base class) or whatever seems appropriate. Just because you started with a "light component" though doesn't mean that LightComponent is an appropriate base; it could be that whatever code made up the light component isn't really a "component" per se and maybe that will be best represented by a set of functions or even a separate class that is aggregated into your new components (as a member variable).

\$\endgroup\$
1
  • \$\begingroup\$ I'm marking this as the answer because it truly answers "How should I design...". Thanks for this, it definitely put me on the right path. \$\endgroup\$ Sep 30, 2010 at 15:20
2
\$\begingroup\$

In general terms, when an object of type A interacts with an object of type B, you want to have some effect C. This is called "double dispatch" and is very hard to do elegantly in C-like languages.

The effective but hard-to-maintain way is just a bunch of switch and if statements, depending on the types of your objects. You'll feel dirty writing it but it will get the job done.

The Visitor pattern is a more robust solution that hides the nasty type switching, but can be clumbersome to set up.

Normally any kind of type-switch in your code is a smell, but here you're trying to generalise polymorphism, which normally switches functions based on a single type, to switch functions based on two types. Polymorphism is a foundation of OOP so it's not a smell.

\$\endgroup\$
2
\$\begingroup\$

Let me see. This is just something I cooked up in my head while I was writing, so sorry if I'm missing something.

Get all light nodes in a reasonable distance around your dude.

For each light you render a polygon representing it's area of effect to a framebuffer object. So a cone of light would create a cone of one type of pixels in your FBO. Render each node type in passes in appropriate priority. You could encode information into each pixel like green channel could be fricition, red be gravity, blue and alpha be something else.

Clever color blending techniques could then create interesting effects. Each level could have it's own blending rules.You can also add fragment shading for psychedelic dynamic effects like pulsating gravity etc.

Lastly, just check which pixels your mandude is touching, and do recalculation of the bitmap whenever you are nearing the edges of the precalculated area.

Rough scetch made in 2 minutes kind of illustrating my idea:

Illustration

Edit: In practice this means the only thing you need is one light component emitting a certain color. The rules connected to what color does what can be somewhere else entirely. You can encode a lot of data into the 32 bits you have pr pixel. Alternatively you can have multiple FBO's containing different attributes that don't affect each other. You could have one gravity/friction FBO and one 1bit collision FBO. If you choose this, you would of course have to flag which FBO your light should render into.

\$\endgroup\$
2
  • \$\begingroup\$ Thank you for your input. I really appreciate the visuals, and this really got me thinking about how the mechanic could work behind the scenes. \$\endgroup\$ Sep 30, 2010 at 15:21
  • \$\begingroup\$ Heh, no prob. I know it didn't answer your exact question, but some problems require specialized solutions. Good luck! \$\endgroup\$
    – Nailer
    Oct 1, 2010 at 7:51
0
\$\begingroup\$

Observer pattern is one of the best solution. Message will be sent only to those objects (components) that are really interested in it. So reciever must subscribe on this message/event type.

There are many signal/slot implementations. For example, in C++ there is a sigslot library

For more information read about Qt signals and slots.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .