Ello List,
Finally found a few hours to spare to knock out a first draft of the very basics of a DI based Game Component Framework.
So far I have developed the core classes: Entity, EntityComponent, EntityMap and GameContext.
Starting with the GameContext. I have had to make a detor from RL here as, on suggestion from Shaun, I likely shouldnt include ViewMap nor MediatorMap for performance reasons. I also require child injectors found in SwiftSuspenders 1.5+ (more on that below) and as the RL ContextBase is built for pre-child injectors I decided not to extend it for now, so I can get something working. So for now my GameContext is a simple class containing an EntityMap reference and a SignalMap reference, and uses the Injector class of SwiftSuspenders directly rather than IInjector of RL.
The method of using the context should be familiar however as it any entities or signals requiring mapping are decared in the startup call. Taken from my very simple example game (find attached):
public class MyGameContext extends GameContext
{
// protecteds
protected var _blueCircle : BlueCircle;
protected var _scene : Scene;
public function MyGameContext(sceneLayer:Sprite)
{
// Making the scene
_scene = new Scene();
sceneLayer.addChild(_scene);
// Init the context
super();
}
override public function startup():void
{
// Map the scene for use by the entities and components
injector.mapValue(Scene, _scene);
// Map some commands
signalCommandMap.mapSignalClass(SpawnRedCircleSignal, SpawnRedCircleCommand);
// Now make a blue circle that follows the mouse about
_blueCircle = entityMap.instansiateEntity(BlueCircle) as BlueCircle;
}
}
The EntityMap is very simple for now, and contains a single method:
public function instansiateEntity(entityClass:Class) : Entity
{
var entity : Entity = new entityClass();
entity.injector = _injector.createChildInjector();
return entity;
}
The entity is to serve as the base of all entities in a game. Its primary function is to manage the components that the user adds via the "mapComponent" function. The entity also manages the injection into the components.
As an example, a typical entity could look like this:
package co.uk.mikecann.app.entities
{
import co.uk.mikecann.app.components.CircleRendererComponent;
import co.uk.mikecann.app.components.SpatialComponent;
import co.uk.swft.base.Entity;
public class RedCircle extends Entity
{
// Components
public var spatial : SpatialComponent;
public var renderer : CircleRendererComponent;
override protected function onMapComponents() : void
{
// Map some components
spatial = mapComponent(SpatialComponent) as SpatialComponent;
renderer = mapComponent(CircleRendererComponent) as CircleRendererComponent;
// Setup some params on the components
renderer.colour = 0xff0000;
}
}
}
Here the RedCircle Entity is made up of two components, a spatial and a renderer. On instantiation the Entity base calls the onMapComponents which adds it to the list of components. Once all components have been added, it then injects into them and calls "onInit" on the components:
public function set injector(value:Injector) : void
{
// Set the injector and inject ourselfs first
_injector = value;
_injector.injectInto(this);
// Now tell sub-classes to map any components they are going to use
_components = new Vector.<EntityComponent>();
onMapComponents();
// Finally inject into those components and tell them to init
injectIntoComponents();
initComponents();
}
When called it makes a child injector (thankyou Shaun for suggesting this) for use by the entity so that the GameComponent injections dont conflict. This way we have have components that are mapped by an entity child injector and so are only available for injection within the context of that entity:
public class CircleRendererComponent extends EntityComponent implements IUpdateable
{
// Injecteds
[Inject] public var scene : Scene;
[Inject] public var spatial : SpatialComponent;
..
}
and
public class MouseFollowController extends EntityComponent implements IUpdateable
{
// Injecteds
[Inject] public var scene : Scene;
[Inject] public var spatial : SpatialComponent;
override public function onInit() : void
{
// register us for updates
scene.registerForUpdates(this);
}
public function update() : void
{
// Follow the mouse scene position
spatial.position.x += (scene.mouseX-spatial.position.x)/6;
spatial.position.y += (scene.mouseY-spatial.position.y)/6;
}
}
So there that is my start to this project. I realise its very basic at the moment and lacks many of the important parts of a framework and indeed good programming style such as Interfaces and Tests, but for now I wanted to bash this out, get a feel for it and see what you think!
I decided to email the list rather than blogging about it as it's still very early days (one evenings work) and im extremely keen to hear any ideas you guys have for changes and improvements!
Cheers,
Mike
P.S. Oh BTW I have called the project “Swft” for now, just because I had to give the project some name, and I had bought the www.swft.co.uk domain name some time ago and not done anything with it. I asked Till of Swift-Suspenders if he minds the similar name and he said he is cool with it.
--
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
<SwftExample1.zip>
<Swft-Lib.zip>
public class BlueCircle extends Entity{...// Components[Component] public var spatial : SpatialComponent;[Component] public var renderer : CircleRendererComponent;[Component] public var controller : MouseFollowController;...
<template name="CafeFloor" template="SpatialEntity">
<component type="com.playdemic.gnb.components.commodity.CommodityComponent" name="Commodity" />
<component type="com.playdemic.gnb.components.commodity.StockItemComponent" name="StockItem" />
<component type="com.playdemic.gnb.components.controllers.cafe.CafeFloorController" name="EntityContainer">
<spatial componentName="Spatial" />
<renderer componentName="Renderer" />
<scene entityName="Scene"/>
<sellable>false</sellable>
<moveable>false</moveable>
<fertiliserSpriteSheet entityName="Cursors_Fertiliser_SpriteSheet" />
<handCursorSpriteSheet entityName="Cursors_Hand_SpriteSheet" />
</component>
<component name="Renderer">
<layerIndex>91</layerIndex>
</component>
</template>
<Player>
<spatial>
<x>200</x>
<y>300</y>
</spatial>
<renderer>
<sprite swf="assets/player.swf" clip="player_idle" />
</renderer>
</Player>
var deserializer : EntityDeserializer = new EntityDeserializer();
deserializer.mapEntity("Player",MyPlayerClass);
deserializer.deserialize("assets/definitions.xml");
protected function mapComponentSingleton(componentClass:Class) : void
{
var component : IEntityComponent = new componentClass();
injector.mapValue(componentClass, component);
_components.push(component);
}
public class BlueCircle extends Entity{
...
// Components[Component] public var spatial : SpatialComponent;[Component] public var renderer : CircleRendererComponent;[Component] public var controller : MouseFollowController;...}
[PostConstruct]
public function init() : void
{
}
override public function init() : void
{
super.init()
spatial.velocity.y = 0.3;
}
Okay I have just spent a few more hours writing a very basic example game called "Shooter":
I should hope that the project never gets too complicated that I cant accept aid from anyone at any stage. One of the main reasons for me posting about this project is because some of the best programmers in our field read this list and I highly value their input even if it isnt strictly to do with the RL Framework. I am also extremely grateful for the contributions so far and am looking for more from anyone that wants to help out.
I have been thinking (mainly after writing my last post) too that I should keep an archive of these mails somewhere. I have the domain www.swft.co.uk and I have my personal blog: www.mikecann.co.uk so I think ill setup a subdomainblog.swft.co.uk and document the discussions of this list.
class MyEntity extends Entity
{
[Inject] public var spatial : SpatialComponent;
[Inject] public var renderer : RendererComponent;
[Inject] public var stateMachine : FSMComponent;
[Inject] public var persistor : PersistedEntityComponent;
override public function mapComponents():void
{
injector.mapSingleton(SpatialComponent);
injector.mapSingleton(RendererComponent);
injector.mapSingleton(FSMComponent);
}
override public function onRegister():void
{
persistor.mapForPersistance(spatial,"x");
persistor.mapForPersistance(spatial,"y");
persistor.mapForPersistance(stateMachine,"state");
}
}
How are you supposed to merge the master with someone elses fork?
http://github.com/mikecann/Swft/blob/master/src/co/uk/swft/base/Entity.as#L37 resulting in the fact that a component may not have some if its dependencies registered in time
I have made a small change to IEntity and hence Entity. I have renamed the removeComponent to unregisterComponent, I think this correlates better with its counterpart method 'registerComponent'.
Having the ability to register and unregister components brings into focus the ability to dynamically add and remove components. Im going to give this some more thought over the next few days. I suspect some modifications will need to be made for it to work. Specifically to dynamically add a component to an entity it will need to be manually injected into using the injector of the entity.
I plan on expanding the shooter game a little too, adding scores and the like. Just to see what other issues come up. I may also take a look at that persistence issue Jos is having and see if there is a neat way to solve it.
ps. i don't want anyone to take offence at _my personal_ take on this, or to project anything out of _my personal_ take on this to your own personal take on this. I don't expect anyone else to think/feel/react the way i do, so please don't take this as some kind of angry reactionary posturing! I can get into the reasons for why i choose to react this way, if you are interested, but that is better off-list. Peace.
LicenseOne final issue guys. I have been talking with my current employer about this project and I was saying how I would like to use it on our next project at work. I think this would give it some solid real-world testing and would improve it greatly. They were however nervous about me giving away company secrets to the community in case I empowered our competitors. After much discussion they agreed it is in the benefit of the company for me to keep working on this open source, there was one stipulation however. When released Swft will need to have a licence that will require companies of 3 or more employees to first seek permission from them.
15. DESIGNS AND INVENTIONS
15.1 All designs, inventions, programs, discoveries or improvements conceived or made by you during the course of or arising out of your employment with the Company (whether alone or together with any other person or persons) and which concern or are applicable to products or articles manufactured or sold by or to services provided by the Company ("Designs and Inventions") shall be the exclusive property of the Company.
one of the things about game programming im trying to figure out is do
I do it in the new spark framework or do it in pure flash?
--
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
Thanks for taking the time with you company to really push for this - Congrats again.
j
ps. Shaun's idea of keeping Components "internal" and closed is still a good one, i think. There is always going to be "goodies" which you develop which are really for internal use only. Having the framework and whatever other components the community works on together open is going to be a huge win as it is.
for support visit http://knowledge.robotlegs.org