Showing posts with label entity system. Show all posts
Showing posts with label entity system. Show all posts

Saturday, March 10, 2012

The Components and Systems of Morgan's Raid

I've written before about the entity system architecture of Morgan's Raid. I am just now polishing a paper on the topic which I will present at the FDG conference in May. I contacted Adam Martin to get his feedback on the paper, and he was very helpful. He made a few suggestions that I simply did not have space to address in the eight-page conference paper, but since Blogger has no page limit, I would like to address one of them here: what are the actual components and systems of Morgan's Raid?

By way of simple introduction, an entity system architecture is a software architecture in which game object data is stored in simple objects called "components" and these are processed by "systems." Game objects then are simply unique identifiers that aggregate components. This approach favors delegation over inheritance. It proves useful in game development due to the highly experimental nature of such systems: the domain model itself is subject to dramatic change during practically every stage of development. For further discussion, check out the entity systems project wiki.
Numbers of components and systems during development
The figure above shows the growth of the number of systems and components during the development of Morgan's Raid. This figure appears in the paper with a brief interpretation. I provided the small initial set to help bootstrap the students, but most of the rest were written by them—the 25 developers who worked in Fall 2010 and eight who worked in the Spring 2011. I am very proud of the team, don't confuse my pride in their achievement with any claims of elegance and beauty. Indeed, there are quite a few smells in our implementation.

Without further ado, tearing into the source code of Morgan's Raid, we can see how the systems and components are related. (It appears that Blogger automatically scales large images down. You can grab a full-size PDF here.)
System-Component Dependencies
The systems are on the left and components on the right, with edges showing system-component dependencies. As evidenced by the diagram, there are a few components which are heavily used throughout the implementation. OnScreenBoundingBox, for example, is used by anything that involves bounding boxes. (This was originally called Position, but that caused serious confusion when dealing with world vs. screen coordinates. After refactoring, we ended up with OnScreenBoundingBox and GPSPosition, the latter because world coordinates were actual GPS coordinates.) There are a few systems that have no out-edges because they use no components at all. For example, FadingSystem handles the fading of the screen based on time of day, but it does not deal with a component explicitly: it is passed a long integer that represents the current time of day and performs its computation from that.

Several of the components have no in-edges. A handful of them are, sadly, rotten code that was never removed. In fact, some are added to game objects and never accessed by anything else. Others of these disconnected nodes are used directly by the non-system game code. The Morgan's Raid implementation reifies the state design pattern, and there are many places where critical game logic was done directly within these classes rather than delegating to explicitly named and tested systems. This is not ideal, and I ascribe it to the novice level of many of the developers. Ask anyone on the team what they think about the 1700-line behemoth InGameState and they will cringe and tell you it should have been done better, but at the time, they did not know how to actually make it better.

In the diagram above, I have hidden the inter-system and inter-component dependencies for one very good reason. When they are shown, the diagram becomes a bit of a mess. Check it out (or full-size PDF here).
System-System, System-Component, and Component-Component Dependencies in Morgan's Raid

Ignoring for the moment the fact that you cannot discern the system-component dependencies, this diagram does show that the number of system-system and component-component dependencies is relatively low. However, if I were to throw InGameState into the mix, it would have its fingers in practically everything.

The diagrams were generated with dot, and you can download the graph file here. (Note that Google Docs thinks this is some kind of Microsoft file due to naive handling of file extensions. Just download the original and open in your favorite plain-text editor.) I created that file manually by inspecting the Morgan's Raid source code, and so it may contain minor errors.

For your reading convenience, here's a simple tabular view of the systems and components as well.


SystemsComponents
BackgroundTileSystem
CityNameSystem
DestinationSystem
FadingSystem
GPSToScreenSystem
HoverableSystem
ImageRenderingSystem
IntInterpolationSystem
MinimumSleepTimeSystem
MorganLocationSystem
NightRenderingSystem
OnClickMoveHereSystem
OnScreenBoundingBoxSystem
RaidSoundSystem
RailwaySystem
ReputationSystem
RevealingTextSystem
SpeedSystem
StepwisePositionInterpolationSystem
SunSystem
TimePassingSystem
TimeTriggeredSystem
TownArrivalSystem
TownArrowSystem
TownUnderSiegeSystem
AnimationRenderable
ArrivesAtTownIndex
BackgroundTile
BeenRaided
CentersOnGPS
CityData
CityImages
CityName
CityPopulation
CityTargets
CommandPoint
Destination
DoesCityHaveMilitia
DoesCityLoseGame
DoesCityWinGame
GPSPosition
GPSPositionList
HasMorganGPS
Hoverable
ImageRenderable
ImageRenderLayer
InGameTime
IntInterpolated
MinimumSleepTimeOverride
Morgan
MorganLocation
MovesOnClick
OnClickMoveHere
OnScreenBoundingBox
OnScreenBoundingBoxList
PositionInterpolated
Raidable
Raider
Railway
Reputation
ReputationValue
RevealingText
Road
RoadsToCity
RouteTaken
Speed
Sun
Terrain
TimeToRaid
TimeTriggeredEvent
TownAdjacency
TownArrow
TownUnderSeige

Thursday, June 16, 2011

A Ruby DSL for creating entity system components in Java

Have you ever been working with entity system architectures in Java and wished for a quicker way to prototype components? Well, you've come to the right place.

After working with entity systems for about year, I have an idiosyncratic way of defining any of my components. Keep in mind that components are just dumb data objects, not proper OO-objects, and I'm roughly following Adam Martin's approach. Here's the way I would define a position component for two-dimensional floating-point space:


public class Position {

    private float x;
    private float y;
    
    public float x() { return x; }
    public float y() { return y; }
    
    public Position x(float x) { this.x=x; return this; }
    public Position y(float y) { this.y=y; return this; }
    
}


I've skipped documentation for the sake of brevity. I like to keep my data private, even though it's exposed through accessors and mutators—I just can't bring myself to make public instance fields in Java. The naming convention for accessors and mutators is a Smalltalk approach, using the same name for both accessor and mutator, which can lean designs towards fluent API design instead of pushbutton (see Fowler's DSL book for more on this). The mutator returns code to promote fluent API design as well, to permit code like the following.


Position p = new Position().x(10).y(15);

Now if I'm feeling really spiffy, I'll use a builder:

Position p = new Position.Builder().x(10).y(15).build();

but that's not my point.

My point is that this is almost all boilerplate code. All I really want to say is that there's a component called Position and it has two floats, x and y. So maybe what I really want to be able to write is something like this:

Component.build :Position do
  float :x
  float :y
end

The title of the post gives it away, but this is a little Ruby DSL that I hacked together this afternoon, just to see if I could. I've been meaning to learn Ruby for some time. I have read quite a bit about Ruby and its use in DSLs, but never actually created one. This time around, I used Jonathan Magen's tutorial as a reference.

The Component module is the starting point, and it uses what I take to be a fairly standard approach, sending blocks of code from the context to be executed within the object context:

module Component
  def self.build(name, &block)
    builder = ComponentBuilder.new(name)
    builder.instance_eval(&block)
    builder.build()
    return builder
  end
end

The one custom piece is the build method on the ComponentBuilder. What this does (perhaps not clearly indicated by the name, in retrospect) is tell the constructed object to dump out a Java source file based on the content of the block. The ComponentBuilder looks like this:

class ComponentBuilder 
  def initialize(name)
    @name = name
    @floats = []
  end

  def float(x)
    @floats << x
  end

  def build
    File.open(@name.to_s + ".java", "w") do |theFile|
      theFile.syswrite("public class #{@name.to_s} implements Component {\n")
      unless @floats.nil? 
        @floats.each do |var|
          theFile.syswrite <<BLOCK
    private float #{var};
    public float #{var}() { return #{var}; }
    public #{@name.to_s} #{var}(float #{var}) {
        this.#{var} = #{var};
        return this;
    }
BLOCK
        end
      end
      theFile.syswrite("}")
    end
  end

end


Here's a very quick walkthrough for those readers who do not know Ruby. The initialize method is the constructor, and it's setting the instance variable @name to the argument's value and initializing an empty array for @floats. The next method is called float, which is not a reserved word in Ruby, and it appends its argument to the @floats array. The build method opens the appropriately-named file, writes the class declaration, and then iterates through the @floats field, dumping out the field, accessor, and mutator definition for each one.

There were two specific pieces of Ruby syntax that I had to learn to make this work: here documents and expression substitution in strings. The oddly named "here documents" are multiline string literals. In my program, they run from <<BLOCK to the recurrence of BLOCK. This is a really useful feature for a program that is essentially filling templates and dumping them out. C# has something similar, but Java—my usual production language— does not. Note that you can do it with Groovy, though it appears the proposal to put this in 1.7 hasn't been approved. Regardless, expression substitution in strings is simple and elegant: within a string literal, put an expression within #{...}, and it is evaluated and interpolated into the string at runtime.

In order to make my program a bit more robust, I added configuration information to control the Java package and path to the destination as well as per-class and per-field embedded Javadoc, passed as optional parameters (via variable-length argument lists). The biggest problem I had with this was creating directories automatically from relative paths, but in the end, I pulled it off with a little custom method shown below.

def defensive_makedir(dir) 
  array = dir.split('/')
  accum = '.'
  array.each do |partial| 
    accum = accum + "/" + partial
    unless File.directory? accum
      Dir.mkdir accum
    end
  end
end

To integrate this into Eclipse, I wrote a simple ant build script. Honestly, I wrote this very early in the experiment, but the process of debugging Ruby through Eclipse and Ant was quite cumbersome, and once I hopped over to a console and emacs, I was able to iterate much faster. To incorporate this into the build process in Eclipse, hop over to your project preferences and check out the "Builders" section. This requires the JRuby jar to be on the build path.


<project name="FunWithComponents" default="make_components">
    
    <property name="lib" location="${basedir}/vendor/lib"/>
    <property name="jruby.jar" location="${lib}/jruby.jar"/>
    <property name="ruby.src" location="${basedir}/ruby"/>
    <property name="generated.src" location="${basedir}/gen"/>
    
    <target name="make_components">
        <java jar="${jruby.jar}" fork="true" dir="${ruby.src}">
            <arg value="${ruby.src}/make_components.rb"/>
        </java>
    </target>
        
</project>

I enjoyed working on this and learned a bit about Ruby, both in terms of the language and how to express myself within it. I acknowledge that I do so much work in Java, it can be hard to switch paradigms or idioms, and so it's good to actually make something useful from time to time. However, it also makes me wonder if all that trouble is actually worth it when I can immediately imagine how to support a Java-based solution like the following.

 public static void main(String[] args) {
    ComponentFactory.instance().build("Position")//
        .withFloat("x")//
        .withFloat("y")//
        .build();
    }

Wednesday, June 30, 2010

Entity system in Java: an early prototype

I have been intrigued with entity systems (ES) since reading Adam Martin's series of posts, and I started tinkering with an ES implementation since reading his Android example. I started with a game concept  using OpenGL on Android, but the mobile environment and my rustiness with OpenGL made this project slow to a crawl. A few days ago, I was inspired to revisit one of my favorite game ideas, and after about two or three days of tinkering, I have a nice framework put together.


Just about four years ago, I led a seminar on game engine design. My inspiration that Summer was to explore the interplay between design patterns and game development. To this end, I created EEClone, a simplified clone of the incredible and addicting Every Extend. EEClone's design explicitly features patterns, although I was careful not to wedge pattern reifications where they did not belong. I consider this project a success, and it led to a series of scholarly articles and a fascinating research direction. I have been considering ES for a project with potentially much greater impact, and so I decided to revisit my cloning of Every Extend gameplay, now with the purpose of exploring ES implementations.


Here is what it looks like in action.





The entity manager is very similar to Adam's, and I'm grateful for his implementation sharing. For me, the most significant challenge was determine how to slice the problem up into components and systems. Keep in mind that in an entity system, components are "dumb" data objects and systems operate over components.


These are the components that I used. [EDIT: I did some refactoring the morning after this post, and the changes are reflected below.]
  • Explodable is a tag component that indicates that the corresponding entity should explode if it hits an explosion.
  • Exploding indicates that an entity is exploding. Contains the max explosion radius, rate of expansion and decay, and whether the explosion is expanding or collapsing.
  • InputExplodable is a tag component that indicates that the corresponding entity can be blown up by direct player input.
  • InputMovable indicates that the entity can be moved by direct player input.
  • PhysicsMovable holds a vector that represents the direction an entity is moving.
  • Position is a position in space, consisting of x, y, width, and height.
  • PrimitiveRenderable has a shape code and a color, indicating that the entity should be drawn with graphics primitives.
  • Renderable has an Image and indicates that the entity should be drawn as an image sprite.
These, then, are the corresponding systems:
  • ExplodingSystem processes Exploding things, scaling them to the right size (i.e. changing their Position), handling the transition from expanding to collapsing, and removing the corresponding entity when the explosion is complete.
  • ExplosionCollisionSystem looks for intersecting Exploding and Explodable entities, replacing the Explodable ones with Exploding ones.
  • KeyboardInputSystem monitors the keyboard and processes InputMovable and InputExplodable entities accordingly.
  • PhysicsMovementSystem goes through all the PhysicsMovable entities and updates their Position based on the their PhysicsMovable velocity vector.
  • PrimitiveRenderSystem draws PrimitiveRenderable entities at their Positions based on the shape and color in the PrimitiveRenderable component.
  • RenderSystem draws images at the corresponding Position baed on the image reference in the Renderable component.
Obviously, some of those names are ripe for refactoring, but this is an accurate representation of the build in the video. To give you an idea of what the implementation feels like, here is the code that creates the crazy guy you control with the keyboard (Boognish), using some method chaining:
manager.createEntity() 
        .add(new Position().x(320).y(240)) 
        .add(new Renderable().image("boognish.png")) 
        .add(new InputExplodable()) 
        .add(new InputMovable().speed(120))
        .add(new KeyboardExplodable());

I started writing this code a two weeks ago or so. Then based on the comments in my other post, I decided to try the Game Object Component System (GOCS) approach described by Chris Stoy in Game Programming Gems 6. In a nutshell, GOCS hits the same pain point as ES, but in GOCS, game object components are regular "smart" objects with their own methods, so there is not the ES distinction between the component and the system that processes it. As I started working on the GOCS code, I kept coming back to the arguments for ES and ended up along the path to simply re-creating my incomplete ES demo. GOCS is now back on the shelf, and I feel like after weeks of off-and-on contemplation and a few days of coding, there's something about ES that has clicked with me.

I am considering spending another day or two with this code to try to make a more compelling example, a real playable game that I could use as a case study in my class next semester. However, even coming this far, I feel like I have a better grasp on how to decompose game elements into components and systems, perhaps well enough to begin work on the technical specification of the Morgan's Raid game.