An Idea for a DI & Signals, Component Based Game Engine built on RL..

31 views
Skip to first unread message

Michael Cann

unread,
Feb 24, 2010, 3:18:31 PM2/24/10
to robo...@googlegroups.com
Hi Guys, 

I have been speaking with fellow-brit, Stray for the last couple of days on an idea for a project I had. He seemed to like it and thought I should post it here and get a wider feedback on it before I go any furthur. So here goes:

Well a little background on me first. I have been developing in flash since flash 5 (have a book on AS1.0 ugghh!) so I have a pretty good understanding of flash. I also am heavily into games development having done a degree in games programming, worked in many games companies and developed a load of my own flash games (see http://www.artificialgames.co.uk/). I am currently working at a company called Playdemic where I am the lead client-side developer. We are developing games for Facebook (think Farmville / Cafe World that sort of thing).

I dont know how much you guys know about game engines but it used to be that you would design your games using a heirachical inheritance based structure. This leads to some problems however due to the fact that some branches of your inheritance tree may require functionality of another branch etc. For this reason there has been a generally accepted movement towards composition in the form of a component like game architecture.  

We are currently using Push Button Engine (quick vid at: http://www.youtube.com/watch?v=auaqZzcjl-Y) with Mate at Playdemic however there are some serious problems with it, and so I have been considering scrapping using it for our next project and rolling my own component based game engine / framework. 

I have been very impressed with the Dependency Injection and  Signals techniques used in robotlegs and wondered how I could take advantage of these new developments to develop a better more advanced component based game engine. 

The first thing I did was to check to see if anyone else has had the idea of using DI in a component based game engine. It looks like it hasnt been done in AS3 but it looks like it has already been thought about and documented in Java. There has been a paper written about it here: http://portal.acm.org/citation.cfm?id=1658866.1658872, I managed to get my greasy mitts on it and have uploaded it here: https://dl-web.dropbox.com/get/Documents/Techincal/a53-passos.pdf?w=34b1e265

Basically the idea is that entites are composed of components, and components are modular encapsulated bits of functionality. Components can however have dependencies between them. So for example if you have a "Renderer" component it will have a dependency on a "Spatial" component, so that it knows where on screen to draw a sprite. 

The usual method of handling these dependencies is for one component to ask its owning entity to lookup at the other components to see if there is one that matches the name "Spatial" and then to return it. My idea (and also documented in the paper) was that you could inject these dependencies into the component upon creation of the entity and hence avoid the call to the owner for a reference.

I have sketched out a couple of diagrams to exmplain more what I mean here:  https://cacoo.com/diagrams/e3TuwV6Yq6sz0z19

The idea is that it could tie quite nicely into Robot Legs framework. Robot legs provides the MVCS part whereas the "Game Engine" part contains alot of the hard, performance-heavy game engine bits.

So basically I was wondering if anyone on this list has any experience with game engines or specifically component based game engines or even more specifically Push Buttone Engine who feels simmilarly and would like to work on something like this with me? 

If not I would be extremely grateful for any feedback you guys have on the idea!

--
Mike Cann
http://www.mikecann.co.uk/
http://www.artificialgames.co.uk/

Stray

unread,
Feb 24, 2010, 3:57:42 PM2/24/10
to robo...@googlegroups.com
Stray is a she, but I'll forgive you for not intuiting that I'm a (remarkably tiny) girl. [Joel can fit 3 of me in his back pocket... which is the best reason I can think of to do a 2 hander one day.]

Re the parent / sibling injection stuff we discussed the other day, Till has confirmed that the injector itself doesn't directly support it (and shouldn't), but I think there's a good solution in the form of a wrapper class that basically decorates the injector with a composite injector manager to handle the family relationships you described.

--
You received this message because you are subscribed to the Google
Groups "Robotlegs" group.
To post to this group, send email to robo...@googlegroups.com
To unsubscribe from this group, send email to
robotlegs+...@googlegroups.com
for support visit http://knowledge.robotlegs.org

Jos Yule

unread,
Feb 24, 2010, 4:33:21 PM2/24/10
to robo...@googlegroups.com
I've used the Push Button Engine a bit, and while i like the idea of it, i've been hard pressed to "feel" it. I know its a bit of a soft reaction, but with RobotLegs, and even Flixel, i was able to understand, to a greater degree what what going on, or how the thing worked.

I'd be interested in chatting about the potential a game engine based on RL could have. It would be interesting to see how one could split out the non-rendering/high-performance bits... This is the reason you don't see too many OOP based game engines. Trying to get them to perform at reasonable frame rates is... challenging.

But using RL/DI for the wiring bits of a component based engine is intriguing. I'd be interested in talking/thinking/brainstorming about it more...

j

Michael Cann

unread,
Feb 24, 2010, 4:35:43 PM2/24/10
to robo...@googlegroups.com
Eeep! Im so sorry! You did tell me your actual name and I still didnt twig *sigh* :P

Ye, ill check that discussion, sounds like a composite injection is exactly what I need. So in that way, the entity becomes its own mini context, so that the components inside the entity can only be injected into the other components within the context of that entity.

On the second diagram I linked I have shown two entities "Player" and "Enemy" inside these entities there are several component variables. I have decorated these with the [Component] meta data. Im not sure if this is even possible, but the reason I did this is that I want strictly typed entity types that have components accessible via the standard dot notation. The reason for this is that in Push Button Engine the way to access components is via something like:

var e : IEntity = PBE.lookupEntity("Player");
var s : SpatialComponent = e.lookupComponentByName("Spatial") as SpatialComponent;
panCameraToPlayer(s.position);

Which involves casts and string lookups and generally feels nasty to me, what I would like is something like:

var p : Player = gameModel.player;
var s : SpatialComponent = p.spatial;
panCameraToPlayer(s.position);

That way everything is strictly typed. 

So what the [Component] tag indicates is that when an entity is created each of those components will be instantsiated and then be injected into any components of that entity that are dependant on it and have the [Inject] meta.

Shaun Smith

unread,
Feb 25, 2010, 4:56:11 AM2/25/10
to robo...@googlegroups.com
Shew.. it's taken me a little while to start getting the gist of what you're after, but I think it can be done pretty easily with child injectors - I don't even think you'll need the [Component] metadata. Or rather, I'd get it working first without it, and then add it later as a convenience.

So, your game entities will need to implement an interface. That interface would have a setter for an injector. When you map an entity the EntityMap creates a child injector and passes it through the setter. The entity configures local rules and injects into itself!

For this to work, you'll need a modified version of SwiftSuspenders:


And you'll have to help me convince Till that mapValue() really needs fixing! Currently SwiftSuspenders automatically performs injection into the value passed to mapValue(), and this will cause the parent injector to attempt injection into the entity (which we don't want - we want the entity to be injected into by its own child injector), but we still need the parent to be able to provide the entity (via mapValue) to other classes in the main context.

Shaun Smith

unread,
Feb 25, 2010, 5:39:06 AM2/25/10
to RobotLegs Discussion Group
And one other thing before I forget: don't use the MediatorMap or ViewMap - in fact, I wouldn't include them in the GameContext at all - they incur performance hits that would be unacceptable for most games.

Michael Cann

unread,
Feb 25, 2010, 8:31:46 AM2/25/10
to robo...@googlegroups.com
Hi Shaun,

Cheers for taking the time to try to understand what im jabbering about ;) Ill check out the child injector stuff for sure. Yes I was thinking too that the [Component] meta would merely be convenience, but it seemed like a neater solution. 

Ill have a crack at an implementation soon, see what others think.

Mike

Till Schneidereit

unread,
Feb 25, 2010, 8:52:45 AM2/25/10
to robo...@googlegroups.com
> And you'll have to help me convince Till that mapValue() really needs
> fixing! Currently SwiftSuspenders automatically performs injection into the
> value passed to mapValue(), and this will cause the parent injector to
> attempt injection into the entity (which we don't want - we want the entity
> to be injected into by its own child injector), but we still need the parent
> to be able to provide the entity (via mapValue) to other classes in the main
> context.

Haha! By now, I'm entirely with you on this one. The only gripe I
still have is with making this change in behavior in a minor version.
This is mostly relevant for Robotlegs, as I'm fairly confident that
people using SwiftSuspenders on its own right now are bound to be
advanced developers who could deal with the change, if it's only
brought to their attention in a prominent way.

If you feel that we can take the risk for Robotlegs 1.1, by all means:
Let's go for it.

Note that I have a couple of other bugs still to fix (mainly that
child injectors should share the map of already instances that have
already been injected into). Will do that real soon now.

Troy Gilbert

unread,
Feb 25, 2010, 10:57:27 AM2/25/10
to Robotlegs AS3
I like how you're thinking about this and am very interested in using
DI (specifically Robotlegs) to manage my component system as well.

I created a component-based game engine called Mockingbird (http://
playmockingbird.com/). I've spent the last 3 years doing AS3 component-
based game engines (and spent the 5 years before that doing similar
engines for consoles). So I've got some experience with this! ;-)

Mockingbird is a bit different in that it's engine is designed for
runtime/real-time modification to the components and game entities.
So, in your example, we'd never have a PlayerEntity or EnemyEntity
class, everything is an entity and the components are assembled based
on data.

Now that I actually start to describe it, I'm not sure where
dependency injection would fit in at our component level! ;-) Since
it's data-driven at run-time, there's not much advantage (or is it
even possible?) of using Robotlegs/SwiftSuspenders to do injection
(because we don't have actual AS3 classes).

I do a somewhat hierarchical dependency injection on my components
(what we call Behaviors): when the individual behaviors are
instantiated I setup references to their owning entity, scene and
game, then call an initializer. This is similar to how Robotlegs sets
up it's mediators (though I don't do it automagically, I explicitly
construct all the entities and populate them).

I have been curious if Robotlegs could help me at this level, but now
that I actually talk it out in this posting, I'm not so sure.

I do love using Robotlegs at the application tier, though, where I
treat the game engine itself as one component in the larger app
(which, if you look at http://playmockingbird.com/ or http://mockingbirdgames.com/
you'll see is it a lot more than just a game engine).

Troy.

Shaun Smith

unread,
Feb 25, 2010, 11:18:23 AM2/25/10
to robo...@googlegroups.com
Yup, there wouldn't be any benefit using automated DI for a completely
dynamically assembled component system - in fact, I believe it would
work rather poorly (performance-wise). For a statically linked system,
however, it might work out pretty well.

Michael Cann

unread,
Feb 25, 2010, 11:31:44 AM2/25/10
to robo...@googlegroups.com
Hi Troy,

Mockingbird looks interesting! I can see what you mean by dynamic entities.

Push Button Engine works in the same way. Even though there is an IEntity interface everything is pretty much a flat layer of Entity classes with components inside, so the only way of identifying each entity is by its "name : String" value.

Now this has probably been discussed elsewhere to death but I feel that Entities should optionally be more strongly typed. To me it just feels nasty referencing everything by string value and then having no idea whether it has the components inside that you expect. 

So im not sure if there is a good reason why you should still allow for dynamically adding components to entities. With your experience, can you think of a good example?

Sometimes I like the "data-driven" aspect of PBE but at other times I really hate it. Working on this large Facebook game at the moment its a nightmare having most things declared in XML, any refactoring causes headaches galore, and the inheritance ability in the XML while cool looking at first causes innumerable problems.

I think rather than calling this idea a "Component based Game Engine" it should be "Component based Game Framework". So that its merely the structure for others to build on, adding thier own stuff like XML-data driven entities rather than saying "this is how you should do it", its more like "here are the tools, off you go".

One thing I havent mentioned yet is Signals. I love this idea Robert Penner has done an incredible job with these things, totally turning on its head my idea about how events should work. I think they could be a great way to communicate between all levels of an app: the applicaiton tier, the entities and components. I just havent quite worked out yet how to take full advantage of these in a component based game framework.

Mike

eidiot

unread,
Feb 26, 2010, 10:46:41 AM2/26/10
to robo...@googlegroups.com
I created a LazyMediator utility: http://github.com/eidiot/robotlegs-utilities-LazyMediator to get better performance and works fine in my game.

I am very interested in the idea of a game engine base on DI (robotlegs) and as3-signals, hope it can be got further. 

2010/2/25 Shaun Smith <dar...@gmail.com>

Troy Gilbert

unread,
Feb 26, 2010, 12:58:13 PM2/26/10
to Robotlegs AS3
> Now this has probably been discussed elsewhere to death but I feel that
> Entities should optionally be more strongly typed. To me it just feels nasty
> referencing everything by string value and then having no idea whether it
> has the components inside that you expect.

In Mockingbird as originally designed (and deployed on our site) we
don't need the strong typing because our behaviors (components) all
have to "just work" when mixed with any other component, so any common
dependencies are pushed into the entity class. This makes the
behaviors less like components (in the PBE-sense) and really just
behavioral (i.e. manipulators of the baseline entity's properties).

In most of the custom work we've done for clients, they've had pre-
designed combinations of behaviors and have not exposed that dynamic
system to the user. In those cases, the behavior system gets in the
way because all of the game object logic is built in code (like what
you're describing). I then end up doing lookup-by-strings and losing a
lot of type safety, and in fact usually end up creating monolithic
behaviors for each object type.

What I'm working on right now is a system that's the best of both
worlds. Given the dynamic nature of AS3, runtime reflection, and stuff
I'm learning from the DI crowd, I've got a few ideas bubbling for how
I can do it. Haven't had a test to implement and test them yet, so
it's still all just on paper.

> So im not sure if there is a good reason why you should still allow for
> dynamically adding components to entities. With your experience, can you
> think of a good example?

We implemented "power-ups" by essentially allowing one component
(which handled "collectable" logic) to assign a behavior to the object
that collected it. So, an invincibility power-up is a collectible that
when collected assigns the "invincible" behavior to the object that
collects it. So, that's one example for dynamic behaviors/components
at runtime.

And in general, if you have that flexibility, you'll find fantastic
ways to take advantage of it. Dynamic behavior systems are very
powerful for certain types of games. For others, they're easily more
trouble than they're worth. Depends on the design.

> Sometimes I like the "data-driven" aspect of PBE but at other times I really
> hate it. Working on this large Facebook game at the moment its a nightmare
> having most things declared in XML, any refactoring causes headaches galore,
> and the inheritance ability in the XML while cool looking at first causes
> innumerable problems.

I've gone back and forth on the XML-driven component definitions.
Mockingbird was originally all described in XML, with the actual
component classes being treated as "assets". For the second version we
stripped all of that out to make Mockingbird leaner and faster, but on
our current project I'm missing the flexibility of having non-
programmers make updates to certain things. So, for our next version
I'm playing with a hybrid model that's essentially a more powerful/
expressive version of the XML, borrowing some things from MXML. In
fact, I'm even looking at making the XML compatible with MXMLC such
that things could be dynamically loaded *or* precompiled.

> I think rather than calling this idea a "Component based Game Engine" it
> should be "Component based Game Framework".

This is an important distinction. As someone who's been selling and
building game tech for the last 10 years, it's critical to distinguish
between a framework for games (something like Flixel or PBE) and a
game engine (like Mockingbird). Frameworks are essentially SDKs for
programmers to use to build the final product. Engines, in my mind,
should be designed to be entirely data-driven (beyond plug-ins/
extensions) and should include some form of toolchain. At least, those
are my expectations in those terms.

> One thing I havent mentioned yet is Signals. I love this idea Robert Penner
> has done an incredible job with these things, totally turning on its head my
> idea about how events should work. I think they could be a great way to
> communicate between all levels of an app: the applicaiton tier, the entities
> and components. I just havent quite worked out yet how to take full
> advantage of these in a component based game framework.

Signals (as a pattern) is critical for games. The native Flash event
system is too heavy weight to use for inter-object communication. It's
the biggest bottleneck in the original Mockingbird (which uses native
events and the native display list extensively). The latest versions
of Mockingbird have dispensed with almost all events from within the
engine and instead use a custom Signals-like system. It was even more
of an issue with Mockingbird as the original version used Flex change
events for handling all of the dynamic updates, which caused a *huge*
amount of memory allocation for just events when a new game would be
loaded.

Troy.

Shaun Smith

unread,
Mar 3, 2010, 12:00:52 PM3/3/10
to robo...@googlegroups.com
This is pretty cool. My only concern is that you're completely re-implementing the MediatorMap - as opposed to simply overriding some of the methods. I believe you're doing this to reduce the overhead of the describeType calls. I'm not sure that they are such a big deal though. The ADDED_TO_STAGE is by far the biggest bottle neck, so I believe it would be enough to simply override the MediatorMap's add/removeListeners methods and listen for the new events. It might not be quite as fast as how you're doing it now, but it would be a nice compatible drop-in replacement.

Michael Cann

unread,
Mar 3, 2010, 12:47:35 PM3/3/10
to robo...@googlegroups.com
Not sure of you were talking to me or not there Shaun. 

If you were talking to me, the problem is that not every entity would have a view component so the Mediator / View pattern doesnt really apply to a game component framework. 

All is not lost however as the Mediator / View bit is needed for such things as popups, menus, things that are typically more "Flex" like and hence RL would be an excellent fit for those bits.

Im not sure how you do menus and non-game-entity views Troy, but in PBE you are encouraged to use components for these too. So you have something like "MainMenuController" component which handles the main menu. I assume because PBE is designed to work without flex this is the way they have done everything.

I like the power flex brings to GUI tasks like menus and HUDs and things like that, so we are currently doing things like that on a separate layer that runs over the top of the PBE "game layer". As I said in a previous mail, this part is currently handled by Mate, but I would much prefer to move that over to RL.

Im under alot of pressure at the moment at work so I have had very little personal time to get coding on this unfortunately. I hope to get some code bashed out in the next coupple of weeks.

Mike

Shaun Smith

unread,
Mar 3, 2010, 12:51:47 PM3/3/10
to robo...@googlegroups.com
Ah, no, sorry, I was talking to Eidiot regarding the LazyMediator util he built :)

Michael Cann

unread,
Mar 3, 2010, 12:53:45 PM3/3/10
to robo...@googlegroups.com
Oh, disregard my diatribe then :P

eidiot

unread,
Mar 3, 2010, 6:54:00 PM3/3/10
to robo...@googlegroups.com
Hi Shaun, 

Yes, I was to reduce the calls to describeType. Because when I profiled my game in Flex, String created by describeType in SwiftSuspenders is the second problem after BitmapData. But that's because MediatorMap check every ADDED_TO_STAGE. In LasyMediatorMap only views really need be mediated will be checked, so I think I'd better remove this and just override some methods as you said. I'll do some test and then change it soon. 

Thanks very much for your attention.

2010/3/4 Shaun Smith <dar...@gmail.com>

Shaun Smith

unread,
Mar 3, 2010, 7:00:38 PM3/3/10
to robo...@googlegroups.com
Hi! I committed some changes to my fork as an example:


But I didn't get round to changing the tests etc, so I'm not sure if it works!

eidiot

unread,
Mar 3, 2010, 7:53:08 PM3/3/10
to robo...@googlegroups.com
I merged your changes and all tests passed. Thanks again for your attention.

Shaun Smith

unread,
Mar 4, 2010, 9:12:01 AM3/4/10
to robo...@googlegroups.com
Cool. How does the performance compare? Is the describeType still slowing things down? Or is it acceptable now that it's now doing it for every display object? How does it compare to your previous version?

eidiot

unread,
Mar 4, 2010, 10:53:10 AM3/4/10
to robo...@googlegroups.com
Almost the same: Yours is a little faster:

Old (my) version (PerformanceTestClass):
[MethodTest name='Add view test' time=111.4 min=104 max=122 deviation=0.162 memory=1168]
<TestCollection>
  <MethodTest name="Add view test" time="111.4" min="104" max="122" deviation="0.162" memory="1168" retainedMemory="1115">
    <iteration time="107" memory="1396" retainedMemory="1268"/>
    <iteration time="109" memory="1052" retainedMemory="1028"/>
    <iteration time="104" memory="1040" retainedMemory="996"/>
    <iteration time="115" memory="1128" retainedMemory="1112"/>
    <iteration time="122" memory="1228" retainedMemory="1176"/>
  </MethodTest>
</TestCollection>

Current (yours) version (PerformanceTestClass):
[MethodTest name='Add view test' time=108.2 min=95 max=123 deviation=0.259 memory=1169]
<TestCollection>
  <MethodTest name="Add view test" time="108.2" min="95" max="123" deviation="0.259" memory="1169" retainedMemory="1113">
    <iteration time="99" memory="1392" retainedMemory="1264"/>
    <iteration time="95" memory="1048" retainedMemory="1020"/>
    <iteration time="108" memory="1060" retainedMemory="1012"/>
    <iteration time="123" memory="1124" retainedMemory="1104"/>
    <iteration time="116" memory="1228" retainedMemory="1172"/>
  </MethodTest>
</TestCollection>

2010/3/4 Shaun Smith <dar...@gmail.com>
Reply all
Reply to author
Forward
0 new messages