Simple Systems

One of the main reasons I decided to include a game example while documenting the ECS development is that I found that much of it is about the pattern that I use with it rather than the actual code itself.

The basic idea of a system in ECS is that it handles any changes needed by components for each game loop. So it your game has components with velocity, a system is responsible for moving those components the appropriate amount.

In my first attempts an an ECS before this, I equated a system to the list of components that it needed to deal with. So a MovementSystem would have a container of Movement components that it processes.

The problem with that is that 2 different systems might share components. A Location component would be needed by a system handling physics and a system that was making decisions for computer controlled entities.

So, the top level EntityScene will have all of the component containers. Each system will declare what components it needs and the scene will pass those into the system each game loop.

Example System

That’s still kind of abstract so here’s an example from the game for the MovementSystem. The implementations are left out here because

Components

///  Describes how an entity moves
struct Movable : Component {
}

protocol MovableComponents {
  associatedtype MovableContainerType: ComponentContainer where MovableContainerType.ComponentType == Movable
  var movables: MovableContainerType {get}
}

/// Describes the physical body and location of an entity
struct Body : Component {
}

protocol BodyComponents {
  associatedtype BodyContainerType: ComponentContainer where BodyContainerType.ComponentType == Body
  var bodies: BodyContainerType {get}
}

The important parts of this are the MovableComponents and BodyComponents protocols. These will be used for a system to declare what kind of components it is dependent on.

A similar pattern will be followed for each component in the game. So for every component, there will be an additional protocol for systems to declare their dependencies.

I tried playing around with Xcode snippets a bit to see if I could make adding them a bit easier, but that seems insufficient. I think an Xcode template will work.

System

/**
 The movement system depends on the following components
 - Movables: determine how the entity moves
 - Bodies: the location of the entity
*/
protocol MovementScene: EntityScene, MovableComponents, BodyComponents {
}

/**
 Moves all of the components that need to be
*/
class MovementSystem<SceneType: MovementScene>: System {
  func update<SceneType: MovementScene>(scene: SceneType, timeDelta: TimeInterval) {
    scene.movables.forEach(with: scene.bodies) { entity, movable, body in
      // move the entity
    }
  }
}

The MovementScene protocol is how we declare what the MovementSystem is dependent on. The EntityScene protocol is just the base protocol for scenes and includes a property for the EntityBuilder so entities can be added and removed.

Then it’s dependent on the two protocols we just declared. So when it’s time to update (each game loop), the MovementSystem can update any scene that has both Movable and Body components.

The MovementSystem itself, will iterate over all entities that have Movable and Body components and move them the appropriate amount.

The forEach function is an extension on a ComponentContainer that simplifies iterating entities when multiple components are required.

Scene

Finally there’s the scene itself.

class BreakoutScene: EntityScene, MovementScene, CollisionScene {
  let builder = EntityBuilder()

  // all components
  let bodies = DenseComponentContainer<Body>()
  let movables = SparseComponentContainer<Movable>()

  // all systems
  let movementSystem = MovementSystem<BreakoutScene>()

  func update(_ timeDelta: TimeInterval) {
    movementSystem.update(scene: self, timeDelta: timeDelta)
    // update the other systems
  }
}

The BreakoutScene class is pretty much an analog for the SKScene subclass that would be in a SpriteKit game. I’ve chosen to keep it separate just to keep a bit of extra separation from the SpriteKit specific code.

Git repositories

I’ve put up a repository for the Breakout game and SwiftECS

Previously

Next up

We’ll get back into actually implementing this and see the basic patterns for a system.

History

All posts about the development of SwiftECS can be found here

:computer:

Updated: