diff --git a/ax/ani.go b/ax/ani.go index 9eb25d5..1437f85 100644 --- a/ax/ani.go +++ b/ax/ani.go @@ -6,11 +6,11 @@ import ( // Unique identifier for animation // in the animation set. -type AnimationId int +type AnimationID int // The type describes set of animations // to switch between. -type AnimationSet map[AnimationId] Animation +type AnimationSet map[AnimationID] Animation // Make new animation set from an image. func AnimationSetFromImage( diff --git a/ax/define.go b/ax/define.go index 6abad44..60a69af 100644 --- a/ax/define.go +++ b/ax/define.go @@ -12,13 +12,13 @@ type RectIndex struct { // to structurely define // animations. type AnimationDefine struct{ - Id AnimationId + Id AnimationID Indexes []RectIndex } // Animation define shortcut. func AD( - id AnimationId, + id AnimationID, indexes ...RectIndex, ) AnimationDefine { return AnimationDefine{ diff --git a/camera.go b/camera.go index 7ba21a5..f4fe765 100644 --- a/camera.go +++ b/camera.go @@ -3,7 +3,7 @@ package gg import "surdeus.su/core/gg/mx" // The type describes what -// a camera object must implement. +// a window camera object must implement. type Camera interface { // Get the matrice to apply // camera's features. @@ -15,5 +15,7 @@ type Camera interface { // The shaders to apply on // everything on the camera. GetShaderOptions() *ShaderOptions + + GetAbsWinSize(Context) mx.Vector } diff --git a/cmd/test/camera.go b/cmd/test/camera.go new file mode 100644 index 0000000..29a8f1d --- /dev/null +++ b/cmd/test/camera.go @@ -0,0 +1,55 @@ +package main + +import "surdeus.su/core/gg/ox" +import "surdeus.su/core/gg/mx" +import "surdeus.su/core/gg" + +var ( + camera = &Camera{ + Camera: ox.NewCamera(), + ScaleSpeed: 5., + RotationSpeed: .3, + } +) + +type Camera struct { + ox.ObjectImpl + ox.Camera + ScaleSpeed mx.Float + RotationSpeed mx.Float +} + +func (cam *Camera) OnUpdate(c gg.Context) { + dt := c.Engine().DT().Seconds() + mov := c.Events().Mouse.Move + wheel := c.Events().Mouse.WheelChange + shiftPressed := c.Engine().IsPressed(gg.KeyShift) + d := float64(1.) + if shiftPressed { + d *= -1 + } + + // Moving. + if mov != nil && c.Engine().IsButtoned( + gg.MouseButtonRight, + ) { + cam.Move(mov.AbsDelta) + } + + // Scale. + if wheel != nil { + cam.AddScale(mx.V2( + wheel.Offset.Y * dt * cam.ScaleSpeed * 40, + )) + } + + // Scale and rotation. + for _, key := range c.Engine().GetKeyboardKeys() { + switch key { + case gg.KeyF: + cam.AddScale(mx.V2(d*cam.ScaleSpeed * dt)) + case gg.KeyR: + cam.Rotate(d*mx.Pi * cam.ScaleSpeed * dt) + } + } +} diff --git a/cmd/test/debug.go b/cmd/test/debug.go index 91e565f..c75c783 100644 --- a/cmd/test/debug.go +++ b/cmd/test/debug.go @@ -1,6 +1,8 @@ package main import "surdeus.su/core/gg" +import "surdeus.su/core/gg/ox" +import "surdeus.su/core/gg/mx" import ( "strings" @@ -8,24 +10,24 @@ import ( ) type Debug struct { - gg.Object - gg.Visibility + ox.ObjectImpl + ox.Visibility } -func (d *Debug) Update(c *Context) { - for _, e := range c.Events { - switch ec := e.(type) { - case *gg.KeyDown: - switch ec.Key { - case gg.KeyF11: - d.Visible = !d.Visible - } +func (d *Debug) OnUpdate(c Context) { + for _, key := range c.Events().Keyboard.KeyDowns { + switch key.Key { + case gg.KeyF11: + d.ToggleVisibility() + //d.Visible = !d.IsVisible() } } } -func (d *Debug) Draw(c *Context) []gg.EVertex { - e := c.Engine +func (d *Debug) GetLayer() gg.Layer {return LayerHighest} + +func (d *Debug) Draw(c Context) *gg.Drawing { + e := c.Engine() relTri := tri.Rel() relPlayer := player.Rel() @@ -34,36 +36,36 @@ func (d *Debug) Draw(c *Context) []gg.EVertex { "counter: %d", counter, )) keyStrs = append(keyStrs, fmt.Sprintf( - "tps: %d", int(c.Tps()), + "tps: %d", int(c.Engine().TPS()), )) keyStrs = append(keyStrs, fmt.Sprintf( - "fps: %d", int(c.Fps()), + "fps: %d", int(c.Engine().FPS()), )) keyStrs = append(keyStrs, fmt.Sprintf( - "dframe: %d", int(c.Dframe()), + "dframe: %d", int(c.Engine().Dframe()), )) keyStrs = append(keyStrs, fmt.Sprintf( - "frame: %d", int(c.Frame()), + "frame: %d", int(c.Engine().Frame()), )) keyStrs = append(keyStrs, fmt.Sprintf( - "relPlayerPos: %v", relPlayer.Position(), + "relPlayerPos: %v", relPlayer.GetPosition(), )) keyStrs = append(keyStrs, fmt.Sprintf( - "absPlayerPos: %v", player.Position(), + "absPlayerPos: %v", player.GetPosition(), )) keyStrs = append(keyStrs, fmt.Sprintf( - "relTriPos: %v", relTri.Position(), + "relTriPos: %v", relTri.GetPosition(), )) keyStrs = append(keyStrs, fmt.Sprintf( - "absTriPos: %v", tri.Position(), + "absTriPos: %v", tri.GetPosition(), )) keyStrs = append(keyStrs, fmt.Sprintf( - "absTriRot: %v", gg.Degree(tri.Rotation()), + "absTriRot: %v", mx.Degree(tri.GetRotation()), )) keys := []string{} - for _, k := range e.Keys() { + for _, k := range e.GetKeyboardKeys() { keys = append(keys, k.String()) } keyStrs = append(keyStrs, fmt.Sprintf( @@ -71,10 +73,10 @@ func (d *Debug) Draw(c *Context) []gg.EVertex { )) keyStrs = append(keyStrs, fmt.Sprintf( - "buttons: %v", c.MouseButtons(), + "buttons: %v", c.Engine().MouseButtons(), )) keyStrs = append(keyStrs, fmt.Sprintf( - "wheel: %v", c.Wheel(), + "wheel: %v", c.Engine().Wheel(), )) /*if rectMove.ContainsPoint(e.AbsCursorPosition()) { keyStrs = append(keyStrs, "contains cursor") @@ -87,14 +89,22 @@ 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, + camera.GetPosition().X, + camera.GetPosition().Y, )) - keyStrs = append(keyStrs, fmt.Sprintf("realCursorPos: %v", e.CursorPosition())) - keyStrs = append(keyStrs, fmt.Sprintf("absCursorPos: %v", e.AbsCursorPosition())) - keyStrs = append(keyStrs, fmt.Sprintf("absWinSize: %v", c.AbsWinSize())) + keyStrs = append(keyStrs, fmt.Sprintf( + "realCursorPos: %v", e.GetRealCursorPosition())) + keyStrs = append(keyStrs, fmt.Sprintf( + "absCursorPos: %v", e.GetAbsCursorPosition() )) - e.DebugPrint(c.Image, + keyStrs = append(keyStrs, + fmt.Sprintf( + "absWinSize: %v", + c.Engine().GetAbsWinSize(), + ), + ) + + e.DebugPrint(c.Image(), strings.Join(keyStrs, "\n")) return nil diff --git a/cmd/test/grid.go b/cmd/test/grid.go new file mode 100644 index 0000000..f5ed743 --- /dev/null +++ b/cmd/test/grid.go @@ -0,0 +1,53 @@ +package main + +import "surdeus.su/core/gg" +import "surdeus.su/core/gg/ox" +import "surdeus.su/core/gg/mx" + +type Grid struct { + ox.ObjectImpl + ox.Sprite + Cage, Width mx.Float +} + +func (grid *Grid) OnUpdate(c Context) { + //d := c.IsPressed(gg.KeyShift) + for _, down := range c.Events().Keyboard.KeyDowns { + switch down.Key { + case gg.Key9: + grid.Cage /= 10 + grid.Width /= 5 + case gg.Key0: + grid.Cage *= 10 + grid.Width *= 5 + } + } +} + +func NewGrid() *Grid { + grid := &Grid{} + grid.Transform = ox.T() + grid.SetAround(mx.V2(0)) + grid.Layer = LayerBackground + grid.Images[0] = gg.NewImage(720, 480) + grid.Images[0].Fill(gg.RGBA(1, 1, 1, 1)) + grid.Shader = bgShader + grid.Uniforms = map[string]any{} + //bg.Floating = true + grid.Visible = true + grid.Floating = true + grid.Cage = 100 + grid.Width = 5 + return grid +} + +func (grid *Grid) Draw(c Context) *gg.Drawing { + scale := camera.GetScale() + pos := camera.GetPosition() + grid.Uniforms["Zoom"] = mx.Float(scale.X) + grid.Uniforms["PosX"] = pos.X + grid.Uniforms["PosY"] = pos.Y + grid.Uniforms["Cage"] = grid.Cage + grid.Uniforms["Width"] = grid.Width + return grid.Sprite.Draw(c) +} diff --git a/cmd/test/main.go b/cmd/test/main.go index 061d9ce..19ba017 100644 --- a/cmd/test/main.go +++ b/cmd/test/main.go @@ -3,8 +3,9 @@ package main import ( "surdeus.su/core/gg" "surdeus.su/core/gg/ox" + //"surdeus.su/core/gg/mx" + "surdeus.su/core/gg/ax" "github.com/hajimehoshi/ebiten/v2/examples/resources/images" - "github.com/hajimehoshi/ebiten/v2/examples/resources/fonts" //_ "github.com/silbinarywolf/preferdiscretegpu" "bytes" "log" @@ -13,105 +14,32 @@ import ( type Context = gg.Context -type Grid struct { - ox.Sprite - Cage, Width gg.Float -} - -func (grid *Grid) OnUpdate(c *Context) { - //d := c.IsPressed(gg.KeyShift) - for _, ev := range c.Events { - switch e := ev.(type) { - case *gg.KeyDown: - switch e.Key { - case gg.Key9: - grid.Cage /= 10 - grid.Width /= 5 - case gg.Key0: - grid.Cage *= 10 - grid.Width *= 5 - } - } - } -} - -func (grid *Grid) OnDraw(c *Context) []gg.EVertex { - scale := c.Camera.Scale() - pos := c.Camera.Position() - grid.Uniforms["Zoom"] = gg.Float(scale.X) - grid.Uniforms["PosX"] = pos.X - grid.Uniforms["PosY"] = pos.Y - grid.Uniforms["Cage"] = grid.Cage - grid.Uniforms["Width"] = grid.Width - return grid.Sprite.Draw(c) -} - const ( - HighestL gg.Layer = -iota - DebugL - TriangleL - PlayerL - RectL - BackgroundLayer - LowestL + LayerHighest gg.Layer = -iota + + LayerDebug + LayerTriangle + LayerPlayer + LayerRect + LayerBackground + + LayerLowest ) const ( - Stand gg.AnimationId = iota + Stand ax.AnimationID = iota Walk ) + var ( - playerAnimations gg.AnimationSet + playerAnimations ax.AnimationSet playerImg *gg.Image player *Player - rectMove gg.Rectangle + rectMove ox.Rectangle rect *Rect tri *Tri -) - -func main() { - e := gg.NewEngine(&gg.WindowConfig{ - Title: "Test title", - Width: 720, - Height: 480, - VSync: true, - Fullscreen: false, - }) - - var err error - playerImg, err = gg.LoadImage(bytes.NewReader(images.Runner_png)) - if err != nil { - log.Fatal(err) - } - - rect = NewRect() - - playerAnimations, _ = gg.AnimationSetFromImage( - playerImg, - 8, 3, - 10, 1, - gg.AD(Stand).DefRow(0, 0, 1, 2, 3, 4), - gg.AD(Walk).DefRow(1, 0, 1, 2, 3, 4, 5, 6, 7), - ) - player = NewPlayer() - tri = NewTri() - - e.Spawn(&Debug{}) - e.Spawn(player) - e.Spawn(rect) - e.Spawn(tri) - - /*circle := &gg.Circle{} - circle.Transform = gg.T() - circle.Rotation = 300 - circle.Color = gg.Rgba(1, 1, 1, 1) - circle.Antialias = true - circle.Layer = HighestL - circle.Visible = true*/ - //e.Spawn(circle) - - bgShader := gg.MustNewShader([]byte(` + bgShader = gg.MustNewShader([]byte(` package main //kage:unit pixels @@ -140,40 +68,58 @@ func main() { return cx } `)) - grid := &Grid{} - grid.Transform = gg.T() - grid.SetAround(gg.V2(0)) - grid.Layer = BackgroundLayer - grid.Images[0] = gg.NewImage(720, 480) - grid.Images[0].Fill(gg.Rgba(1, 1, 1, 1)) - grid.Shader = bgShader - grid.Uniforms = map[string]any{} - //bg.Floating = true - grid.Visible = true - grid.Floating = true - grid.Cage = 100 - grid.Width = 5 - e.Spawn(grid) +) - txt := &Text{} - txt.Transform = gg.T() - //txt.Position = gg.V2(400) - txt.Color = gg.Rgba(1, 1, 1, 1) - txt.Layer = HighestL - txt.Visible = true - txt.Data = "Hello, World!\nПривет, Мир!" - txt.Face, err = gg.MakeFaceFromTtf( - bytes.NewReader(fonts.MPlus1pRegular_ttf), - &gg.TtfFaceOptions{ - Size: 32, - DPI: 72, - Hinting: gg.FontHintingNone, - }, +func main() { + e := gg.NewEngine(gg.WindowConfig{ + Title: "Test title", + Width: 720, + Height: 480, + VSync: true, + Fullscreen: false, + }) + e.SetCamera(camera) + e.Spawn(camera) + + var err error + playerImg, err = gg.LoadImage(bytes.NewReader(images.Runner_png)) + if err != nil { + log.Fatal(err) + } + + rect = NewRect() + + playerAnimations, _ = ax.AnimationSetFromImage( + playerImg, + 8, 3, + 10, 1, + ax.AD(Stand).DefRow(0, 0, 1, 2, 3, 4), + ax.AD(Walk).DefRow(1, 0, 1, 2, 3, 4, 5, 6, 7), ) + player = NewPlayer() + tri = NewTri() + + e.Spawn(&Debug{}) + e.Spawn(player) + e.Spawn(rect) + e.Spawn(tri) + + /*circle := &gg.Circle{} + circle.Transform = gg.T() + circle.Rotation = 300 + circle.Color = gg.Rgba(1, 1, 1, 1) + circle.Antialias = true + circle.Layer = HighestL + circle.Visible = true*/ + //e.Spawn(circle) + + e.Spawn(NewGrid()) + + text, err := NewText() if err != nil { panic(err) } - e.Spawn(txt) + e.Spawn(text) //fmt.Println(rect.GetLayer(), player.GetLayer()) fmt.Println("Starting...") diff --git a/cmd/test/player.go b/cmd/test/player.go index 840a636..dda5615 100644 --- a/cmd/test/player.go +++ b/cmd/test/player.go @@ -1,33 +1,36 @@ package main -import ( - //"math/rand" - "fmt" - "time" -) - import "surdeus.su/core/gg" +import "surdeus.su/core/gg/ox" +import "surdeus.su/core/gg/mx" +import "time" +import "log" type Player struct { - gg.AnimatedSprite - MoveSpeed gg.Float - ScaleSpeed gg.Float + ox.AnimatedSprite + MoveSpeed mx.Float + ScaleSpeed mx.Float Spawned bool } func NewPlayer() *Player { ret := &Player{} - ret.Transform = gg.T() - ret.SetScale(gg.V2(1)) - ret.SetAround(gg.V2(.5)) + //ret.Transform = ox.T() + ret.AnimatedSprite = ox.NewAnimatedSprite( + playerAnimations, + time.Second / 1, + ) + + + ret.SetScale(mx.V2(1)) + ret.SetAround(mx.V2(.5)) + ret.MoveSpeed = 40. ret.ScaleSpeed = .2 - ret.Animations = playerAnimations - ret.TimeBetweenFrames = time.Second / 10 ret.Shader = gg.SolidWhiteColorShader ret.Visible = true - ret.Layer = PlayerL + ret.Layer = LayerPlayer //ret.Collidable = true //ret.Resolvable = true @@ -35,20 +38,28 @@ func NewPlayer() *Player { return ret } -func (p *Player) Start(c *Context) { +func (p *Player) OnStart(c Context) { p.Connect(rect) } -func (p *Player) Draw(c *Context) []gg.EVertex { +func (p *Player) Draw(c Context) *gg.Drawing { return p.AnimatedSprite.Draw(c) - prect := &gg.DrawableRectangle{ - Rectangle: p.Rectangle(), + prect := &ox.DrawableRectangle{ + Rectangle: p.GetRectangle(), } - prect.Color = gg.Rgba(1, 1, 1, 1) + prect.Color = gg.RGBA(1, 1, 1, 1) return prect.Draw(c) } -func (p *Player) Update(c *Context) { +func (p *Player) OnUpdate(c Context) { + log.Println(p.IsVisible()) + if p.Spawned { + return + } + e := c.Engine() + dt := e.DT().Seconds() + //cam := c.Camera + keys := e.GetKeyboardKeys() /*r := gg.Rectangle{ Transform: gg.T(), } @@ -57,76 +68,52 @@ func (p *Player) Update(c *Context) { col, _ := gg.Collide(p, r) fmt.Println(col.Crosses)*/ //p.SetPosition(p.Position().Sub(gg.Y(2))) - p.Move(gg.Y(1)) - if p.Spawned { - return - } - dt := c.Dt().Seconds() - cam := c.Camera - keys := c.Keys() + //p.Move(gg.Y(1)) walking := false - shift := c.IsPressed(gg.KeyShift) + shiftPressed := e.IsPressed(gg.KeyShift) + d := float64(1) + if shiftPressed { + d *= -1 + } + //p.Uniforms["Random"] = any(rand.Float32()) - for _, v := range keys { - switch v { + for _, key := range keys { + switch key { case gg.KeyQ: - p.SetScale( - p.Scale().Add( - gg.X(p.ScaleSpeed * dt), - ), - ) + p.AddScale(mx.VX(d*p.ScaleSpeed * dt)) case gg.KeyW: - p.Move(gg.Y(-p.MoveSpeed * dt)) + p.Move(mx.VY(-p.MoveSpeed * dt)) walking = true p.Animate(Walk) case gg.KeyA: - p.Move(gg.X(-p.MoveSpeed * dt)) - p.SetScale(gg.V(-1, 1)) + p.Move(mx.VX(-p.MoveSpeed * dt)) + + p.SetScale(mx.V(-1, 1)) walking = true p.Animate(Walk) case gg.KeyS: - p.Move(gg.Y(p.MoveSpeed * dt)) + p.Move(mx.VY(p.MoveSpeed * dt)) //p.Position.Y -= p.MoveSpeed * dt walking = true p.Animate(Walk) case gg.KeyD: - p.Move(gg.X(p.MoveSpeed * dt)) - p.SetScale(gg.V(1, 1)) + p.Move(mx.VX(p.MoveSpeed * dt)) + p.SetScale(mx.V(1, 1)) walking = true p.Animate(Walk) - case gg.KeyR: - cam.Rotate(gg.Pi * p.ScaleSpeed * dt) - case gg.KeyT: - cam.Rotate(-gg.Pi * p.ScaleSpeed * dt) - case gg.KeyRightBracket: - if shift { - p.Rotate(-gg.Pi * 0.3 * dt) - } else { - p.Rotate(+gg.Pi * 0.3 * dt) - } - case gg.KeyF: - if shift { - cam.AddScale(gg.V2(p.ScaleSpeed * dt)) - } else { - cam.AddScale(gg.V2(-p.ScaleSpeed * dt)) - } - case gg.KeyLeftBracket: - if shift { - rect.Rotate(-gg.Pi * 0.3 * dt) - } else { - rect.Rotate(+gg.Pi * 0.3 * dt) - } - case gg.Key0: - c.Del(p) - case gg.KeyB: - case gg.Key5: + + case gg.KeyE : + p.Rotate(d*mx.Pi * 0.3 * dt) + case gg.KeyX: + c.Engine().Delete(p) + case gg.KeyC: pp := *p counter++ pp.Spawned = true - pp.Collidable = false - pp.Resolvable = false - c.Spawn(&pp) + //pp.Collidable = false + //pp.Resolvable = false + c.Engine().Spawn(&pp) } } @@ -134,38 +121,26 @@ func (p *Player) Update(c *Context) { p.Animate(Stand) } - for _, event := range c.Events { - switch ec := event.(type) { - case *gg.KeyDown: - switch { - case ec.Key == gg.KeyB: - if p.Layer != PlayerL { - p.Layer = PlayerL - } else { - p.Layer = HighestL - } + for _, down := range c.Events().Keyboard.KeyDowns { + switch { + case down.Key == gg.KeyZ: + if p.Layer != LayerPlayer { + p.Layer = LayerPlayer + } else { + p.Layer = LayerHighest } - case *gg.MouseMove: - if !c.IsButtoned(gg.MouseButtonRight) { - break - } - c.Camera.Move(ec.Abs) - case *gg.WheelChange: - c.Camera.AddScale(gg.V2( - ec.Offset.Y * dt * p.ScaleSpeed * 40, - )) } } } -func (p *Player) GetCollisionInterest() []gg.CollisionType { +/*func (p *Player) GetCollisionInterest() []gg.CollisionType { return []gg.CollisionType{ gg.CollisionStaticPhysics, } -} +}*/ -func (p *Player) Resolve(c *Context) { +/*func (p *Player) Resolve(c *Context) { col := c.Collisions[0] if !p.Spawned && false { fmt.Printf( @@ -186,4 +161,4 @@ func (p *Player) Resolve(c *Context) { } } } -} +}*/ diff --git a/cmd/test/rect.go b/cmd/test/rect.go index 064dcdd..d7d81ce 100644 --- a/cmd/test/rect.go +++ b/cmd/test/rect.go @@ -1,21 +1,19 @@ package main import "surdeus.su/core/gg" +import "surdeus.su/core/gg/ox" +import "surdeus.su/core/gg/mx" type Rect struct { - gg.DrawableRectangle + ox.ObjectImpl + ox.DrawableRectangle } func NewRect() *Rect { ret := &Rect{} - ret.SetScale(gg.V(5, 5)) - ret.Color = gg.Color{ - gg.MaxColorV, - 0, - 0, - gg.MaxColorV, - } - ret.Layer = RectL + ret.SetScale(mx.V(5, 5)) + ret.Color = gg.RGBA(1, 0, 0, 1) + ret.Layer = LayerRect ret.Visible = true //ret.Collidable = true ret.Width = 100 @@ -24,27 +22,33 @@ func NewRect() *Rect { return ret } -func (r *Rect) CollisionType() gg.CollisionType { - return gg.CollisionStaticPhysics -} - -func (r *Rect) Update(c *Context) { +func (r *Rect) OnUpdate(c Context) { //r.R += 0.3 * e.DT() - dt := c.Dt().Seconds() + e := c.Engine() + dt := e.DT().Seconds() + shiftPressed := e.IsPressed(gg.KeyShift) + d := float64(1) + if shiftPressed { + d *= -1 + } //r.Position = c.AbsCursorPosition() - for _, v := range c.Keys() { + for _, v := range e.GetKeyboardKeys() { switch v { case gg.KeyArrowUp: - r.Move(gg.Y(-10 * dt)) + r.Move(mx.VY(-10 * dt)) case gg.KeyArrowDown: - r.Move(gg.Y(10 * dt)) + r.Move(mx.VY(10 * dt)) case gg.KeyArrowLeft: - r.Move(gg.X(-10 * dt)) + r.Move(mx.VX(-10 * dt)) case gg.KeyArrowRight: - r.Move(gg.X(10 * dt)) + r.Move(mx.VX(10 * dt)) + case gg.KeyLeftBracket: + r.Rotate(d*mx.Pi * 0.3 * dt) } } } -func (r *Rect) Event(c *Context) { -} +/*func (r *Rect) CollisionType() gg.CollisionType { + return gg.CollisionStaticPhysics +}*/ + diff --git a/cmd/test/text.go b/cmd/test/text.go index ad51811..4ea62ae 100644 --- a/cmd/test/text.go +++ b/cmd/test/text.go @@ -2,26 +2,40 @@ package main import ( "surdeus.su/core/gg" + "surdeus.su/core/gg/ox" + "github.com/hajimehoshi/ebiten/v2/examples/resources/fonts" + "bytes" //"fmt" ) -type Objecter interface { -} - -type Wrap[V Objecter] struct { - O V -} - -//func (w *Wrap) - -type Context2 struct { - *gg.Context -} - type Text struct { - gg.Text + ox.ObjectImpl + ox.Text } -func (txt *Text) Update(c *Context) { +func NewText() (*Text, error) { + txt := &Text{} + txt.Transform = ox.T() + //txt.Position = gg.V2(400) + txt.Color = gg.RGBA(1, 1, 1, 1) + txt.Layer = LayerHighest + txt.Visible = true + txt.Data = "Hello, World!\nПривет, Мир!" + var err error + txt.Face, err = gg.MakeFaceFromTTF( + bytes.NewReader(fonts.MPlus1pRegular_ttf), + &gg.FaceOptionsTTF{ + Size: 32, + DPI: 72, + Hinting: gg.FontHintingNone, + }, + ) + if err != nil { + return nil, err + } + return txt, nil +} + +func (txt *Text) Update(c *gg.Context) { //txt.Data += string(c.Runes()) } diff --git a/cmd/test/trianlge.go b/cmd/test/trianlge.go index 654dcc8..e5aabb3 100644 --- a/cmd/test/trianlge.go +++ b/cmd/test/trianlge.go @@ -1,39 +1,42 @@ package main import "surdeus.su/core/gg" -import "fmt" +import "surdeus.su/core/gg/ox" +import "surdeus.su/core/gg/mx" +//import "fmt" var ( counter int ) type Tri struct { - gg.DrawablePolygon + ox.ObjectImpl + ox.DrawablePolygon Spawned bool } func NewTri() *Tri { ret := &Tri{} - ret.Transform = gg.T() - ret.SetPosition(gg.V(-100, -100)) - ret.Triangles = gg.Triangles{ - gg.Triangle{ - gg.V(0, 10), - gg.V(100, 0), - gg.V(0, -10), + ret.Transform = ox.T() + ret.SetPosition(mx.V2(-100)) + ret.Triangles = mx.Triangles{ + mx.Triangle{ + mx.V(0, 10), + mx.V(100, 0), + mx.V(0, -10), }, } - ret.Color = gg.Rgba(1, 1, 0, 1) + ret.Color = gg.RGBA(1, 1, 0, 1) ret.Visible = true //ret.Collidable = true - ret.Type = gg.CollisionStaticPhysics - ret.Layer = TriangleL + //ret.Type = gg.CollisionStaticPhysics + ret.Layer = LayerTriangle //ret.Connect(player) return ret } -func (t *Tri) Update(c *Context) { +func (t *Tri) OnUpdate(c Context) { //redges := rect.Edges() //tedges := t.Edges() //crosses, ok := tedges.CrossWithEdges(redges) @@ -42,24 +45,25 @@ func (t *Tri) Update(c *Context) { if false { //fmt.Println("edges:", tedges) } - col, hasCol := gg.Collide(t, rect) + /*col, hasCol := gg.Collide(t, rect) if hasCol && len(col.Crosses) > 0 { fmt.Println("col:", col) - } - dt := c.Dt().Seconds() - if !t.ContainedPoints(gg.Points{c.AbsCursorPosition()}).Empty() { + }*/ + e := c.Engine() + dt := e.DT().Seconds() + /*if !t.ContainedPoints(gg.Points{c.AbsCursorPosition()}).Empty() { t.Color = gg.Rgba(0, 1, 0, 1) } else { t.Color = gg.Rgba(1, 0, 1, 1) - } + }*/ if t.Spawned { return } - keys := c.Keys() + keys := e.GetKeyboardKeys() d := +1. - if c.IsPressed(gg.KeyShift) { + if e.IsPressed(gg.KeyShift) { d = -1 } @@ -67,21 +71,21 @@ func (t *Tri) Update(c *Context) { switch key { case gg.KeyM: - t.Move(gg.Y(100 * dt * d)) + t.Move(mx.VY(100 * dt * d)) case gg.KeyN: - t.Move(gg.X(100 * dt * d)) + t.Move(mx.VX(100 * dt * d)) case gg.KeyV: - t.Rotate(d * gg.Pi * 0.3 * dt) + t.Rotate(d * mx.Pi * 0.3 * dt) case gg.Key2: if t.Spawned { break } - t.Triangles = append(t.Triangles, gg.Triangle{ - gg.V(0, 10+gg.Float(counter)), - gg.V(100+gg.Float(counter), 0), + /*t.Triangles = append(t.Triangles, gg.Triangle{ + gg.V(0, 10+ mx.Float(counter)), + gg.V(100+ mx.Float(counter), 0), gg.V(0, -10-gg.Float(counter)), - }) + })*/ case gg.Key3: if t.Spawned { break @@ -89,22 +93,19 @@ func (t *Tri) Update(c *Context) { tt := *t tt.Spawned = true tt.Disconnect() - if c.Spawn(&tt) == nil { + if e.Spawn(&tt) == nil { counter++ } } } - for _, event := range c.Events { - switch e := event.(type) { - case *gg.KeyDown: - switch e.Key { - case gg.Key1: - if t.Connected() { - t.Disconnect() - } else { - t.Connect(player) - } + for _, down := range c.Events().Keyboard.KeyDowns { + switch down.Key { + case gg.Key1: + if t.IsConnected() { + t.Disconnect() + } else { + t.Connect(player) } } } diff --git a/collider.go b/collider.go deleted file mode 100644 index a28e3fb..0000000 --- a/collider.go +++ /dev/null @@ -1,2 +0,0 @@ -package gg - diff --git a/context.go b/context.go index 1c71255..51dfd2c 100644 --- a/context.go +++ b/context.go @@ -1,8 +1,35 @@ package gg +// The type is used to provide +// custom behaviour for drawing and updating etc. type Context struct { - Events []any - *Engine - *Image + events Events + engine *Engine + image *Image +} + +// Get the current engine. +func (c Context) Engine() *Engine { + return c.engine +} + +func (c Context) Camera() Camera { + if c.engine == nil { + return nil + } + return c.engine.camera +} + +// Get the image to draw to. +// Can be accessed only in the +// Draw(...) call. +func (c Context) Image() *Image { + return c.image +} + +// Get the events. +// Available only in the Update(...) call. +func (c Context) Events() Events { + return c.events } diff --git a/draw.go b/draw.go index c8dac8b..490e8d3 100644 --- a/draw.go +++ b/draw.go @@ -1,14 +1,14 @@ package gg type Drawing struct { - EVertices []EVertice + Vertices []Vertice } // The interface describes anything that can be // drawn. It will be drew corresponding to // the layers order so the layer must be returned. type Drawer interface { - Draw(Context) Drawing + Draw(Context) *Drawing GetLayer() Layer IsVisible() bool } diff --git a/engine.go b/engine.go index bbee5b1..6d74f07 100644 --- a/engine.go +++ b/engine.go @@ -17,13 +17,6 @@ const ( type GraphicsLibrary = ebiten.GraphicsLibrary type RunOptions = ebiten.RunGameOptions -// The type represents order of drawing. -// Higher values are drawn later. -type Layer float64 - -func (l Layer) GetLayer() Layer { - return l -} // Window configuration type. type WindowConfig struct { @@ -60,7 +53,7 @@ type Engine struct { // The main camera to display in window. // If is set to nil then the engine will panic. - Camera Camera + camera Camera drawLastTime time.Time drawdt Duration @@ -92,7 +85,7 @@ type Engine struct { type engine Engine // Get currently pressed keys. -func (e *Engine) Keys() []Key { +func (e *Engine) GetKeyboardKeys() []Key { return e.keys } @@ -119,7 +112,6 @@ func NewEngine( ret := &Engine{} ret.wcfg = cfg - ret.Camera = ret.NewCamera() ret.outerEvents = make(EventChan) ret.handleEvents = make(EventChan) ret.Objects = &Objects{} @@ -127,24 +119,16 @@ func NewEngine( return ret } -// Get the real window size in the current context. -func (c *Engine) RealWinSize() mx.Vector { - var w, h int - if c.wcfg.Fullscreen { - w, h = ebiten.ScreenSizeInFullscreen() - } else { - w, h = c.wcfg.Width, c.wcfg.Height - } - return mx.Vector{ - mx.Float(w), - mx.Float(h), - } +func (e *Engine) Camera() Camera { + return e.camera } -func (c *Engine) AbsWinSize() mx.Vector { - return c.RealWinSize().Div(c.Camera.GetScale()) +func (e *Engine) SetCamera(c Camera) *Engine { + e.camera = c + return e } + func (e *Engine) EventInput() EventChan { return e.outerEvents } @@ -156,7 +140,7 @@ func (e *Engine) Spawn(o Object) error { }*/ o.OnStart(Context{ - Engine: e, + engine: e, }) e.Objects.store = append(e.Objects.store, o) @@ -186,7 +170,7 @@ var ( ) func (e *Engine) IsPressed(k Key) bool { - keys := e.Keys() + keys := e.GetKeyboardKeys() for _, v := range keys { if v == k { return true @@ -210,77 +194,121 @@ func (e *Engine) cursorPosition() mx.Vector { return mx.Vector{mx.Float(x), mx.Float(y)} } -func (e *Engine) CursorPosition() mx.Vector { +// Get the real cursor position. +func (e *Engine) GetRealCursorPosition() mx.Vector { return e.cursorPos } -func (e *Engine) AbsCursorPosition() mx.Vector { - return e.CursorPosition().Apply(e.Camera.GetAbsMatrice()) +// Get the absolute cursor position in the world +// of the engine. +func (e *Engine) GetAbsCursorPosition( +) mx.Vector { + return e.GetRealCursorPosition(). + Apply(e.camera.GetAbsMatrice(Context{ + engine: e, + })) } +// Get the real window size in the current context. +func (e *Engine) GetRealWinSize() mx.Vector { + var w, h int + if e.wcfg.Fullscreen { + w, h = ebiten.ScreenSizeInFullscreen() + } else { + w, h = e.wcfg.Width, e.wcfg.Height + } + return mx.Vector{ + mx.Float(w), + mx.Float(h), + } +} + +func (e *Engine) GetAbsWinSize() mx.Vector { + return e.camera.GetAbsWinSize(Context{ + engine: e, + }) +} func (e *Engine) Runes() []rune { return e.runes } -func (e *engine) updateEvents() []any { +func (e *engine) updateEvents() Events { eng := (*Engine)(e) e.prevKeys = e.keys e.keys = inpututil. AppendPressedKeys(e.keys[:0]) - events := []any{} + events := Events{} + + // Mouse buttons. btns := e.buttons for _, btn := range allButtons { if inpututil.IsMouseButtonJustPressed(btn) { btns[btn] = struct{}{} - events = append(events, &MouseButtonDown{ - MouseButton: btn, - }) + events.Mouse.ButtonDowns = append( + events.Mouse.ButtonDowns, + MouseButtonDown{ + MouseButton: btn, + }, + ) } else if inpututil.IsMouseButtonJustReleased(btn) { delete(btns, btn) - events = append(events, &MouseButtonUp{ - MouseButton: btn, - }) + events.Mouse.ButtonUps = append( + events.Mouse.ButtonUps, + MouseButtonUp{ + MouseButton: btn, + }, + ) } } + // Mouse wheel. x, y := ebiten.Wheel() e.wheel = mx.Vector{x, y} if !(e.wheel.Eq(mx.ZV)) { - events = append(events, &WheelChange{ + events.Mouse.WheelChange = &WheelChange{ Offset: e.wheel, - }) - } - - keyDiff := diffEm(e.prevKeys, e.keys) - for _, key := range keyDiff { - var event any - if eng.IsPressed(key) { - event = &KeyDown{ - Key: key, - } - } else { - event = &KeyUp{ - Key: key, - } } - events = append(events, event) } + // Cursor position. realPos := eng.cursorPosition() if !realPos.Eq(e.cursorPos) { - absM := eng.Camera.GetAbsMatrice() + absM := eng.camera.GetAbsMatrice(Context{ + engine: eng, + }) absPrevPos := e.cursorPos.Apply(absM) absPos := realPos.Apply(absM) - events = append(events, &MouseMove{ + events.Mouse.Move = &MouseMove{ RealDelta: realPos.Sub(e.cursorPos), AbsDelta: absPos.Sub(absPrevPos), - }) + } e.cursorPos = realPos } + + // Keyboard. + keyDiff := diffEm(e.prevKeys, e.keys) + for _, key := range keyDiff { + if eng.IsPressed(key) { + events.Keyboard.KeyDowns = append( + events.Keyboard.KeyDowns, + KeyDown{ + Key: key, + }, + ) + } else { + events.Keyboard.KeyUps = append( + events.Keyboard.KeyUps, + KeyUp{ + Key: key, + }, + ) + } + } + return events } @@ -298,8 +326,8 @@ func (e *engine) Update() error { events := e.updateEvents() c := Context{ - Engine: eng, - Events: events, + engine: eng, + events: events, } for _, object := range e.Objects.store { object.OnUpdate(c) @@ -350,16 +378,16 @@ func (e *engine) Draw(img *ebiten.Image) { // First drawing via the inside function // and then the returned []EVertex. layers := maps.NewSparse[Layer, []Drawer](nil, m) - c := Context{Engine: eng, Image: img} + c := Context{engine: eng, image: img} for layer := range layers.Chan() { - vertices := []EVertice{} + vertices := Vertices{} for _, drawer := range layer { drawing := drawer.Draw(c) - if drawing.EVertices != nil { + if drawing != nil { vertices = append( vertices, - drawing.EVertices..., + drawing.Vertices..., ) } } @@ -369,7 +397,7 @@ func (e *engine) Draw(img *ebiten.Image) { for i := 0 ; i fullTime { as.duration -= fullTime } as.Images[0] = frames[ - (as.duration/as.TimeBetweenFrames) % - Duration(len(frames)), + (as.duration/as.timeBetweenFrames) % + gg.Duration(len(frames)), ] return as.Sprite.Draw(c) diff --git a/ox/camera.go b/ox/camera.go index 1285557..3849479 100644 --- a/ox/camera.go +++ b/ox/camera.go @@ -5,9 +5,8 @@ import "surdeus.su/core/gg/mx" // Default camera implementation. +var _ = gg.Camera(&Camera{}) type Camera struct { - ObjectImpl - // The Transform to interact with // to change camera position, rotation etc. Transform @@ -18,13 +17,13 @@ type Camera struct { // The bufferization implementation // to keep everything fast. - absMatrice realMatrice + absMatrice, realMatrice mx.Matrice } // Returns the new camera // with default settings. -func NewCamera() *Camera { - ret := &Camera{} +func NewCamera() Camera { + ret := Camera{} ret.Transform = T() return ret } @@ -37,7 +36,7 @@ func (c *Camera) GetRealMatrice(ctx gg.Context) mx.Matrice { // Bufferization // so we do not need to recalculate // Transform again. - if !c.Transform.Dirty() { + if !c.Transform.IsDirty() { return c.realMatrice } @@ -50,7 +49,7 @@ func (c *Camera) GetRealMatrice(ctx gg.Context) mx.Matrice { g.Translate(-position.X, -position.Y) g.Rotate(rotation) - size := ctx.Engine.AbsWinSize() + size := ctx.Engine().GetAbsWinSize() g.Translate(around.X * size.X, around.Y * size.Y) g.Scale(scale.X, scale.Y) @@ -63,14 +62,21 @@ func (c *Camera) GetRealMatrice(ctx gg.Context) mx.Matrice { // inside engine representation, // get the position of cursor inside the world // basing on its window position. -func (c *Camera) GetAbsMatrice(ctx gg.Context) mx.Matrice { - if !c.Transform.Dirty() { - return c.absMatrice +func (camera *Camera) GetAbsMatrice(ctx gg.Context) mx.Matrice { + if !camera.Transform.IsDirty() { + return camera.absMatrice } - m := c.GetRealMatrice(ctx) + m := camera.GetRealMatrice(ctx) m.Invert() - c.absMatrice = m + camera.absMatrice = m return m } +func (camera *Camera) GetAbsWinSize( + ctx gg.Context, +) mx.Vector { + return ctx.Engine().GetRealWinSize(). + Div(camera.GetScale()) +} + diff --git a/ox/circle.go b/ox/circle.go index a59f41c..e75957f 100644 --- a/ox/circle.go +++ b/ox/circle.go @@ -5,27 +5,28 @@ import ( ) import "surdeus.su/core/gg" +import "surdeus.su/core/gg/mx" type Circle struct { ObjectImpl - gg.Transform + mx.Circle Visibility Colority Antialiasity - Layer - Radius Float + gg.Layer } -func (circle *Circle) Draw(c *Context) []EVertex { - rPos := circle.Position().Apply(c.Camera.RealMatrix()) +func (circle *Circle) Draw(c gg.Context) gg.Drawing { + center := circle.Center. + Apply(c.Camera().GetRealMatrice(c)) vector.DrawFilledCircle( - c.Image, - float32(rPos.X), float32(rPos.Y), + c.Image(), + float32(center.X), float32(center.Y), float32(circle.Radius), circle.Color, circle.Antialias, ) - return nil + return gg.Drawing{} } diff --git a/ox/feats.go b/ox/feats.go index 0feaabe..3d04c38 100644 --- a/ox/feats.go +++ b/ox/feats.go @@ -1,5 +1,15 @@ package ox +import "surdeus.su/core/gg" + + +type Drawity struct { + Visibility + Colority + Shaderity + Floatity + Layerity +} // Feat to emded for turning antialias on and off. type Antialiasity struct { @@ -14,18 +24,32 @@ func (v Visibility) IsVisible() bool { return v.Visible } +func (v Visibility) ToggleVisibility() bool { + v.Visible = !v.Visible + return v.IsVisible() +} + // Feat to embed to make colorful objects. type Colority struct { - Color Color + Color gg.Color } // The structure to embed into shaderable // objects. type Shaderity struct { - ShaderOptions ShaderOptions + gg.ShaderOptions } -func (s *Shaderity) GetShaderOptions( -) *ShaderOptions { +func (s Shaderity) GetShaderOptions( +) *gg.ShaderOptions { return &s.ShaderOptions } + +type Floatity struct { + Floating bool +} +func (s Floatity) IsFloating() bool { + return s.Floating +} + +type Layerity = gg.Layer diff --git a/ox/object.go b/ox/object.go index 9d2619e..b7b1b7a 100644 --- a/ox/object.go +++ b/ox/object.go @@ -1,12 +1,25 @@ package ox +import "surdeus.su/core/gg" + +type DrawerImpl struct{} +func (o DrawerImpl) Draw(c gg.Context) *gg.Drawing { + return nil +} +func (o DrawerImpl) GetLayer() gg.Layer {return 0} +func (o DrawerImpl) IsVisible() bool {return false} + +type BeherImpl struct{} +func (o BeherImpl) OnStart(c gg.Context) {} +func (o BeherImpl) OnUpdate(c gg.Context) {} +func (o BeherImpl) OnDelete(c gg.Context) {} +func (o BeherImpl) GetTags() gg.TagMap {return nil} + // The standard empty implementation -// of the Object interface to embed. -type ObjectImpl struct {} -func (o ObjectImpl) OnStart(c Context) {} -func (o ObjectImpl) OnUpdate(c Context) {} -func (o ObjectImpl) OnDelete(c Context) {} -func (o ObjectImpl) GetTags() map[string]struct{}{return nil} -func (o ObjectImpl) Draw(c Context) {} -func (o ObjectImpl) GetLayer() Layer {return 0} -func (o ObjectImpl) IsVisible() bool {return false} +// of the Object interface to embed +// so you do not need to implement everything. +var _ = gg.Object(ObjectImpl{}) +type ObjectImpl struct { + DrawerImpl + BeherImpl +} diff --git a/ox/polygon.go b/ox/polygon.go index b391a37..53feb68 100644 --- a/ox/polygon.go +++ b/ox/polygon.go @@ -12,15 +12,18 @@ type Polygon struct { mx.Triangles } -func (p Polygon) ContainedPoints(pts Points) (Points) { - return p.MakeTriangles().ContainedPoints(pts) +func (p Polygon) GetContainedPoints( + pts mx.Vectors, +) (mx.Vectors) { + return p.MakeTriangles(). + GetContainedPoints(pts) } -func (p Polygon) MakeTriangles() Triangles { +func (p Polygon) MakeTriangles() mx.Triangles { m := p.Transform.GetMatrice() - ret := make(Triangles, len(p.Triangles)) + ret := make(mx.Triangles, len(p.Triangles)) for i, t := range p.Triangles { - ret[i] = Triangle{ + ret[i] = mx.Triangle{ t[0].Apply(m), t[1].Apply(m), t[2].Apply(m), @@ -38,21 +41,18 @@ func (p Polygon) GetEdges() mx.Lines { return p.MakeTriangles().GetEdges() } +var _ = gg.Drawer(&DrawablePolygon{}) // Polygon that can be drawn. type DrawablePolygon struct { Polygon - ShaderOptions - Visibility - Colority + + Drawity } -func (p *DrawablePolygon) Draw(c *Context) gg.Drawing { - ret := gg.Drawing{ - EVertices: (&DrawableTriangles{ - Colority: p.Colority, - Triangles: p.MakeTriangles(), - }).MakeEVertices(c), - } - return ret +func (p *DrawablePolygon) Draw(c gg.Context) *gg.Drawing { + tri := &DrawableTriangles{} + tri.Triangles = p.MakeTriangles() + tri.Drawity = p.Drawity + return tri.Draw(c) } diff --git a/ox/rect.go b/ox/rect.go index 2bfb314..04c7256 100644 --- a/ox/rect.go +++ b/ox/rect.go @@ -13,30 +13,30 @@ import "surdeus.su/core/gg/mx" // way to move, rotate and scale it. type Rectangle struct { ObjectImpl - gg.Transform - Width, Height Float + Transform + Width, Height mx.Float } // Return points of vertices of the rectangle. func (r Rectangle) Vertices() mx.Vectors { t := r.Transform - wh := V(r.Width, r.Height) - t.SetAround(t.Around().Mul(wh)) - m := t.Matrix() - p1 := V(0, 0).Apply(m) - p2 := V(wh.X, 0).Apply(m) - p3 := V(wh.X, wh.Y).Apply(m) - p4 := V(0, wh.Y).Apply(m) + wh := mx.Vector{r.Width, r.Height} + t.SetAround(t.GetAround().Mul(wh)) + m := t.GetMatrice() + p1 := mx.Vector{0, 0}.Apply(m) + p2 := mx.Vector{wh.X, 0}.Apply(m) + p3 := mx.Vector{wh.X, wh.Y}.Apply(m) + p4 := mx.Vector{0, wh.Y}.Apply(m) return mx.Vectors{p1, p2, p3, p4} } func (r Rectangle) Edges() mx.Lines { vs := r.Vertices() - return Lines{ - Edge{vs[0], vs[1]}, - Edge{vs[1], vs[2]}, - Edge{vs[2], vs[3]}, - Edge{vs[3], vs[0]}, + return mx.Lines{ + mx.Line{vs[0], vs[1]}, + mx.Line{vs[1], vs[2]}, + mx.Line{vs[2], vs[3]}, + mx.Line{vs[3], vs[0]}, } } @@ -55,6 +55,11 @@ func (r Rectangle) MakeTriangles() mx.Triangles { } // Check whether the rectangle contains the point. +func (r Rectangle) ContainsPoint(pt mx.Vector) bool { + return r.MakeTriangles().ContainsPoint(pt) +} + +// Get the points that are contained in the rectangle. func (r Rectangle) GetContainedPoints( pts mx.Vectors, ) (mx.Vectors) { @@ -64,19 +69,14 @@ func (r Rectangle) GetContainedPoints( // The type describes rectangle that can be drawn. type DrawableRectangle struct { Rectangle - ShaderOptions - - // Solid color of the rectangle. - // Will be ignored if the Shader - // field is not nil. - Colority + Drawity } -func (r *DrawableRectangle) Draw(c *Context) []EVertex { - return (&DrawableTriangles{ - Colority: r.Colority, - Triangles: r.MakeTriangles(), - }).MakeEVertices(c) +func (r *DrawableRectangle) Draw(c gg.Context) *gg.Drawing { + tri := &DrawableTriangles{} + tri.Drawity = r.Drawity + tri.Triangles = r.MakeTriangles() + return tri.Draw(c) /*// Use the Color as base image if no is provided. //var did bool diff --git a/ox/sprite.go b/ox/sprite.go index 03313c3..a31a546 100644 --- a/ox/sprite.go +++ b/ox/sprite.go @@ -5,22 +5,21 @@ import ( //"fmt" ) -import "surdeus.su/core/gg" import "surdeus.su/core/gg/mx" +import "surdeus.su/core/gg" +var _ = gg.Drawer(&Sprite{}) type Sprite struct { - ObjectImpl - gg.Transform - ShaderOptions - Floating bool - Visibility + Transform + + Drawity } var ( //spritesOp DrawImageOptions ) -func (s *Sprite) Draw(c Context) []EVertex { +func (s *Sprite) Draw(c gg.Context) *gg.Drawing { // Nothing to draw. if s.Images[0] == nil { return nil @@ -28,13 +27,13 @@ func (s *Sprite) Draw(c Context) []EVertex { t := s.GetRectangleToDraw().Transform m := t.GetMatrice() - if !s.Floating { - m.Concat(c.Camera.GetRealMatrix()) + if !s.IsFloating() { + m.Concat(c.Camera().GetRealMatrice(c)) } // Drawing without shader. if s.Shader == nil { - c.DrawImage(s.Images[0], &ebiten.DrawImageOptions{ + c.Image().DrawImage(s.Images[0], &ebiten.DrawImageOptions{ GeoM: m, }) return nil @@ -42,7 +41,7 @@ func (s *Sprite) Draw(c Context) []EVertex { w, h := s.Images[0].Size() // Drawing with shader. - c.DrawRectShader( + c.Image().DrawRectShader( w, h, s.Shader, &ebiten.DrawRectShaderOptions{ @@ -63,8 +62,8 @@ func (s *Sprite) GetRectangleToDraw() Rectangle { w, h := s.Images[0].Size() t := s.Transform t.SetAround( - t.Around().Mul( - V(Float(w), Float(h)), + t.GetAround().Mul( + mx.Vector{mx.Float(w), mx.Float(h)}, ), ) @@ -87,15 +86,15 @@ func (s *Sprite) GetRectangle() Rectangle { return Rectangle{ Transform: t, - Width: Float(w), - Height: Float(h), + Width: mx.Float(w), + Height: mx.Float(h), } } // Get triangles of the rectangle that contains the sprite // and has the same widght and height. -func (s *Sprite) MakeTriangles() Triangles { - return s.Rectangle().MakeTriangles() +func (s *Sprite) MakeTriangles() mx.Triangles { + return s.GetRectangle().MakeTriangles() } func (s *Sprite) Vertices() mx.Vectors { @@ -106,10 +105,14 @@ func (s *Sprite) Edges() mx.Lines { return s.GetRectangle().Edges() } -func (s *Sprite) ContainsPoint(pt mx.Vector) bool { +func (s *Sprite) ContainsPoint( + pt mx.Vector, +) bool { return s.GetRectangle().ContainsPoint(pt) } -func (s *Sprite) GetContainedPoints(pts mx.Vectors) Points { - return s.Rectangle().GetContainedPoints(pts) +func (s *Sprite) GetContainedPoints( + pts mx.Vectors, +) mx.Vectors { + return s.GetRectangle().GetContainedPoints(pts) } diff --git a/ox/text.go b/ox/text.go index d3036a9..69f6415 100644 --- a/ox/text.go +++ b/ox/text.go @@ -1,25 +1,36 @@ package ox -import "surdeus.su/core/gg/mx" +//import "surdeus.su/core/gg/mx" import "surdeus.su/core/gg" +import "github.com/hajimehoshi/ebiten/v2/text" +import "github.com/hajimehoshi/ebiten/v2" // The type implements basic drawable text. // (Now needs to implement rotation, scaling etc, cause now only position) type Text struct { ObjectImpl - mx.Transform - Data string - Face Face + Transform + Colority Visibility + Shaderity + Floatity + + Face gg.Face + Data string } -func (txt *Text) Draw(c gg.Context) []EVertex { - m := txt.Matrix() - m.Concat(c.Camera.RealMatrix()) +func (txt *Text) Draw(c gg.Context) *gg.Drawing { + m := txt.Transform.GetMatrice() + if !txt.IsFloating() { + m.Concat(c.Camera().GetRealMatrice(c)) + } //x, y := txt.Position.XY() //text.Draw(c.Image) - text.DrawWithOptions(c.Image, txt.Data, txt.Face, + text.DrawWithOptions( + c.Image(), + txt.Data, + txt.Face, &ebiten.DrawImageOptions{ GeoM: m, }, diff --git a/ox/transform.go b/ox/transform.go index 3d66014..5aeb247 100644 --- a/ox/transform.go +++ b/ox/transform.go @@ -43,7 +43,7 @@ func T() Transform { // Returns whether it needs to be recalculated // or not. func (t *Transform) IsDirty() bool { - return t.dirty + return t.dirty || t.parentDirty } // For implementing the Transformer on embedding. diff --git a/ox/tri.go b/ox/tri.go index 53d886b..089e968 100644 --- a/ox/tri.go +++ b/ox/tri.go @@ -1,20 +1,35 @@ package ox +import "surdeus.su/core/gg/mx" +import "surdeus.su/core/gg" +//import "github.com/hajimehoshi/ebiten/v2" + type DrawableTriangles struct { - Triangles - Colority + mx.Triangles + + Drawity } -func (r *DrawableTriangles) MakeEVertices(c *Context) []EVertex { - m := c.Camera.RealMatrix() - vs := make([]ebiten.Vertex, len(r.Triangles) * 3) - var buf Vertex +func (r *DrawableTriangles) MakeVertices( + c gg.Context, +) gg.Vertices { + m := c.Camera().GetRealMatrice(c) + vs := make(gg.Vertices, len(r.Triangles) * 3) + var buf gg.Vertice buf.Color = r.Color for i := range r.Triangles { for j := range r.Triangles[i] { buf.Dst = r.Triangles[i][j].Apply(m) - vs[i*3 + j] = buf.Ebiten() + vs[i*3 + j] = buf } } return vs } + +func (r *DrawableTriangles) Draw( + c gg.Context, +) *gg.Drawing { + return &gg.Drawing{ + Vertices: r.MakeVertices(c), + } +} diff --git a/tag.go b/tag.go new file mode 100644 index 0000000..a49d737 --- /dev/null +++ b/tag.go @@ -0,0 +1,5 @@ +package gg + +type Tag int64 +type TagMap map[Tag] struct{} + diff --git a/text.go b/text.go index 5ac62dd..a743cd2 100644 --- a/text.go +++ b/text.go @@ -4,8 +4,6 @@ import ( //"strings" "golang.org/x/image/font" "golang.org/x/image/font/opentype" - //"github.com/hajimehoshi/ebiten/v2/text" - //"github.com/hajimehoshi/ebiten/v2" "io" //"fmt" ) diff --git a/vector.go b/vector.go new file mode 100644 index 0000000..40b3daa --- /dev/null +++ b/vector.go @@ -0,0 +1,4 @@ +package gg + +//import "surdeus.su/core/gg/mx" + diff --git a/vertice.go b/vertice.go index 71ec517..758adfb 100644 --- a/vertice.go +++ b/vertice.go @@ -12,15 +12,26 @@ type Vertice struct { Color } +// Convert the vertice into the Ebiten's type. func (v Vertice) ToAPI() EVertice { + r, g, b, a := v.RGBA() return EVertice { DstX: float32(v.Dst.X), DstY: float32(v.Dst.Y), SrcX: float32(v.Src.X), SrcY: float32(v.Src.Y), - ColorR: float32(v.Color.R)/(float32(MaxColorValue)), - ColorG: float32(v.Color.G)/(float32(MaxColorValue)), - ColorB: float32(v.Color.B)/(float32(MaxColorValue)), - ColorA: float32(v.Color.A)/(float32(MaxColorValue)), + ColorR: float32(r)/(float32(MaxColorValue)), + ColorG: float32(g)/(float32(MaxColorValue)), + ColorB: float32(b)/(float32(MaxColorValue)), + ColorA: float32(a)/(float32(MaxColorValue)), } } + +type Vertices []Vertice +func (vs Vertices) ToAPI() []EVertice { + ret := make([]EVertice, len(vs)) + for i, v := range vs { + ret[i] = v.ToAPI() + } + return ret +}