Implemented better rotating around system.

This commit is contained in:
Andrey Parhomenko 2023-06-03 10:39:15 +03:00
parent ccefc2669b
commit 3807fc4bc2
5 changed files with 71 additions and 15 deletions

View file

@ -68,7 +68,7 @@ func NewPlayer() *Player {
Sprite: &gx.Sprite{ Sprite: &gx.Sprite{
Transform: gx.Transform { Transform: gx.Transform {
S: gx.Vector{5, 5}, S: gx.Vector{5, 5},
RA: gx.Vector{320, 240}, RA: gx.Vector{.5, .5},
}, },
Visible: true, Visible: true,
ShaderOptions: gx.ShaderOptions { ShaderOptions: gx.ShaderOptions {
@ -87,12 +87,12 @@ func NewPlayer() *Player {
func (p *Player) Draw(e *gx.Engine, i *gx.Image) { func (p *Player) Draw(e *gx.Engine, i *gx.Image) {
p.Sprite.Draw(e, i) p.Sprite.Draw(e, i)
t := p.Transform
t.S.X *= 4.
t.S.Y *= 4.
r := &gx.DrawableRectangle{ r := &gx.DrawableRectangle{
Rectangle: gx.Rectangle{ Rectangle: gx.Rectangle{
Transform: gx.Transform{ Transform: t,
P: player.P,
S: gx.Vector{100, 100},
},
}, },
Color: gx.Color{0, 0, gx.MaxColorV, gx.MaxColorV}, Color: gx.Color{0, 0, gx.MaxColorV, gx.MaxColorV},
} }
@ -132,6 +132,12 @@ func (p *Player) Update(e *gx.Engine) error {
c.R += gx.Pi * p.ScaleSpeed * dt c.R += gx.Pi * p.ScaleSpeed * dt
case ebiten.KeyT : case ebiten.KeyT :
c.R -= gx.Pi * p.ScaleSpeed * dt c.R -= gx.Pi * p.ScaleSpeed * dt
case ebiten.KeyRightBracket :
if e.KeyIsPressed(ebiten.KeyShift) {
p.R -= gx.Pi * 0.3 * dt
} else {
p.R += gx.Pi * 0.3 * dt
}
case ebiten.KeyF : case ebiten.KeyF :
if e.KeyIsPressed(ebiten.KeyShift) { if e.KeyIsPressed(ebiten.KeyShift) {
c.S.X -= gx.Pi * p.ScaleSpeed * dt c.S.X -= gx.Pi * p.ScaleSpeed * dt
@ -150,14 +156,18 @@ func (p *Player) Update(e *gx.Engine) error {
} else { } else {
c.RA.X += gx.Pi * p.MoveSpeed * dt c.RA.X += gx.Pi * p.MoveSpeed * dt
} }
log.Println(c.RA.X)
case ebiten.KeyX : case ebiten.KeyX :
if e.KeyIsPressed(ebiten.KeyShift) { if e.KeyIsPressed(ebiten.KeyShift) {
c.RA.Y -= gx.Pi * p.MoveSpeed * dt c.RA.Y -= gx.Pi * p.MoveSpeed * dt
} else { } else {
c.RA.Y += gx.Pi * p.MoveSpeed * dt c.RA.Y += gx.Pi * p.MoveSpeed * dt
} }
log.Println(c.RA.Y) case ebiten.KeyLeftBracket :
if e.KeyIsPressed(ebiten.KeyShift) {
rect.R -= gx.Pi * 0.3 * dt
} else {
rect.R += gx.Pi * 0.3 * dt
}
case ebiten.Key0 : case ebiten.Key0 :
e.Del(p) e.Del(p)
}} }}
@ -186,7 +196,7 @@ func (d *Debug) Draw(
func (d *Debug) IsVisible() bool {return true} func (d *Debug) IsVisible() bool {return true}
func main() { func main() {
e := gx.New(&gx.WindowConfig{ e := gx.NewEngine(&gx.WindowConfig{
Title: "Test title", Title: "Test title",
Width: 720, Width: 720,
Height: 480, Height: 480,

View file

@ -53,7 +53,7 @@ func (e *Engine) Keys() []Key {
} }
// Returns new empty Engine. // Returns new empty Engine.
func New( func NewEngine(
cfg *WindowConfig, cfg *WindowConfig,
) *Engine { ) *Engine {
w := Float(cfg.Width) w := Float(cfg.Width)
@ -157,7 +157,8 @@ func (e *engine) Draw(i *ebiten.Image) {
eng := (*Engine)(e) eng := (*Engine)(e)
for p := range e.layers.Vals() { for p := range e.layers.Vals() {
for pj := range p.V.Range() { for pj := range p.V.Range() {
if !pj.V.IsVisible() { visibler, ok := pj.V.(Visibler)
if ok && !visibler.IsVisible() {
continue continue
} }
pj.V.Draw(eng, i) pj.V.Draw(eng, i)

View file

@ -20,6 +20,9 @@ type Color struct {
// the layers order. // the layers order.
type Drawer interface { type Drawer interface {
Draw(*Engine, *Image) Draw(*Engine, *Image)
}
type Visibler interface {
IsVisible() bool IsVisible() bool
} }

View file

@ -19,9 +19,9 @@ func (s *Sprite) Draw(
return return
} }
t := s.Rectangle().Transform
m := &Matrix{} m := &Matrix{}
m.Concat(t.Matrix())
m.Concat(s.Matrix())
if !s.Floating { if !s.Floating {
m.Concat(e.Camera().RealMatrix( m.Concat(e.Camera().RealMatrix(
e, e,
@ -36,8 +36,8 @@ func (s *Sprite) Draw(
return return
} }
// Drawing with shader.
w, h := s.Images[0].Size() w, h := s.Images[0].Size()
// Drawing with shader.
opts := &ebiten.DrawRectShaderOptions{ opts := &ebiten.DrawRectShaderOptions{
Images: s.Images, Images: s.Images,
Uniforms: s.Uniforms, Uniforms: s.Uniforms,
@ -46,7 +46,26 @@ func (s *Sprite) Draw(
i.DrawRectShader(w, h, s.Shader, opts) i.DrawRectShader(w, h, s.Shader, opts)
} }
// Check is sprite is visible.
func (s *Sprite) IsVisible() bool { func (s *Sprite) IsVisible() bool {
return s.Visible return s.Visible
} }
// Return the rectangle that contains the sprite.
func (s *Sprite) Rectangle() Rectangle {
if s.Images[0] == nil {
panic("trying to get rectangle for nil image pointer")
}
w, h := s.Images[0].Size()
t := s.Transform
t.RA.X *= Float(w)
t.RA.Y *= Float(h)
return Rectangle{t}
}
func (s *Sprite) Triangles() Triangles {
return s.Rectangle().Triangles()
}

View file

@ -5,8 +5,17 @@ import (
//"math" //"math"
) )
// The structure represents basic transformation
// features: positioning, rotating and scaling.
type Transform struct { type Transform struct {
// Position, scale, rotate around(relatively of position, not absolute). // P - absolute phisycal position in engine itself.
//
// S - scale width and height (X and Y).
//
// RA - rotate around(relatively of position, not absolute).
//
// For example RA=Vector{0, 0} will rotate around right up corner
// and RA=Vector{.5, .5} will rotate around center.
P, S, RA Vector P, S, RA Vector
// Rotation angle in radians. // Rotation angle in radians.
R Float R Float
@ -20,13 +29,27 @@ func T() Transform {
return ret return ret
} }
func (t Transform) ScaledToXY(x, y Float) Transform {
return t.ScaledToX(x).ScaledToY(y)
}
func (t Transform) ScaledToX(x Float) Transform {
t.S.X = x
return t
}
func (t Transform) ScaledToY(y Float) Transform {
t.S.Y = y
return t
}
// 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{} g := &Matrix{}
g.Scale(t.S.X, t.S.Y) g.Scale(t.S.X, t.S.Y)
g.Translate(-t.RA.X, -t.RA.Y) g.Translate(-t.RA.X * t.S.X, -t.RA.Y * t.S.Y)
g.Rotate(t.R) g.Rotate(t.R)
g.Translate(t.P.X, t.P.Y) g.Translate(t.P.X, t.P.Y)