This commit is contained in:
Andrey Parhomenko 2024-01-18 06:06:27 +03:00
parent 82da88509a
commit b479bf1988
9 changed files with 208 additions and 105 deletions

View file

@ -29,11 +29,18 @@ func (c *Camera)RealMatrix() Matrix {
return c.buf return c.buf
} }
g := Matrix{} g := Matrix{}
g.Translate(-c.Position.X, -c.Position.Y) position := c.Position().Neg()
g.Rotate(c.Rotation) around := c.Around()
siz := c.engine.AbsWinSize() scale := c.Scale()
g.Translate(c.Around.X * siz.X, c.Around.Y * siz.Y) rotation := c.Rotation()
g.Scale(c.Scale.X, c.Scale.Y)
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.buf = g
c.buffered = true c.buffered = true

View file

@ -11,14 +11,15 @@ type Circle struct {
Colority Colority
Antialiasity Antialiasity
Layer Layer
Radius Float
} }
func (circle *Circle) Draw(c *Context) []EVertex { func (circle *Circle) Draw(c *Context) []EVertex {
rPos := circle.Position.Apply(c.Camera.RealMatrix()) rPos := circle.Position().Apply(c.Camera.RealMatrix())
vector.DrawFilledCircle( vector.DrawFilledCircle(
c.Image, c.Image,
float32(rPos.X), float32(rPos.Y), float32(rPos.X), float32(rPos.Y),
float32(circle.Rotation), float32(circle.Radius),
circle.Color, circle.Color,
circle.Antialias, circle.Antialias,
) )

View file

@ -13,6 +13,9 @@ type Debug struct {
func (d *Debug) Draw(c *Context) []gg.EVertex { func (d *Debug) Draw(c *Context) []gg.EVertex {
e := c.Engine e := c.Engine
relTri := tri.Rel()
relPlayer := player.Rel()
keyStrs := []string{} keyStrs := []string{}
keyStrs = append(keyStrs, fmt.Sprintf( keyStrs = append(keyStrs, fmt.Sprintf(
"counter: %d", counter, "counter: %d", counter,
@ -30,20 +33,20 @@ func (d *Debug) Draw(c *Context) []gg.EVertex {
"frame: %d", int(c.Frame()), "frame: %d", int(c.Frame()),
)) ))
keyStrs = append(keyStrs, fmt.Sprintf( keyStrs = append(keyStrs, fmt.Sprintf(
"relPlayerPos: %v", player.Position, "relPlayerPos: %v", relPlayer.Position(),
)) ))
keyStrs = append(keyStrs, fmt.Sprintf( keyStrs = append(keyStrs, fmt.Sprintf(
"absPlayerPos: %v", player.AbsPosition(), "absPlayerPos: %v", player.Position(),
)) ))
keyStrs = append(keyStrs, fmt.Sprintf( keyStrs = append(keyStrs, fmt.Sprintf(
"relTriPos: %v", tri.Position, "relTriPos: %v", tri.Position(),
)) ))
keyStrs = append(keyStrs, fmt.Sprintf( keyStrs = append(keyStrs, fmt.Sprintf(
"absTriPos: %v", tri.AbsPosition(), "absTriPos: %v", relTri.Position(),
)) ))
keyStrs = append(keyStrs, fmt.Sprintf( keyStrs = append(keyStrs, fmt.Sprintf(
"absTriRot: %v", gg.Degree(tri.AbsRotation()), "absTriRot: %v", gg.Degree(tri.Rotation()),
)) ))
keys := []string{} keys := []string{}
@ -71,8 +74,8 @@ func (d *Debug) Draw(c *Context) []gg.EVertex {
keyStrs = append(keyStrs, fmt.Sprintf( keyStrs = append(keyStrs, fmt.Sprintf(
"camera position: %v %v", "camera position: %v %v",
c.Camera.Position.X, c.Camera.Position().X,
c.Camera.Position.Y, c.Camera.Position().Y,
)) ))
keyStrs = append(keyStrs, fmt.Sprintf("realCursorPos: %v", e.CursorPosition())) keyStrs = append(keyStrs, fmt.Sprintf("realCursorPos: %v", e.CursorPosition()))
keyStrs = append(keyStrs, fmt.Sprintf("absCursorPos: %v", e.AbsCursorPosition())) keyStrs = append(keyStrs, fmt.Sprintf("absCursorPos: %v", e.AbsCursorPosition()))

View file

@ -18,8 +18,8 @@ type Player struct {
func NewPlayer() *Player { func NewPlayer() *Player {
ret := &Player{} ret := &Player{}
ret.Transform = gg.T() ret.Transform = gg.T()
ret.Scale = gg.V2(1) ret.SetScale(gg.V2(1))
ret.Around = gg.V2(.5) ret.SetAround(gg.V2(.5))
ret.MoveSpeed = 40. ret.MoveSpeed = 40.
ret.ScaleSpeed = .2 ret.ScaleSpeed = .2
ret.Animations = playerAnimations ret.Animations = playerAnimations
@ -48,7 +48,7 @@ func (p *Player) Draw(c *Context) []gg.EVertex {
} }
func (p *Player) Update(c *Context) { func (p *Player) Update(c *Context) {
p.Position.Y += 2 p.SetPosition(p.Position().Sub(gg.Y(2)))
if p.Spawned { if p.Spawned {
return return
} }
@ -62,25 +62,30 @@ func (p *Player) Update(c *Context) {
for _, v := range keys { for _, v := range keys {
switch v { switch v {
case gg.KeyQ: 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: case gg.KeyArrowUp:
cam.Position.Y += p.MoveSpeed * dt cam.Move(gg.Y(-p.MoveSpeed * dt))
case gg.KeyArrowLeft:
cam.Position.X -= p.MoveSpeed * dt
case gg.KeyArrowDown: 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: case gg.KeyArrowRight:
cam.Position.X += p.MoveSpeed * dt cam.Move(gg.X(p.MoveSpeed * dt))
case gg.KeyW: case gg.KeyW:
p.Position.Y -= p.MoveSpeed * dt*10 p.Move(gg.Y(p.MoveSpeed * dt*10))
walking = true walking = true
p.Animate(Walk) p.Animate(Walk)
case gg.KeyA: case gg.KeyA:
p.Position.X -= p.MoveSpeed * dt p.Move(gg.X(-MoveSpeed * dt))
p.Scale.X = -1 p.SetScale(gg.V(-1, 1)
walking = true walking = true
p.Animate(Walk) p.Animate(Walk)
case gg.KeyS: case gg.KeyS:
p.Move(gg.X(-MoveSpeed * dt))
p.Position.Y -= p.MoveSpeed * dt p.Position.Y -= p.MoveSpeed * dt
walking = true walking = true
p.Animate(Walk) p.Animate(Walk)

View file

@ -145,7 +145,7 @@ func (c *Engine) RealWinSize() Vector {
} }
func (c *Engine) AbsWinSize() 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 { func (e *Engine) EventInput() EventChan {

View file

@ -19,7 +19,7 @@ type Rectangle struct {
func (r Rectangle) Vertices() Vertices { func (r Rectangle) Vertices() Vertices {
t := r.Transform t := r.Transform
wh := V(r.Width, r.Height) wh := V(r.Width, r.Height)
t.Around = t.Around.Scale(wh) t.SetAround(t.Around().Mul(wh))
m := t.Matrix() m := t.Matrix()
p1 := V(0, 0).Apply(m) p1 := V(0, 0).Apply(m)
p2 := V(wh.X, 0).Apply(m) p2 := V(wh.X, 0).Apply(m)

View file

@ -55,8 +55,11 @@ func (s *Sprite) RectangleToDraw() Rectangle {
w, h := s.Images[0].Size() w, h := s.Images[0].Size()
t := s.Transform t := s.Transform
t.Around.X *= Float(w) t.SetAround(
t.Around.Y *= Float(h) t.Around().Mul(
V(Float(w), Float(h)),
),
)
return Rectangle{ return Rectangle{
Transform: t, Transform: t,

View file

@ -6,7 +6,7 @@ import (
) )
type Transformer interface { type Transformer interface {
GetTransform() Transform GetTransform() *Transform
} }
// The structure represents basic transformation // The structure represents basic transformation
@ -14,18 +14,25 @@ type Transformer interface {
type Transform struct { type Transform struct {
// Absolute (if no parent) position and // Absolute (if no parent) position and
// the scale. // the scale.
Position, Scale Vector position, scale Vector
// The object rotation in radians. // The object rotation in radians.
Rotation Float rotation Float
// The not scaled offset vector from upper left corner // The not scaled offset vector from upper left corner
// which the object should be rotated around. // which the object should be rotated around.
Around Vector around Vector
// If is not nil then the upper values will be relational to // If is not nil then the upper values will be relational to
// the parent ones. // 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 return t
} }
@ -33,121 +40,190 @@ func (t Transform) GetTransform() Transform {
func T() Transform { func T() Transform {
ret := Transform{ ret := Transform{
// Rotate around // Rotate around
Scale: Vector{1, 1}, scale: Vector{1, 1},
// Rotate around the center. // Rotate around the center.
Around: V(.5, .5), around: V(.5, .5),
} }
return ret return ret
} }
func (t *Transform) SetAbsPosition(absPosition Vector) { // Set the absolute object position.
if t.Parent == nil { func (t *Transform) SetPosition(position Vector) {
t.Position = absPosition t.dirty = true
t.parentDirty = true
if t.parent == nil {
t.position = position
return return
} }
m := t.ParentMatrix()
m.Invert() _, mi := t.parent.MatrixForParenting()
t.Position = absPosition.Apply(m) 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. // Get the absolute representation of the transform.
func (t Transform) Abs() Transform { func (t *Transform) Abs() Transform {
if t.Parent == nil { if t.parent == nil {
return t return *t
} }
ret := T() ret := T()
ret.Position = t.AbsPosition() ret.position = t.Position()
ret.Rotation = t.AbsRotation() ret.rotation = t.Rotation()
ret.Scale = t.AbsScale()
// 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 return ret
} }
func (t Transform) AbsPosition() Vector { func (t *Transform) Rel() Transform {
if t.Parent == nil { ret := *t
return t.Position ret.parent = nil
} return ret
return t.Position.Apply(t.ParentMatrix())
} }
func (t Transform) AbsScale() Vector { // Get the absolute object position.
if t.Parent == nil { func (t *Transform) Position() Vector {
return t.Scale if t.parent == nil {
return t.position
} }
return V2(1) pm, _ := t.parent.MatrixForParenting()
return t.position.Apply(pm)
} }
func (t Transform) AbsRotation() Float { func (t *Transform) Move(v ...Vector) {
if t.Parent == nil { t.SetPosition(t.Position().Add(v...))
return t.Rotation
}
return t.Rotation + t.Parent.GetTransform().AbsRotation()
} }
func (t *Transform) SetAbsRotation(rot Float) { // Get the absolute object scale.
if t.Parent == nil { func (t *Transform) Scale() Vector {
t.Rotation = rot return t.scale
}
t.Rotation -= t.Parent.GetTransform().AbsRotation()
} }
// 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 { 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) { func (t *Transform) Connect(parent Transformer) {
absPosition := t.AbsPosition() absPosition := t.Position()
absRotation := t.AbsRotation() absRotation := t.Rotation()
t.Parent = parent t.parent = parent.GetTransform()
t.SetAbsPosition(absPosition) t.SetPosition(absPosition)
t.SetAbsRotation(absRotation) t.SetRotation(absRotation)
} }
// Disconnect from the parent.
func (t *Transform) Disconnect() { func (t *Transform) Disconnect() {
if t.Parent == nil { if t.parent == nil {
return return
} }
*t = t.Abs() *t = t.Abs()
} }
func (t Transform) ParentMatrix() Matrix { // Return the matrix and the inverted one for parenting children.
g := Matrix{} func (t *Transform) MatrixForParenting() (Matrix, Matrix) {
if t.Parent == nil { var m, mi Matrix
return g
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() if t.parent != nil {
g = p.ParentMatrix() 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 // Returns the GeoM with corresponding
// to the transfrom transformation. // to the transfrom transformation.
func (t Transform)Matrix() Matrix { func (t *Transform)Matrix() Matrix {
g := Matrix{} var m, pm Matrix
// Scale first. // Calculating only if we changed the structure anyhow.
g.Scale(t.Scale.X, t.Scale.Y) 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. // Setting the flag so we d
g.Translate( t.dirty = false
-t.Around.X * t.Scale.X, } else {
-t.Around.Y * t.Scale.Y, m = t.matrix
) }
g.Rotate(t.Rotation)
// And finally move to the absolute position. if t.parent != nil {
g.Translate(t.Position.X, t.Position.Y) pm, _ = t.parent.MatrixForParenting()
m.Concat(pm)
}
m := t.ParentMatrix() return m
g.Concat(m)
return g
} }

View file

@ -22,7 +22,15 @@ func V(x, y Float) Vector {
} }
func V2(v 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 { 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( return V(
v.X * o.X, v.X * o.X,
v.Y * o.Y, v.Y * o.Y,
@ -78,7 +86,7 @@ func (v Vector) Neg() Vector {
} }
// Returns the vector rotated by "a" angle in radians. // 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 := Matrix{}
m.Rotate(a) m.Rotate(a)
return v.Apply(m) return v.Apply(m)