Table of Contents
This page is still WIP!
About
This page serves as a rubric for development on our ECS branch. Be aware that as the ECS branch is under active development, the information on this page may be out of date or in need of revision.
What is ECS?
ECS is an architectural pattern, you can read about it on wikipedia.
Why do we want ECS in OpenDiablo2?
As of writing, much of our engine code is tightly coupled. It makes writing tests or re-using code fairly difficult. An ECS implementation will resolve this issue because systems in an ECS architecture are decoupled via the components they use.
What ECS framework are we using?
We have developed our own called Akara.
Please read the akara README
for the most up-to-date info regarding basic usage.
Development Guide
Everything in this section needs to be adhered to. PR's will not be merged if they violate anything described herein.
Systems will contain a d2util.Logger
and a unique logger prefix
const (
logPrefixExample = "Example System"
)
type ExampleSystem struct {
akara.BaseSystem
*d2util.Logger
}
func (u *ExampleSystem) Init(world *akara.World) {
u.World = world
u.setupLogger()
if u.World == nil {
u.SetActive(false)
}
u.Debug("initializing")
}
func (u *ExampleSystem) setupLogger() {
u.Logger = d2util.NewLogger()
u.SetPrefix(logPrefixExample)
}
Graphical systems must be implemented as a Scene
system
Please read about scene systems here.
Every component should also declare a concrete component factory
This is important because it reduces noise in our code by keeping us from constantly casting akara.Component
to the concrete component implementation.
here is an example Color
component:
// Color is a flag component that is used to denote a "dirty" state
type Color struct {
color.Color
}
// New creates a new Color. By default, IsColor is false.
func (*Color) New() akara.Component {
return &Color{
color.Transparent,
}
}
And here is the concrete component factory for this component
// ColorFactory is a wrapper for the generic component factory that returns Color component instances.
// This can be embedded inside of a system to give them the methods for adding, retrieving, and removing a Color.
type ColorFactory struct {
*akara.ComponentFactory
}
// Add adds a Color component to the given entity and returns it
func (m *ColorFactory) Add(id akara.EID) *Color {
return m.ComponentFactory.Add(id).(*Color)
}
// Get returns the Color component for the given entity, and a bool for whether or not it exists
func (m *ColorFactory) Get(id akara.EID) (*Color, bool) {
component, found := m.ComponentFactory.Get(id)
if !found {
return nil, found
}
return component.(*Color), found
}
File locations
At the time of writing:
- all systems belong in
d2core/d2systems/
- all components and component factories belong in
d2core/d2components/