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
}
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

View file

@ -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,
)

View file

@ -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()))

View file

@ -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)

View file

@ -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 {

View file

@ -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)

View file

@ -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,

View file

@ -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
}

View file

@ -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)