From 80e5cb20f84d5929fff60901a4c44268b08d7c82 Mon Sep 17 00:00:00 2001 From: Marvin Blum Date: Sat, 7 May 2016 11:28:42 +0200 Subject: [PATCH] Removed Add() method from System interface, added 2D culling. --- culling.go | 99 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ game.go | 13 ++++++- sprite.go | 22 +++++------- system.go | 30 ++--------------- 4 files changed, 123 insertions(+), 41 deletions(-) create mode 100644 culling.go diff --git a/culling.go b/culling.go new file mode 100644 index 0000000..ec562ed --- /dev/null +++ b/culling.go @@ -0,0 +1,99 @@ +package goga + +import ( + "log" +) + +const ( + culling_2d_name = "culling2d" +) + +type Cullable struct { + *Actor + *Pos2D +} + +type Culling2D struct { + cullables []Cullable + viewport Vec4 +} + +// Creates a new sprite culling system. +// To update the viewport, call SetViewport(). +func NewCulling2D(x, y, width, height int) *Culling2D { + culling := &Culling2D{} + culling.cullables = make([]Cullable, 0) + culling.viewport = Vec4{float64(x), float64(y), float64(width), float64(height)} + + return culling +} + +// Sets the culling outer bounds. +// Actors outside of this box won't be rendered. +func (c *Culling2D) SetViewport(x, y, width, height int) { + c.viewport = Vec4{float64(x), float64(y), float64(width), float64(height)} +} + +func (c *Culling2D) Cleanup() {} + +// Adds actor with Pos2D to the system. +func (c *Culling2D) Add(actor *Actor, pos *Pos2D) bool { + id := actor.GetId() + + for _, cull := range c.cullables { + if id == cull.Actor.GetId() { + return false + } + } + + c.cullables = append(c.cullables, Cullable{actor, pos}) + + return true +} + +// Removes actor with Pos2D from system. +func (c *Culling2D) Remove(actor *Actor) bool { + return c.RemoveById(actor.GetId()) +} + +// Removes actor with Pos2D from system by ID. +func (c *Culling2D) RemoveById(id ActorId) bool { + for i, cull := range c.cullables { + if cull.GetId() == id { + c.cullables = append(c.cullables[:i], c.cullables[i+1:]...) + return true + } + } + + return false +} + +// Removes all cullable objects. +func (c *Culling2D) RemoveAll() { + c.cullables = make([]Cullable, 0) +} + +// Returns number of cullable objects. +func (c *Culling2D) Len() int { + return len(c.cullables) +} + +func (c *Culling2D) GetName() string { + return culling_2d_name +} + +// Updates visibility of all contained sprites. +func (c *Culling2D) Update(delta float64) { + for i := range c.cullables { + if c.cullables[i].Pos.X > c.viewport.Z || + c.cullables[i].Pos.X+c.cullables[i].Size.X < c.viewport.X || + c.cullables[i].Pos.Y > c.viewport.W || + c.cullables[i].Pos.Y+c.cullables[i].Size.Y < c.viewport.Y { + c.cullables[i].Visible = false + log.Print("h") + } else { + c.cullables[i].Visible = true + log.Print("s") + } + } +} diff --git a/game.go b/game.go index 8a8f7ea..15b00de 100644 --- a/game.go +++ b/game.go @@ -227,6 +227,7 @@ func initGoga(width, height int) { EnableAlphaBlending(true) AddLoader(&PngLoader{gl.LINEAR, false}) AddSystem(NewSpriteRenderer(nil, nil, false)) + AddSystem(NewCulling2D(0, 0, width, height)) } func cleanup() { @@ -296,13 +297,23 @@ func EnableAlphaBlending(enable bool) { } } -// Sets GL viewport. +// Sets GL viewport and updates default resources and systems. func SetViewport(x, y, width, height int32) { viewportWidth = int(width) viewportHeight = int(height) + DefaultCamera.SetViewport(int(x), int(y), viewportWidth, viewportHeight) DefaultCamera.CalcRatio() DefaultCamera.CalcOrtho() + + if culling2d := GetSystemByName(culling_2d_name); culling2d != nil { + system, ok := culling2d.(*Culling2D) + + if ok { + system.SetViewport(int(x), int(y), viewportWidth, viewportHeight) + } + } + gl.Viewport(x, y, width, height) } diff --git a/sprite.go b/sprite.go index a9426c7..2d1c3e1 100644 --- a/sprite.go +++ b/sprite.go @@ -87,27 +87,23 @@ func (s *SpriteRenderer) Cleanup() { } // Adds sprite to the renderer. -func (s *SpriteRenderer) Add(actor interface{}) bool { - sprite, ok := actor.(*Sprite) +func (s *SpriteRenderer) Add(actor *Actor, pos *Pos2D, tex *Tex) bool { + id := actor.GetId() - if !ok { - return false + for _, sprite := range s.sprites { + if id == sprite.Actor.GetId() { + return false + } } - s.sprites = append(s.sprites, *sprite) + s.sprites = append(s.sprites, Sprite{actor, pos, tex}) return true } // Removes sprite from renderer. -func (s *SpriteRenderer) Remove(actor interface{}) bool { - sprite, ok := actor.(*Sprite) - - if !ok { - return false - } - - return s.RemoveById(sprite.Actor.GetId()) +func (s *SpriteRenderer) Remove(actor *Actor) bool { + return s.RemoveById(actor.GetId()) } // Removes sprite from renderer by ID. diff --git a/system.go b/system.go index 3cf12c3..f80c793 100644 --- a/system.go +++ b/system.go @@ -10,8 +10,7 @@ import () type System interface { Update(float64) Cleanup() - Add(interface{}) bool - Remove(interface{}) bool + Remove(*Actor) bool RemoveById(ActorId) bool RemoveAll() Len() int @@ -76,34 +75,11 @@ func updateSystems(delta float64) { } } -// Takes an actor and tries to add it to all systems that accept it. -// This maybe not as performant as directly adding it to the right system. -// Returns true if it could be added to at least one system, else false. -func AddActor(actor interface{}) bool { - accepted := false - - for _, system := range systems { - if system.Add(actor) { - accepted = true - } - } - - return accepted -} - // Removes an actor from all systems. // This maybe not as performant as directly removing it from the right system. // Returns true if it could be removed from at least one system, else false. -func RemoveActor(actor interface{}) bool { - removed := false - - for _, system := range systems { - if system.Remove(actor) { - removed = true - } - } - - return removed +func RemoveActor(actor *Actor) bool { + return RemoveActorById(actor.GetId()) } // Removes an actor from all systems by ID.