diff --git a/camera.go b/camera.go index 1b3594b..18d2c80 100644 --- a/camera.go +++ b/camera.go @@ -4,6 +4,7 @@ package gg // for the main window. type Camera struct { Transform + buf *Matrix } // Returns the matrix satysfying camera @@ -12,22 +13,24 @@ type Camera struct { // transform to display on the screen. // (Should implement buffering it so we do not // need to calculate it each time for each object. ) -func (c *Camera)RealMatrix( - e *Engine, -) Matrix { +func (c *Camera)RealMatrix() Matrix { g := &Matrix{} g.Translate(-c.P.X, -c.P.Y) g.Rotate(c.R) g.Scale(c.S.X, c.S.Y) g.Translate(c.RA.X, c.RA.Y) + c.buf = g + return *g } -func (c *Camera) AbsMatrix( - e *Engine, -) Matrix { - m := c.RealMatrix(e) +// The matrix to convert things into the +// inside engine representation, +// get the position of cursor inside the world +// basing on its window position. +func (c *Camera) AbsMatrix() Matrix { + m := c.RealMatrix() m.Invert() return m } diff --git a/cmd/test/main.go b/cmd/test/main.go index c1323a0..d155262 100644 --- a/cmd/test/main.go +++ b/cmd/test/main.go @@ -11,6 +11,8 @@ import ( "math/rand" ) +type Context = gg.Context + const ( HighestL gg.Layer = -iota DebugL @@ -28,6 +30,7 @@ type Player struct { } type Debug struct { + gg.Visibility gg.Layer } @@ -98,11 +101,15 @@ func NewRect() *Rect { return ret } -func (r *Rect) Update(e *gg.Engine) error { +func (r *Rect) Update(c *Context) error { //r.R += 0.3 * e.DT() + r.P = c.AbsCursorPosition() return nil } +func (r *Rect) Event(c *Context) { +} + var ( playerImg *gg.Image player *Player @@ -134,8 +141,8 @@ func NewPlayer() *Player { return ret } -func (p *Player) Draw(e *gg.Engine, i *gg.Image) { - p.Sprite.Draw(e, i) +func (p *Player) Draw(c *Context) { + p.Sprite.Draw(c) t := p.Transform t.S.X *= 4. t.S.Y *= 4. @@ -146,31 +153,31 @@ func (p *Player) Draw(e *gg.Engine, i *gg.Image) { Rectangle: rectMove, Color: gg.Color{0, 0, gg.MaxColorV, gg.MaxColorV}, } - r.Draw(e, i) + r.Draw(c) } -func (p *Player) Start(e *gg.Engine, v ...any) { +func (p *Player) Start(c *Context) { fmt.Println("starting") - c := e.Camera() - c.RA = gg.V(360, 240) + cam := c.Camera() + cam.RA = gg.V(360, 240) } -func (p *Player) Update(e *gg.Engine) error { - dt := e.DT() - c := e.Camera() - keys := e.Keys() +func (p *Player) Update(c *Context) error { + dt := c.DT() + cam := c.Camera() + keys := c.Keys() p.Uniforms["Random"] = any(rand.Float32()) for _, v := range keys { switch v { case ebiten.KeyArrowUp: - c.P.Y += p.MoveSpeed * dt + cam.P.Y += p.MoveSpeed * dt case ebiten.KeyArrowLeft: - c.P.X -= p.MoveSpeed * dt + cam.P.X -= p.MoveSpeed * dt case ebiten.KeyArrowDown: - c.P.Y -= p.MoveSpeed * dt + cam.P.Y -= p.MoveSpeed * dt case ebiten.KeyArrowRight: - c.P.X += p.MoveSpeed * dt + cam.P.X += p.MoveSpeed * dt case ebiten.KeyW: p.P.Y += p.MoveSpeed * dt case ebiten.KeyA: @@ -180,61 +187,61 @@ func (p *Player) Update(e *gg.Engine) error { case ebiten.KeyD: p.P.X += p.MoveSpeed * dt case ebiten.KeyR: - c.R += gg.Pi * p.ScaleSpeed * dt + cam.R += gg.Pi * p.ScaleSpeed * dt case ebiten.KeyT: - c.R -= gg.Pi * p.ScaleSpeed * dt + cam.R -= gg.Pi * p.ScaleSpeed * dt case ebiten.KeyRightBracket: - if e.IsPressed(ebiten.KeyShift) { + if c.IsPressed(gg.KeyShift) { p.R -= gg.Pi * 0.3 * dt } else { p.R += gg.Pi * 0.3 * dt } - case ebiten.KeyF: - if e.IsPressed(ebiten.KeyShift) { - c.S.X -= gg.Pi * p.ScaleSpeed * dt + case gg.KeyF: + if c.IsPressed(ebiten.KeyShift) { + cam.S.X -= gg.Pi * p.ScaleSpeed * dt } else { - c.S.X += gg.Pi * p.ScaleSpeed * dt + cam.S.X += gg.Pi * p.ScaleSpeed * dt } - case ebiten.KeyG: - if e.IsPressed(ebiten.KeyShift) { - c.S.Y -= gg.Pi * p.ScaleSpeed * dt + case gg.KeyG: + if c.IsPressed(ebiten.KeyShift) { + cam.S.Y -= gg.Pi * p.ScaleSpeed * dt } else { - c.S.Y += gg.Pi * p.ScaleSpeed * dt + cam.S.Y += gg.Pi * p.ScaleSpeed * dt } - case ebiten.KeyZ: - if e.IsPressed(ebiten.KeyShift) { - c.RA.X -= gg.Pi * p.MoveSpeed * dt + case gg.KeyZ: + if c.IsPressed(ebiten.KeyShift) { + cam.RA.X -= gg.Pi * p.MoveSpeed * dt } else { - c.RA.X += gg.Pi * p.MoveSpeed * dt + cam.RA.X += gg.Pi * p.MoveSpeed * dt } - case ebiten.KeyX: - if e.IsPressed(ebiten.KeyShift) { - c.RA.Y -= gg.Pi * p.MoveSpeed * dt + case gg.KeyX: + if c.IsPressed(ebiten.KeyShift) { + cam.RA.Y -= gg.Pi * p.MoveSpeed * dt } else { - c.RA.Y += gg.Pi * p.MoveSpeed * dt + cam.RA.Y += gg.Pi * p.MoveSpeed * dt } - case ebiten.KeyV: - if e.IsPressed(ebiten.KeyShift) { + case gg.KeyV: + if c.IsPressed(ebiten.KeyShift) { tri.R -= gg.Pi * 0.3 * dt } else { tri.R += gg.Pi * 0.3 * dt } - case ebiten.KeyLeftBracket: - if e.IsPressed(ebiten.KeyShift) { + case gg.KeyLeftBracket: + if c.IsPressed(ebiten.KeyShift) { rect.R -= gg.Pi * 0.3 * dt } else { rect.R += gg.Pi * 0.3 * dt } - case ebiten.Key0: - e.Del(p) - case ebiten.KeyB: + case gg.Key0: + c.Del(p) + case gg.KeyB: } } return nil } -func (p *Player) Event(e *gg.Engine, ev any) { +func (p *Player) Signal(e *gg.Engine, ev any) { fmt.Println("event:", ev) switch ec := ev.(type) { case *gg.KeyDown: @@ -249,10 +256,8 @@ func (p *Player) Event(e *gg.Engine, ev any) { } } -func (d *Debug) Draw( - e *gg.Engine, - i *gg.Image, -) { +func (d *Debug) Draw(c *Context) { + e := c.Engine keyStrs := []string{} for _, k := range e.Keys() { keyStrs = append(keyStrs, k.String()) @@ -270,7 +275,7 @@ func (d *Debug) Draw( keyStrs = append(keyStrs, fmt.Sprintf("%v", e.CursorPosition())) keyStrs = append(keyStrs, fmt.Sprintf("%v", e.AbsCursorPosition())) - e.DebugPrint(i, + e.DebugPrint(c.Image, strings.Join(keyStrs, ", ")) } diff --git a/context.go b/context.go new file mode 100644 index 0000000..749a18f --- /dev/null +++ b/context.go @@ -0,0 +1,7 @@ +package gg + +type Context struct { + *Engine + *Image + Event any +} diff --git a/engine.go b/engine.go index dbbba1e..3bfdf78 100644 --- a/engine.go +++ b/engine.go @@ -96,7 +96,9 @@ func (e *Engine) Add(b any) error { starter, ok := b.(Starter) if ok { - starter.Start(e) + starter.Start(&Context{ + Engine: e, + }) } e.objects.Set(object, struct{}{}) @@ -113,7 +115,9 @@ func (e *Engine) Del(b any) error { deleter, ok := b.(Deleter) if ok { - deleter.Delete(e) + deleter.Delete(&Context{ + Engine: e, + }) } e.objects.Del(b) @@ -152,14 +156,19 @@ func (e *engine) Update() error { eventer, ok := object.(Eventer) if ok { for _, event := range events { - eventer.Event(eng, event) + eventer.Event(&Context{ + Engine: eng, + Event: event, + }) } } updater, ok := object.(Updater) if !ok { continue } - err = updater.Update(eng) + err = updater.Update(&Context{ + Engine: eng, + }) if err != nil { return err } @@ -193,7 +202,10 @@ func (e *engine) Draw(i *ebiten.Image) { layers := maps.NewSparse[Layer, []Drawer](nil, m) for layer := range layers.Chan() { for _, drawer := range layer { - drawer.Draw(eng, i) + drawer.Draw(&Context{ + Engine: eng, + Image: i, + }) } } } diff --git a/event.go b/event.go index f645849..cd11f41 100644 --- a/event.go +++ b/event.go @@ -4,10 +4,6 @@ import ( //"github.com/hajimehoshi/ebiten/v2" ) -type Eventer interface { - Event(e *Engine, ev any) -} - func keyDiff(s1, s2 []Key) []Key { combinedSlice := append(s1, s2...) dm := make(map[Key]int) @@ -37,7 +33,6 @@ type KeyUp struct { Key } - type MouseButtonDown struct { MouseButton P Vector diff --git a/line.go b/line.go index 35b793a..5068fc2 100644 --- a/line.go +++ b/line.go @@ -2,7 +2,7 @@ package gg import ( "math" - "fmt" + //"fmt" ) // The type represents mathematical equation of line and line itself. diff --git a/mouse.go b/mouse.go index bedb13a..3574c31 100644 --- a/mouse.go +++ b/mouse.go @@ -13,7 +13,7 @@ func (e *Engine) CursorPosition() Vector { func (e *Engine) AbsCursorPosition() Vector { m := &Matrix{} - m.Concat(e.Camera().AbsMatrix(e)) + m.Concat(e.Camera().AbsMatrix()) return e.CursorPosition().Apply(m) } diff --git a/object.go b/object.go index b7a1527..ee1b747 100644 --- a/object.go +++ b/object.go @@ -1,28 +1,35 @@ 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 // the OnUpdate. // The v value will be get from Add function. type Starter interface { - Start(*Engine) + Start(*Context) } // Implementing the interface type // will call the function on each // engine iteration. type Updater interface { - Update(*Engine) error + Update(*Context) error } // Implementing the interface type // will call the function on deleting // the object. type Deleter interface { - Delete(*Engine, ...any) + Delete(*Context) } +// Feat to embed for turning visibility on and off. type Visibility struct { Visible bool } @@ -30,15 +37,16 @@ func (v Visibility) IsVisible() bool { return v.Visible } +// Feat to embed to make colorful objects. type Colority struct { Color Color } // The interface describes anything that can be // drawn. It will be drew corresponding to -// the layers order. +// the layers order so the layer must be returned. type Drawer interface { - Draw(*Engine, *Image) + Draw(*Context) GetLayer() Layer IsVisible() bool } diff --git a/polygon.go b/polygon.go index ce4cc9b..d5b5a6f 100644 --- a/polygon.go +++ b/polygon.go @@ -38,15 +38,12 @@ func (p *Polygon) MakeTriangles() Triangles { return ret } -func (p *DrawablePolygon) Draw( - e *Engine, - i *Image, -) { +func (p *DrawablePolygon) Draw(c *Context) { (&DrawableTriangles{ Visibility: p.Visibility, Colority: p.Colority, ShaderOptions: p.ShaderOptions, Triangles: p.MakeTriangles(), - }).Draw(e, i) + }).Draw(c) } diff --git a/rect.go b/rect.go index cfcff88..a27434c 100644 --- a/rect.go +++ b/rect.go @@ -73,12 +73,9 @@ func (r *DrawableRectangle) IsVisible() bool { return r.Visible } -func (r *DrawableRectangle) Draw( - e *Engine, - i *Image, -) { +func (r *DrawableRectangle) Draw(c *Context) { m := r.Matrix() - rm := e.Camera().RealMatrix(e) + rm := c.Camera().RealMatrix() m.Concat(rm) // Draw solid color if no shader. if r.Shader == nil { @@ -89,7 +86,7 @@ func (r *DrawableRectangle) Draw( opts := &ebiten.DrawImageOptions{ GeoM: m, } - i.DrawImage(img, opts) + c.DrawImage(img, opts) return } @@ -117,6 +114,6 @@ func (r *DrawableRectangle) Draw( Images: r.Images, Uniforms: r.Uniforms, } - i.DrawRectShader(w, h, r.Shader, opts) + c.DrawRectShader(w, h, r.Shader, opts) } diff --git a/sprite.go b/sprite.go index c383368..d98dffa 100644 --- a/sprite.go +++ b/sprite.go @@ -10,10 +10,7 @@ type Sprite struct { Floating, Visible bool } -func (s *Sprite) Draw( - e *Engine, - i *Image, -) { +func (s *Sprite) Draw(c *Context) { // Nothing to draw. if s.Images[0] == nil { return @@ -23,16 +20,14 @@ func (s *Sprite) Draw( m := &Matrix{} m.Concat(t.Matrix()) if !s.Floating { - m.Concat(e.Camera().RealMatrix( - e, - )) + m.Concat(c.Camera().RealMatrix()) } // Drawing without shader. if s.Shader == nil { opts := &ebiten.DrawImageOptions{} opts.GeoM = *m - i.DrawImage(s.Images[0], opts) + c.DrawImage(s.Images[0], opts) return } @@ -43,7 +38,7 @@ func (s *Sprite) Draw( Uniforms: s.Uniforms, GeoM: *m, } - i.DrawRectShader(w, h, s.Shader, opts) + c.DrawRectShader(w, h, s.Shader, opts) } // Check is sprite is visible. diff --git a/triangle.go b/triangle.go index 282db5b..42c24f3 100644 --- a/triangle.go +++ b/triangle.go @@ -88,11 +88,8 @@ func (ts Triangles) ContainsPoint(p Point) bool { return false } -func (r *DrawableTriangles) Draw( - e *Engine, - i *Image, -) { - m := e.Camera().RealMatrix(e) +func (r *DrawableTriangles) Draw(c *Context) { + m := c.Camera().RealMatrix() cm := &m // Draw solid color if no shader. @@ -115,7 +112,7 @@ func (r *DrawableTriangles) Draw( img := NewImage(1, 1) img.Set(0, 0, r.Color) - i.DrawTriangles(vs, is, img, &r.DrawTrianglesOptions) + c.DrawTriangles(vs, is, img, &r.DrawTrianglesOptions) return } diff --git a/vector.go b/vector.go index e369896..0d0a678 100644 --- a/vector.go +++ b/vector.go @@ -14,10 +14,6 @@ type Point = Vector type Vectors []Vector type Points []Point -type PointContainer interface { - ContainsPoint(Point) bool -} - func V(x, y Float) Vector { return Vector{x, y} }