diff --git a/cmd/test/debug.go b/cmd/test/debug.go index d5205ae..8b3419a 100644 --- a/cmd/test/debug.go +++ b/cmd/test/debug.go @@ -8,8 +8,7 @@ import ( ) type Debug struct { - gg.Visibility - gg.Layer + gg.Object } func (d *Debug) Draw(c *Context) { diff --git a/cmd/test/main.go b/cmd/test/main.go index 921db7b..855b25e 100644 --- a/cmd/test/main.go +++ b/cmd/test/main.go @@ -46,10 +46,10 @@ func main() { player = NewPlayer() tri = NewTri() - e.Add(&Debug{}) - e.Add(player) - e.Add(rect) - e.Add(tri) + e.Spawn(&Debug{}) + e.Spawn(player) + e.Spawn(rect) + e.Spawn(tri) fmt.Println(rect.GetLayer(), player.GetLayer()) err = e.Run() diff --git a/cmd/test/player.go b/cmd/test/player.go index c3252ce..e3f83db 100644 --- a/cmd/test/player.go +++ b/cmd/test/player.go @@ -11,7 +11,6 @@ type Player struct { gg.Sprite MoveSpeed gg.Float ScaleSpeed gg.Float - gg.Layer } func NewPlayer() *Player { diff --git a/cmd/test/rect.go b/cmd/test/rect.go index 649d7ff..7a70fdc 100644 --- a/cmd/test/rect.go +++ b/cmd/test/rect.go @@ -4,7 +4,6 @@ import "vultras.su/core/gg" type Rect struct { gg.DrawableRectangle - gg.Layer } func NewRect() *Rect { @@ -17,6 +16,7 @@ func NewRect() *Rect { gg.MaxColorV, } ret.Layer = RectL + ret.Visible = true return ret } diff --git a/cmd/test/trianlge.go b/cmd/test/trianlge.go index e74b455..71abbd3 100644 --- a/cmd/test/trianlge.go +++ b/cmd/test/trianlge.go @@ -5,7 +5,7 @@ import "fmt" type Tri struct { gg.DrawablePolygon - gg.Layer + Spawned bool } func NewTri() *Tri { @@ -34,6 +34,10 @@ func (t *Tri) Update(c *Context) { t.Color = gg.Rgba(1, 0, 1, 1) } + /*if t.Spawned { + return + }*/ + d := +1. if c.IsPressed(gg.KeyShift) { d = -1. @@ -55,15 +59,25 @@ func (t *Tri) Update(c *Context) { func (t *Tri) Event(c *Context) { switch e := c.Event.(type) { case *gg.KeyDown: - if e.Key != gg.Key1 { - break - } - if t.Connected() { - fmt.Println("disconnecting:", tri.Transform) - t.Disconnect() - } else { - t.Connect(player) - fmt.Println("connecting:", tri.Transform) + fmt.Println(e) + switch e.Key { + case gg.Key1 : + if t.Connected() { + fmt.Println("disconnecting:", tri.Transform) + t.Disconnect() + } else { + t.Connect(player) + fmt.Println("connecting:", tri.Transform) + } + case gg.Key2 : + if t.Spawned { + return + } + fmt.Println("shit") + tt := *t + tt.Spawned = true + tt.Disconnect() + c.Spawn(&tt) } } } diff --git a/context.go b/context.go index 749a18f..926a687 100644 --- a/context.go +++ b/context.go @@ -1,6 +1,17 @@ package gg +type contextType int +const ( + startContext contextType = iota + updateContext + eventContext + drawContext + deleteContext +) + type Context struct { + typ contextType + events []any *Engine *Image Event any diff --git a/engine.go b/engine.go index 94f321c..6320f93 100644 --- a/engine.go +++ b/engine.go @@ -47,7 +47,7 @@ type Engine struct { // The main holder for objects. // Uses the map structure to quickly // delete and create new objects. - Objects maps.Map[Object, struct{}] + Objects maps.Map[Objecter, struct{}] // The main camera to display in window. // If is set to nil then the engine will panic. @@ -64,6 +64,7 @@ type Engine struct { wheel Vector cursorPos Vector outerEvents, handleEvents EventChan + wg sync.WaitGroup } type engine Engine @@ -102,7 +103,7 @@ func NewEngine( ret.Camera = ret.NewCamera() ret.outerEvents = make(EventChan) ret.handleEvents = make(EventChan) - ret.Objects = maps.NewOrdered[Object, struct{}]() + ret.Objects = maps.NewOrdered[Objecter, struct{}]() ret.buttons = MouseButtonMap{} return ret } @@ -125,42 +126,42 @@ func (e *Engine) EventInput() EventChan { // Add new object considering what // interfaces it implements. -func (e *Engine) Add(b any) error { - object, _ := b.(Object) - if e.Objects.Has(object) { +func (e *Engine) Spawn(b Objecter) error { + if e.Objects.Has(b) { return ObjectExistErr } - /*o, ok := e.makeObject(b) - if !ok { - return ObjectNotImplementedErr - }*/ - starter, ok := b.(Starter) - if ok { - starter.Start(&Context{ - Engine: e, - }) - } - - e.Objects.Set(object, struct{}{}) + b.Start(&Context{Engine: e}) + obj := b.GetObject() + obj.input = make(chan *Context) + go func() { + for c := range obj.input { + switch c.typ { + case updateContext: + b.Update(c) + case eventContext: + for _, event := range c.events { + b.Event(&Context{ + Engine: e, + Event: event, + }) + } + } + e.wg.Done() + } + }() + e.Objects.Set(b, struct{}{}) return nil } // Delete object from Engine. -func (e *Engine) Del(b any) error { - object, _ := b.(Object) - if !e.Objects.Has(object) { +func (e *Engine) Del(b Objecter) error { + if !e.Objects.Has(b) { return ObjectNotExistErr } - deleter, ok := b.(Deleter) - if ok { - deleter.Delete(&Context{ - Engine: e, - }) - } - + b.Delete(&Context{Engine: e}) e.Objects.Del(b) return nil @@ -210,24 +211,16 @@ func (e *Engine) AbsCursorPosition() Vector { } func (e *engine) Update() error { - var wg sync.WaitGroup eng := (*Engine)(e) e.dt = time.Since(e.lastTime).Seconds() + // Buffering the context for faster. + c := &Context{Engine: eng, typ: updateContext} for object := range e.Objects.KeyChan() { - updater, ok := object.(Updater) - if !ok { - continue - } - wg.Add(1) - go func() { - updater.Update(&Context{ - Engine: eng, - }) - wg.Done() - }() + e.wg.Add(1) + object.Input() <- c } - wg.Wait() + e.wg.Wait() e.prevKeys = e.keys e.keys = inpututil. @@ -289,22 +282,12 @@ func (e *engine) Update() error { // Providing the events to the objects. // Maybe should think of the better way, // but for it is simple enough. + c = &Context{Engine: eng, typ: eventContext, events: events} for object := range e.Objects.KeyChan() { - eventer, ok := object.(Eventer) - if ok { - wg.Add(1) - go func() { - defer wg.Done() - for _, event := range events { - eventer.Event(&Context{ - Engine: eng, - Event: event, - }) - } - }() - } + e.wg.Add(1) + object.Input() <- c } - wg.Wait() + e.wg.Wait() e.lastTime = time.Now() return nil @@ -314,30 +297,27 @@ func (e *engine) Draw(i *ebiten.Image) { eng := (*Engine)(e) m := map[Layer][]Drawer{} for object := range eng.Objects.KeyChan() { - drawer, ok := object.(Drawer) - if !ok { + // Skipping the ones we do not need to draw. + if !object.IsVisible() { continue } - - l := drawer.GetLayer() + l := object.GetLayer() layer, ok := m[l] // Create new if has no the layer if !ok { - m[l] = []Drawer{drawer} + m[l] = []Drawer{object} continue } - m[l] = append(layer, drawer) + m[l] = append(layer, object) } // Drawing layers. layers := maps.NewSparse[Layer, []Drawer](nil, m) + c := &Context{Engine: eng, typ: drawContext, Image: i} for layer := range layers.Chan() { for _, drawer := range layer { - drawer.Draw(&Context{ - Engine: eng, - Image: i, - }) + drawer.Draw(c) } } // Empty the buff to generate it again. diff --git a/object.go b/object.go index 4e7a1ae..f1d6a84 100644 --- a/object.go +++ b/object.go @@ -1,11 +1,5 @@ package gg -// Implementing the interface lets the object -// to handle emited events. -type Eventer interface { - Event(*Context) -} - // Implementing the interface type // will call the function OnStart // when first appear on scene BEFORE @@ -22,6 +16,12 @@ type Updater interface { Update(*Context) } +// Implementing the interface lets the object +// to handle emited events. +type Eventer interface { + Event(*Context) +} + // Implementing the interface type // will call the function on deleting // the object. @@ -51,6 +51,29 @@ type Drawer interface { IsVisible() bool } -// The type represents everything that can work inside engine. -type Object any +type Objecter interface { + GetObject() *Object + Input() chan *Context + Starter + Updater + Eventer + Drawer + Deleter +} + +// The type for embedding into engine-in types. +type Object struct { + Layer + Visibility + input chan *Context +} + +func (o *Object) GetObject() *Object { return o } +func (o *Object) Input() chan *Context { return o.input } + +func (o *Object) Start(c *Context) {} +func (o *Object) Update(c *Context) {} +func (o *Object) Event(c *Context) {} +func (o *Object) Draw(c *Context) {} +func (o *Object) Delete(c *Context) {} diff --git a/polygon.go b/polygon.go index 3decfb5..11d7eac 100644 --- a/polygon.go +++ b/polygon.go @@ -5,6 +5,7 @@ import ( // Grouped triangles type. type Polygon struct { + Object Transform Triangles } diff --git a/rect.go b/rect.go index 59887fa..3392601 100644 --- a/rect.go +++ b/rect.go @@ -9,6 +9,7 @@ import ( // The type describes rectangle geometry. type Rectangle struct { + Object Transform } diff --git a/sprite.go b/sprite.go index cc5d887..c747263 100644 --- a/sprite.go +++ b/sprite.go @@ -6,6 +6,7 @@ import ( ) type Sprite struct { + Object Transform ShaderOptions Floating bool @@ -52,7 +53,9 @@ func (s *Sprite) Rectangle() Rectangle { t.Around.X *= Float(w) t.Around.Y *= Float(h) - return Rectangle{t} + return Rectangle{ + Transform: t, + } } // Get triangles of the rectangle that contains the sprite diff --git a/vector.go b/vector.go index 5ad417e..99a5299 100644 --- a/vector.go +++ b/vector.go @@ -92,7 +92,7 @@ func (v Vector) Norm() Vector { } func (pts Points) Contained(c PointContainer) Points { - ret := Points{} + ret := make([]Point, 0, len(pts)) for _, pt := range pts { if c.ContainsPoint(pt) {