mirror of
https://github.com/OpenDiablo2/OpenDiablo2
synced 2025-02-18 14:36:44 -05:00
Systems now place all of their component factories into a `Components` member. This improves code readability and makes it clear when we are dealing specifically with ecs components. The concrete ComponentFactory instances now have `Add` and `Get` methods (as opposed to `AddAlpha` or `GetAlpha`). This enforces naming of component factories as to avoid collisions when embedded in a struct with other components. Also, the ComponentFactory interface is embedded directly into the concrete component factory without a name.
154 lines
4.1 KiB
Go
154 lines
4.1 KiB
Go
package d2systems
|
|
|
|
import (
|
|
"image/color"
|
|
|
|
"github.com/gravestench/akara"
|
|
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2common/d2util"
|
|
"github.com/OpenDiablo2/OpenDiablo2/d2core/d2components"
|
|
)
|
|
|
|
// NewShapeSystem creates a new sprite factory which is intended
|
|
// to be embedded in the game object factory system.
|
|
func NewShapeSystem(b akara.BaseSystem, l *d2util.Logger) *ShapeSystem {
|
|
sys := &ShapeSystem{
|
|
Logger: l,
|
|
}
|
|
|
|
sys.BaseSystem = b
|
|
|
|
sys.World.AddSystem(sys)
|
|
|
|
return sys
|
|
}
|
|
|
|
// ShapeSystem is responsible for queueing sprites to be loaded (as spriteations),
|
|
// as well as binding the spriteation to a renderer if one is present (which generates the sprite surfaces).
|
|
type ShapeSystem struct {
|
|
akara.BaseSubscriberSystem
|
|
*d2util.Logger
|
|
RenderSystem *RenderSystem
|
|
Components struct {
|
|
Transform d2components.TransformFactory
|
|
Color d2components.ColorFactory
|
|
Rectangle d2components.RectangleFactory
|
|
Texture d2components.TextureFactory
|
|
Size d2components.SizeFactory
|
|
Origin d2components.OriginFactory
|
|
}
|
|
loadQueue spriteLoadQueue
|
|
shapesToRender *akara.Subscription
|
|
shapesToUpdate *akara.Subscription
|
|
}
|
|
|
|
// Init the sprite factory, injecting the necessary components
|
|
func (t *ShapeSystem) Init(world *akara.World) {
|
|
t.World = world
|
|
|
|
t.Debug("initializing sprite factory ...")
|
|
|
|
t.setupFactories()
|
|
t.setupSubscriptions()
|
|
|
|
t.loadQueue = make(spriteLoadQueue)
|
|
}
|
|
|
|
func (t *ShapeSystem) setupFactories() {
|
|
t.InjectComponent(&d2components.Color{}, &t.Components.Color.ComponentFactory)
|
|
t.InjectComponent(&d2components.Transform{}, &t.Components.Transform.ComponentFactory)
|
|
t.InjectComponent(&d2components.Texture{}, &t.Components.Texture.ComponentFactory)
|
|
t.InjectComponent(&d2components.Origin{}, &t.Components.Origin.ComponentFactory)
|
|
t.InjectComponent(&d2components.Size{}, &t.Components.Size.ComponentFactory)
|
|
t.InjectComponent(&d2components.Rectangle{}, &t.Components.Rectangle.ComponentFactory)
|
|
}
|
|
|
|
func (t *ShapeSystem) setupSubscriptions() {
|
|
shapesToRender := t.NewComponentFilter().
|
|
RequireOne(&d2components.Rectangle{}).
|
|
Require(&d2components.Texture{}).
|
|
Build()
|
|
|
|
shapesToUpdate := t.NewComponentFilter().
|
|
RequireOne(&d2components.Rectangle{}).
|
|
Require(&d2components.Transform{}, &d2components.Size{}).
|
|
Build()
|
|
|
|
t.shapesToRender = t.AddSubscription(shapesToRender)
|
|
t.shapesToUpdate = t.AddSubscription(shapesToUpdate)
|
|
}
|
|
|
|
// Update processes the load queue which attempting to create spriteations, as well as
|
|
// binding existing spriteations to a renderer if one is present.
|
|
func (t *ShapeSystem) Update() {
|
|
for _, id := range t.shapesToUpdate.GetEntities() {
|
|
t.updateShape(id)
|
|
}
|
|
|
|
for _, id := range t.shapesToRender.GetEntities() {
|
|
t.renderShape(id)
|
|
}
|
|
}
|
|
|
|
// ComponentFactory queues a sprite spriteation to be loaded
|
|
func (t *ShapeSystem) Rectangle(x, y, width, height int, color color.Color) akara.EID {
|
|
t.Debug("creating rectangle")
|
|
|
|
eid := t.NewEntity()
|
|
r := t.Components.Rectangle.Add(eid)
|
|
|
|
r.X, r.Y = float64(x), float64(y)
|
|
r.Width, r.Height = float64(width), float64(height)
|
|
|
|
c := t.Components.Color.Add(eid)
|
|
c.Color = color
|
|
|
|
texture := t.Components.Texture.Add(eid)
|
|
texture.Texture = t.RenderSystem.renderer.NewSurface(width, height)
|
|
texture.Texture.Clear(c.Color)
|
|
|
|
return eid
|
|
}
|
|
|
|
func (t *ShapeSystem) updateShape(eid akara.EID) {
|
|
transform, found := t.Components.Transform.Get(eid)
|
|
if !found {
|
|
return
|
|
}
|
|
|
|
size, found := t.Components.Size.Get(eid)
|
|
if !found {
|
|
return
|
|
}
|
|
|
|
texture, found := t.Components.Texture.Get(eid)
|
|
if !found || texture.Texture == nil {
|
|
return
|
|
}
|
|
|
|
rectangle, rectangleFound := t.Components.Rectangle.Get(eid)
|
|
if rectangleFound {
|
|
transform.Translation.X, transform.Translation.Y = rectangle.X, rectangle.Y
|
|
size.X, size.Y = rectangle.Width, rectangle.Height
|
|
|
|
tw, th := texture.Texture.GetSize()
|
|
if tw != int(size.X) || th != int(size.Y) {
|
|
texture.Texture.Renderer().NewSurface(int(size.X), int(size.Y))
|
|
}
|
|
}
|
|
}
|
|
|
|
func (t *ShapeSystem) renderShape(eid akara.EID) {
|
|
texture, found := t.Components.Texture.Get(eid)
|
|
if !found || texture.Texture == nil {
|
|
return
|
|
}
|
|
|
|
col, found := t.Components.Color.Get(eid)
|
|
if !found {
|
|
return
|
|
}
|
|
|
|
texture.Texture.Clear(col.Color)
|
|
}
|