From b479bf1988d4d5d5de06457d6c2517d96b5d7b0f Mon Sep 17 00:00:00 2001 From: surdeus Date: Thu, 18 Jan 2024 06:06:27 +0300 Subject: [PATCH] save --- camera.go | 17 ++-- circle.go | 5 +- cmd/test/debug.go | 17 ++-- cmd/test/player.go | 29 +++--- engine.go | 2 +- rect.go | 2 +- sprite.go | 7 +- transform.go | 220 ++++++++++++++++++++++++++++++--------------- vector.go | 14 ++- 9 files changed, 208 insertions(+), 105 deletions(-) diff --git a/camera.go b/camera.go index bb98d9f..f684ff8 100644 --- a/camera.go +++ b/camera.go @@ -29,11 +29,18 @@ func (c *Camera)RealMatrix() Matrix { return c.buf } g := Matrix{} - g.Translate(-c.Position.X, -c.Position.Y) - g.Rotate(c.Rotation) - siz := c.engine.AbsWinSize() - g.Translate(c.Around.X * siz.X, c.Around.Y * siz.Y) - g.Scale(c.Scale.X, c.Scale.Y) + position := c.Position().Neg() + around := c.Around() + scale := c.Scale() + rotation := c.Rotation() + + g.Translate(-position.X, -position.Y) + g.Rotate(rotation) + + size := c.engine.AbsWinSize() + g.Translate(around.X * size.X, around.Y * size.Y) + + g.Scale(scale.X, scale.Y) c.buf = g c.buffered = true diff --git a/circle.go b/circle.go index de242db..d35bde2 100644 --- a/circle.go +++ b/circle.go @@ -11,14 +11,15 @@ type Circle struct { Colority Antialiasity Layer + Radius Float } func (circle *Circle) Draw(c *Context) []EVertex { - rPos := circle.Position.Apply(c.Camera.RealMatrix()) + rPos := circle.Position().Apply(c.Camera.RealMatrix()) vector.DrawFilledCircle( c.Image, float32(rPos.X), float32(rPos.Y), - float32(circle.Rotation), + float32(circle.Radius), circle.Color, circle.Antialias, ) diff --git a/cmd/test/debug.go b/cmd/test/debug.go index 34669e3..a27ce84 100644 --- a/cmd/test/debug.go +++ b/cmd/test/debug.go @@ -13,6 +13,9 @@ type Debug struct { func (d *Debug) Draw(c *Context) []gg.EVertex { e := c.Engine + relTri := tri.Rel() + relPlayer := player.Rel() + keyStrs := []string{} keyStrs = append(keyStrs, fmt.Sprintf( "counter: %d", counter, @@ -30,20 +33,20 @@ func (d *Debug) Draw(c *Context) []gg.EVertex { "frame: %d", int(c.Frame()), )) keyStrs = append(keyStrs, fmt.Sprintf( - "relPlayerPos: %v", player.Position, + "relPlayerPos: %v", relPlayer.Position(), )) keyStrs = append(keyStrs, fmt.Sprintf( - "absPlayerPos: %v", player.AbsPosition(), + "absPlayerPos: %v", player.Position(), )) keyStrs = append(keyStrs, fmt.Sprintf( - "relTriPos: %v", tri.Position, + "relTriPos: %v", tri.Position(), )) keyStrs = append(keyStrs, fmt.Sprintf( - "absTriPos: %v", tri.AbsPosition(), + "absTriPos: %v", relTri.Position(), )) keyStrs = append(keyStrs, fmt.Sprintf( - "absTriRot: %v", gg.Degree(tri.AbsRotation()), + "absTriRot: %v", gg.Degree(tri.Rotation()), )) keys := []string{} @@ -71,8 +74,8 @@ func (d *Debug) Draw(c *Context) []gg.EVertex { keyStrs = append(keyStrs, fmt.Sprintf( "camera position: %v %v", - c.Camera.Position.X, - c.Camera.Position.Y, + c.Camera.Position().X, + c.Camera.Position().Y, )) keyStrs = append(keyStrs, fmt.Sprintf("realCursorPos: %v", e.CursorPosition())) keyStrs = append(keyStrs, fmt.Sprintf("absCursorPos: %v", e.AbsCursorPosition())) diff --git a/cmd/test/player.go b/cmd/test/player.go index 2b837d0..9f95de2 100644 --- a/cmd/test/player.go +++ b/cmd/test/player.go @@ -18,8 +18,8 @@ type Player struct { func NewPlayer() *Player { ret := &Player{} ret.Transform = gg.T() - ret.Scale = gg.V2(1) - ret.Around = gg.V2(.5) + ret.SetScale(gg.V2(1)) + ret.SetAround(gg.V2(.5)) ret.MoveSpeed = 40. ret.ScaleSpeed = .2 ret.Animations = playerAnimations @@ -48,7 +48,7 @@ func (p *Player) Draw(c *Context) []gg.EVertex { } func (p *Player) Update(c *Context) { - p.Position.Y += 2 + p.SetPosition(p.Position().Sub(gg.Y(2))) if p.Spawned { return } @@ -62,25 +62,30 @@ func (p *Player) Update(c *Context) { for _, v := range keys { switch v { case gg.KeyQ: - p.Scale = p.Scale.Add(gg.V(p.ScaleSpeed*dt, 0)) + p.SetScale( + p.Scale().Add( + gg.X(p.ScaleSpeed*dt), + ), + ) case gg.KeyArrowUp: - cam.Position.Y += p.MoveSpeed * dt - case gg.KeyArrowLeft: - cam.Position.X -= p.MoveSpeed * dt + cam.Move(gg.Y(-p.MoveSpeed * dt)) case gg.KeyArrowDown: - cam.Position.Y -= p.MoveSpeed * dt + cam.Move(gg.Y(p.MoveSpeed * dt)) + case gg.KeyArrowLeft: + cam.Move(gg.X(-p.MoveSpeed*dt)) case gg.KeyArrowRight: - cam.Position.X += p.MoveSpeed * dt + cam.Move(gg.X(p.MoveSpeed * dt)) case gg.KeyW: - p.Position.Y -= p.MoveSpeed * dt*10 + p.Move(gg.Y(p.MoveSpeed * dt*10)) walking = true p.Animate(Walk) case gg.KeyA: - p.Position.X -= p.MoveSpeed * dt - p.Scale.X = -1 + p.Move(gg.X(-MoveSpeed * dt)) + p.SetScale(gg.V(-1, 1) walking = true p.Animate(Walk) case gg.KeyS: + p.Move(gg.X(-MoveSpeed * dt)) p.Position.Y -= p.MoveSpeed * dt walking = true p.Animate(Walk) diff --git a/engine.go b/engine.go index 6cd1bd7..e4496fa 100644 --- a/engine.go +++ b/engine.go @@ -145,7 +145,7 @@ func (c *Engine) RealWinSize() Vector { } func (c *Engine) AbsWinSize() Vector { - return c.RealWinSize().Div(c.Camera.Scale) + return c.RealWinSize().Div(c.Camera.Scale()) } func (e *Engine) EventInput() EventChan { diff --git a/rect.go b/rect.go index 7badbc5..e4191cd 100644 --- a/rect.go +++ b/rect.go @@ -19,7 +19,7 @@ type Rectangle struct { func (r Rectangle) Vertices() Vertices { t := r.Transform wh := V(r.Width, r.Height) - t.Around = t.Around.Scale(wh) + t.SetAround(t.Around().Mul(wh)) m := t.Matrix() p1 := V(0, 0).Apply(m) p2 := V(wh.X, 0).Apply(m) diff --git a/sprite.go b/sprite.go index e6f159b..dec4e10 100644 --- a/sprite.go +++ b/sprite.go @@ -55,8 +55,11 @@ func (s *Sprite) RectangleToDraw() Rectangle { w, h := s.Images[0].Size() t := s.Transform - t.Around.X *= Float(w) - t.Around.Y *= Float(h) + t.SetAround( + t.Around().Mul( + V(Float(w), Float(h)), + ), + ) return Rectangle{ Transform: t, diff --git a/transform.go b/transform.go index ca6d468..b20f947 100644 --- a/transform.go +++ b/transform.go @@ -6,7 +6,7 @@ import ( ) type Transformer interface { - GetTransform() Transform + GetTransform() *Transform } // The structure represents basic transformation @@ -14,18 +14,25 @@ type Transformer interface { type Transform struct { // Absolute (if no parent) position and // the scale. - Position, Scale Vector + position, scale Vector // The object rotation in radians. - Rotation Float + rotation Float // The not scaled offset vector from upper left corner // which the object should be rotated around. - Around Vector + around Vector + // If is not nil then the upper values will be relational to // the parent ones. - Parent Transformer + parent *Transform + + // Dirty is true if we anyhow changed matrix. + dirty, parentDirty bool + + matrix, parentMatrix, parentInverted Matrix } -func (t Transform) GetTransform() Transform { +// For implementing the Transformer on embedding. +func (t *Transform) GetTransform() *Transform { return t } @@ -33,121 +40,190 @@ func (t Transform) GetTransform() Transform { func T() Transform { ret := Transform{ // Rotate around - Scale: Vector{1, 1}, + scale: Vector{1, 1}, // Rotate around the center. - Around: V(.5, .5), + around: V(.5, .5), } return ret } -func (t *Transform) SetAbsPosition(absPosition Vector) { - if t.Parent == nil { - t.Position = absPosition +// Set the absolute object position. +func (t *Transform) SetPosition(position Vector) { + t.dirty = true + t.parentDirty = true + if t.parent == nil { + t.position = position return } - m := t.ParentMatrix() - m.Invert() - t.Position = absPosition.Apply(m) + + _, mi := t.parent.MatrixForParenting() + t.position = position.Apply(mi) +} + +// Set the absolute object rotation. +func (t *Transform) SetRotation(rotation Float) { + t.dirty = true + t.parentDirty = true + if t.parent == nil { + t.rotation = rotation + return + } + t.rotation -= t.parent.Rotation() +} + +// Set the absolute object scale. +func (t *Transform) SetScale(scale Vector) { + t.dirty = true + t.scale = scale +} + +func (t *Transform) SetAround(around Vector) { + t.dirty = true + t.around = around } // Get the absolute representation of the transform. -func (t Transform) Abs() Transform { - if t.Parent == nil { - return t +func (t *Transform) Abs() Transform { + if t.parent == nil { + return *t } ret := T() - ret.Position = t.AbsPosition() - ret.Rotation = t.AbsRotation() - ret.Scale = t.AbsScale() + ret.position = t.Position() + ret.rotation = t.Rotation() + + // Do not need that + // cause parent does not affect + // scaling. + // (Should think if scaling from parent + // can be used anyhow) + + //ret.scale = t.Scale() return ret } -func (t Transform) AbsPosition() Vector { - if t.Parent == nil { - return t.Position - } - return t.Position.Apply(t.ParentMatrix()) +func (t *Transform) Rel() Transform { + ret := *t + ret.parent = nil + return ret } -func (t Transform) AbsScale() Vector { - if t.Parent == nil { - return t.Scale +// Get the absolute object position. +func (t *Transform) Position() Vector { + if t.parent == nil { + return t.position } - return V2(1) + pm, _ := t.parent.MatrixForParenting() + return t.position.Apply(pm) } -func (t Transform) AbsRotation() Float { - if t.Parent == nil { - return t.Rotation - } - return t.Rotation + t.Parent.GetTransform().AbsRotation() +func (t *Transform) Move(v ...Vector) { + t.SetPosition(t.Position().Add(v...)) } -func (t *Transform) SetAbsRotation(rot Float) { - if t.Parent == nil { - t.Rotation = rot - } - t.Rotation -= t.Parent.GetTransform().AbsRotation() +// Get the absolute object scale. +func (t *Transform) Scale() Vector { + return t.scale } +// Get the absolute object rotation. +func (t *Transform) Rotation() Float { + if t.parent == nil { + return t.rotation + } + return t.rotation + t.parent.Rotation() +} +func (t *Transform) Around() Vector { + return t.around +} + +// Returns true if the object is connected +// to some parent. func (t *Transform) Connected() bool { - return t.Parent != nil + return t.parent != nil } +// Connect the object to another one making +// it its parent. func (t *Transform) Connect(parent Transformer) { - absPosition := t.AbsPosition() - absRotation := t.AbsRotation() - t.Parent = parent - t.SetAbsPosition(absPosition) - t.SetAbsRotation(absRotation) + absPosition := t.Position() + absRotation := t.Rotation() + t.parent = parent.GetTransform() + t.SetPosition(absPosition) + t.SetRotation(absRotation) } +// Disconnect from the parent. func (t *Transform) Disconnect() { - if t.Parent == nil { + if t.parent == nil { return } *t = t.Abs() } -func (t Transform) ParentMatrix() Matrix { - g := Matrix{} - if t.Parent == nil { - return g +// Return the matrix and the inverted one for parenting children. +func (t *Transform) MatrixForParenting() (Matrix, Matrix) { + var m, mi Matrix + + if t.parentDirty { + + m.Scale(t.scale.X, t.scale.Y) + m.Rotate(t.rotation) + m.Translate(t.position.X, t.position.Y) + t.parentMatrix = m + + mi := m + mi.Invert() + t.parentInverted = mi + + t.parentDirty = false + } else { + m = t.parentMatrix + mi = t.parentInverted } - p := t.Parent.GetTransform() - g = p.ParentMatrix() + if t.parent != nil { + pm, pmi := t.parent.MatrixForParenting() + m.Concat(pm) + mi.Concat(pmi) + } + + return m, mi - g.Scale(p.Scale.X, p.Scale.Y) - g.Rotate(p.Rotation) - g.Translate(p.Position.X, p.Position.Y) - return g } // Returns the GeoM with corresponding // to the transfrom transformation. -func (t Transform)Matrix() Matrix { - g := Matrix{} +func (t *Transform)Matrix() Matrix { + var m, pm Matrix - // Scale first. - g.Scale(t.Scale.X, t.Scale.Y) + // Calculating only if we changed the structure anyhow. + if t.dirty { + // Scale first. + m.Scale(t.scale.X, t.scale.Y) + // Then move and rotate. + m.Translate( + -t.around.X * t.scale.X, + -t.around.Y * t.scale.Y, + ) + m.Rotate(t.rotation) + // And finally move to the absolute position. + m.Translate(t.position.X, t.position.Y) + t.matrix = m - // Then move and rotate. - g.Translate( - -t.Around.X * t.Scale.X, - -t.Around.Y * t.Scale.Y, - ) - g.Rotate(t.Rotation) + // Setting the flag so we d + t.dirty = false + } else { + m = t.matrix + } - // And finally move to the absolute position. - g.Translate(t.Position.X, t.Position.Y) + if t.parent != nil { + pm, _ = t.parent.MatrixForParenting() + m.Concat(pm) + } - m := t.ParentMatrix() - g.Concat(m) - - return g + return m } diff --git a/vector.go b/vector.go index 8d3175c..36d49e5 100644 --- a/vector.go +++ b/vector.go @@ -22,7 +22,15 @@ func V(x, y Float) Vector { } func V2(v Float) Vector { - return V(v, v) + return Vector{v, v} +} + +func X(x Float) Vector { + return Vector{x, 0} +} + +func Y(y Float) Vector { + return Vector{0, y} } func (v Vector) Div(o Vector) Vector { @@ -32,7 +40,7 @@ func (v Vector) Div(o Vector) Vector { ) } -func (v Vector) Scale(o Vector) Vector { +func (v Vector) Mul(o Vector) Vector { return V( v.X * o.X, v.Y * o.Y, @@ -78,7 +86,7 @@ func (v Vector) Neg() Vector { } // Returns the vector rotated by "a" angle in radians. -func (v Vector) Rotate(a Float) Vector { +func (v Vector) Rot(a Float) Vector { m := Matrix{} m.Rotate(a) return v.Apply(m)