feat: using the new Context model I perform everywhere.

This commit is contained in:
Andrey Parhomenko 2023-12-20 22:39:33 +03:00
parent 4fdb569bca
commit d4ac7909db
13 changed files with 114 additions and 102 deletions

View file

@ -4,6 +4,7 @@ package gg
// for the main window.
type Camera struct {
Transform
buf *Matrix
}
// Returns the matrix satysfying camera
@ -12,22 +13,24 @@ type Camera struct {
// transform to display on the screen.
// (Should implement buffering it so we do not
// need to calculate it each time for each object. )
func (c *Camera)RealMatrix(
e *Engine,
) Matrix {
func (c *Camera)RealMatrix() Matrix {
g := &Matrix{}
g.Translate(-c.P.X, -c.P.Y)
g.Rotate(c.R)
g.Scale(c.S.X, c.S.Y)
g.Translate(c.RA.X, c.RA.Y)
c.buf = g
return *g
}
func (c *Camera) AbsMatrix(
e *Engine,
) Matrix {
m := c.RealMatrix(e)
// The matrix to convert things into the
// inside engine representation,
// get the position of cursor inside the world
// basing on its window position.
func (c *Camera) AbsMatrix() Matrix {
m := c.RealMatrix()
m.Invert()
return m
}

View file

@ -11,6 +11,8 @@ import (
"math/rand"
)
type Context = gg.Context
const (
HighestL gg.Layer = -iota
DebugL
@ -28,6 +30,7 @@ type Player struct {
}
type Debug struct {
gg.Visibility
gg.Layer
}
@ -98,11 +101,15 @@ func NewRect() *Rect {
return ret
}
func (r *Rect) Update(e *gg.Engine) error {
func (r *Rect) Update(c *Context) error {
//r.R += 0.3 * e.DT()
r.P = c.AbsCursorPosition()
return nil
}
func (r *Rect) Event(c *Context) {
}
var (
playerImg *gg.Image
player *Player
@ -134,8 +141,8 @@ func NewPlayer() *Player {
return ret
}
func (p *Player) Draw(e *gg.Engine, i *gg.Image) {
p.Sprite.Draw(e, i)
func (p *Player) Draw(c *Context) {
p.Sprite.Draw(c)
t := p.Transform
t.S.X *= 4.
t.S.Y *= 4.
@ -146,31 +153,31 @@ func (p *Player) Draw(e *gg.Engine, i *gg.Image) {
Rectangle: rectMove,
Color: gg.Color{0, 0, gg.MaxColorV, gg.MaxColorV},
}
r.Draw(e, i)
r.Draw(c)
}
func (p *Player) Start(e *gg.Engine, v ...any) {
func (p *Player) Start(c *Context) {
fmt.Println("starting")
c := e.Camera()
c.RA = gg.V(360, 240)
cam := c.Camera()
cam.RA = gg.V(360, 240)
}
func (p *Player) Update(e *gg.Engine) error {
dt := e.DT()
c := e.Camera()
keys := e.Keys()
func (p *Player) Update(c *Context) error {
dt := c.DT()
cam := c.Camera()
keys := c.Keys()
p.Uniforms["Random"] = any(rand.Float32())
for _, v := range keys {
switch v {
case ebiten.KeyArrowUp:
c.P.Y += p.MoveSpeed * dt
cam.P.Y += p.MoveSpeed * dt
case ebiten.KeyArrowLeft:
c.P.X -= p.MoveSpeed * dt
cam.P.X -= p.MoveSpeed * dt
case ebiten.KeyArrowDown:
c.P.Y -= p.MoveSpeed * dt
cam.P.Y -= p.MoveSpeed * dt
case ebiten.KeyArrowRight:
c.P.X += p.MoveSpeed * dt
cam.P.X += p.MoveSpeed * dt
case ebiten.KeyW:
p.P.Y += p.MoveSpeed * dt
case ebiten.KeyA:
@ -180,61 +187,61 @@ func (p *Player) Update(e *gg.Engine) error {
case ebiten.KeyD:
p.P.X += p.MoveSpeed * dt
case ebiten.KeyR:
c.R += gg.Pi * p.ScaleSpeed * dt
cam.R += gg.Pi * p.ScaleSpeed * dt
case ebiten.KeyT:
c.R -= gg.Pi * p.ScaleSpeed * dt
cam.R -= gg.Pi * p.ScaleSpeed * dt
case ebiten.KeyRightBracket:
if e.IsPressed(ebiten.KeyShift) {
if c.IsPressed(gg.KeyShift) {
p.R -= gg.Pi * 0.3 * dt
} else {
p.R += gg.Pi * 0.3 * dt
}
case ebiten.KeyF:
if e.IsPressed(ebiten.KeyShift) {
c.S.X -= gg.Pi * p.ScaleSpeed * dt
case gg.KeyF:
if c.IsPressed(ebiten.KeyShift) {
cam.S.X -= gg.Pi * p.ScaleSpeed * dt
} else {
c.S.X += gg.Pi * p.ScaleSpeed * dt
cam.S.X += gg.Pi * p.ScaleSpeed * dt
}
case ebiten.KeyG:
if e.IsPressed(ebiten.KeyShift) {
c.S.Y -= gg.Pi * p.ScaleSpeed * dt
case gg.KeyG:
if c.IsPressed(ebiten.KeyShift) {
cam.S.Y -= gg.Pi * p.ScaleSpeed * dt
} else {
c.S.Y += gg.Pi * p.ScaleSpeed * dt
cam.S.Y += gg.Pi * p.ScaleSpeed * dt
}
case ebiten.KeyZ:
if e.IsPressed(ebiten.KeyShift) {
c.RA.X -= gg.Pi * p.MoveSpeed * dt
case gg.KeyZ:
if c.IsPressed(ebiten.KeyShift) {
cam.RA.X -= gg.Pi * p.MoveSpeed * dt
} else {
c.RA.X += gg.Pi * p.MoveSpeed * dt
cam.RA.X += gg.Pi * p.MoveSpeed * dt
}
case ebiten.KeyX:
if e.IsPressed(ebiten.KeyShift) {
c.RA.Y -= gg.Pi * p.MoveSpeed * dt
case gg.KeyX:
if c.IsPressed(ebiten.KeyShift) {
cam.RA.Y -= gg.Pi * p.MoveSpeed * dt
} else {
c.RA.Y += gg.Pi * p.MoveSpeed * dt
cam.RA.Y += gg.Pi * p.MoveSpeed * dt
}
case ebiten.KeyV:
if e.IsPressed(ebiten.KeyShift) {
case gg.KeyV:
if c.IsPressed(ebiten.KeyShift) {
tri.R -= gg.Pi * 0.3 * dt
} else {
tri.R += gg.Pi * 0.3 * dt
}
case ebiten.KeyLeftBracket:
if e.IsPressed(ebiten.KeyShift) {
case gg.KeyLeftBracket:
if c.IsPressed(ebiten.KeyShift) {
rect.R -= gg.Pi * 0.3 * dt
} else {
rect.R += gg.Pi * 0.3 * dt
}
case ebiten.Key0:
e.Del(p)
case ebiten.KeyB:
case gg.Key0:
c.Del(p)
case gg.KeyB:
}
}
return nil
}
func (p *Player) Event(e *gg.Engine, ev any) {
func (p *Player) Signal(e *gg.Engine, ev any) {
fmt.Println("event:", ev)
switch ec := ev.(type) {
case *gg.KeyDown:
@ -249,10 +256,8 @@ func (p *Player) Event(e *gg.Engine, ev any) {
}
}
func (d *Debug) Draw(
e *gg.Engine,
i *gg.Image,
) {
func (d *Debug) Draw(c *Context) {
e := c.Engine
keyStrs := []string{}
for _, k := range e.Keys() {
keyStrs = append(keyStrs, k.String())
@ -270,7 +275,7 @@ func (d *Debug) Draw(
keyStrs = append(keyStrs, fmt.Sprintf("%v", e.CursorPosition()))
keyStrs = append(keyStrs, fmt.Sprintf("%v", e.AbsCursorPosition()))
e.DebugPrint(i,
e.DebugPrint(c.Image,
strings.Join(keyStrs, ", "))
}

7
context.go Normal file
View file

@ -0,0 +1,7 @@
package gg
type Context struct {
*Engine
*Image
Event any
}

View file

@ -96,7 +96,9 @@ func (e *Engine) Add(b any) error {
starter, ok := b.(Starter)
if ok {
starter.Start(e)
starter.Start(&Context{
Engine: e,
})
}
e.objects.Set(object, struct{}{})
@ -113,7 +115,9 @@ func (e *Engine) Del(b any) error {
deleter, ok := b.(Deleter)
if ok {
deleter.Delete(e)
deleter.Delete(&Context{
Engine: e,
})
}
e.objects.Del(b)
@ -152,14 +156,19 @@ func (e *engine) Update() error {
eventer, ok := object.(Eventer)
if ok {
for _, event := range events {
eventer.Event(eng, event)
eventer.Event(&Context{
Engine: eng,
Event: event,
})
}
}
updater, ok := object.(Updater)
if !ok {
continue
}
err = updater.Update(eng)
err = updater.Update(&Context{
Engine: eng,
})
if err != nil {
return err
}
@ -193,7 +202,10 @@ func (e *engine) Draw(i *ebiten.Image) {
layers := maps.NewSparse[Layer, []Drawer](nil, m)
for layer := range layers.Chan() {
for _, drawer := range layer {
drawer.Draw(eng, i)
drawer.Draw(&Context{
Engine: eng,
Image: i,
})
}
}
}

View file

@ -4,10 +4,6 @@ import (
//"github.com/hajimehoshi/ebiten/v2"
)
type Eventer interface {
Event(e *Engine, ev any)
}
func keyDiff(s1, s2 []Key) []Key {
combinedSlice := append(s1, s2...)
dm := make(map[Key]int)
@ -37,7 +33,6 @@ type KeyUp struct {
Key
}
type MouseButtonDown struct {
MouseButton
P Vector

View file

@ -2,7 +2,7 @@ package gg
import (
"math"
"fmt"
//"fmt"
)
// The type represents mathematical equation of line and line itself.

View file

@ -13,7 +13,7 @@ func (e *Engine) CursorPosition() Vector {
func (e *Engine) AbsCursorPosition() Vector {
m := &Matrix{}
m.Concat(e.Camera().AbsMatrix(e))
m.Concat(e.Camera().AbsMatrix())
return e.CursorPosition().Apply(m)
}

View file

@ -1,28 +1,35 @@
package gg
// Implementing the interface lets the object
// to handle emited events.
type Eventer interface {
Event(*Context)
}
// Implementing the interface type
// will call the function OnStart
// when first appear on scene BEFORE
// the OnUpdate.
// The v value will be get from Add function.
type Starter interface {
Start(*Engine)
Start(*Context)
}
// Implementing the interface type
// will call the function on each
// engine iteration.
type Updater interface {
Update(*Engine) error
Update(*Context) error
}
// Implementing the interface type
// will call the function on deleting
// the object.
type Deleter interface {
Delete(*Engine, ...any)
Delete(*Context)
}
// Feat to embed for turning visibility on and off.
type Visibility struct {
Visible bool
}
@ -30,15 +37,16 @@ func (v Visibility) IsVisible() bool {
return v.Visible
}
// Feat to embed to make colorful objects.
type Colority struct {
Color Color
}
// The interface describes anything that can be
// drawn. It will be drew corresponding to
// the layers order.
// the layers order so the layer must be returned.
type Drawer interface {
Draw(*Engine, *Image)
Draw(*Context)
GetLayer() Layer
IsVisible() bool
}

View file

@ -38,15 +38,12 @@ func (p *Polygon) MakeTriangles() Triangles {
return ret
}
func (p *DrawablePolygon) Draw(
e *Engine,
i *Image,
) {
func (p *DrawablePolygon) Draw(c *Context) {
(&DrawableTriangles{
Visibility: p.Visibility,
Colority: p.Colority,
ShaderOptions: p.ShaderOptions,
Triangles: p.MakeTriangles(),
}).Draw(e, i)
}).Draw(c)
}

11
rect.go
View file

@ -73,12 +73,9 @@ func (r *DrawableRectangle) IsVisible() bool {
return r.Visible
}
func (r *DrawableRectangle) Draw(
e *Engine,
i *Image,
) {
func (r *DrawableRectangle) Draw(c *Context) {
m := r.Matrix()
rm := e.Camera().RealMatrix(e)
rm := c.Camera().RealMatrix()
m.Concat(rm)
// Draw solid color if no shader.
if r.Shader == nil {
@ -89,7 +86,7 @@ func (r *DrawableRectangle) Draw(
opts := &ebiten.DrawImageOptions{
GeoM: m,
}
i.DrawImage(img, opts)
c.DrawImage(img, opts)
return
}
@ -117,6 +114,6 @@ func (r *DrawableRectangle) Draw(
Images: r.Images,
Uniforms: r.Uniforms,
}
i.DrawRectShader(w, h, r.Shader, opts)
c.DrawRectShader(w, h, r.Shader, opts)
}

View file

@ -10,10 +10,7 @@ type Sprite struct {
Floating, Visible bool
}
func (s *Sprite) Draw(
e *Engine,
i *Image,
) {
func (s *Sprite) Draw(c *Context) {
// Nothing to draw.
if s.Images[0] == nil {
return
@ -23,16 +20,14 @@ func (s *Sprite) Draw(
m := &Matrix{}
m.Concat(t.Matrix())
if !s.Floating {
m.Concat(e.Camera().RealMatrix(
e,
))
m.Concat(c.Camera().RealMatrix())
}
// Drawing without shader.
if s.Shader == nil {
opts := &ebiten.DrawImageOptions{}
opts.GeoM = *m
i.DrawImage(s.Images[0], opts)
c.DrawImage(s.Images[0], opts)
return
}
@ -43,7 +38,7 @@ func (s *Sprite) Draw(
Uniforms: s.Uniforms,
GeoM: *m,
}
i.DrawRectShader(w, h, s.Shader, opts)
c.DrawRectShader(w, h, s.Shader, opts)
}
// Check is sprite is visible.

View file

@ -88,11 +88,8 @@ func (ts Triangles) ContainsPoint(p Point) bool {
return false
}
func (r *DrawableTriangles) Draw(
e *Engine,
i *Image,
) {
m := e.Camera().RealMatrix(e)
func (r *DrawableTriangles) Draw(c *Context) {
m := c.Camera().RealMatrix()
cm := &m
// Draw solid color if no shader.
@ -115,7 +112,7 @@ func (r *DrawableTriangles) Draw(
img := NewImage(1, 1)
img.Set(0, 0, r.Color)
i.DrawTriangles(vs, is, img, &r.DrawTrianglesOptions)
c.DrawTriangles(vs, is, img, &r.DrawTrianglesOptions)
return
}

View file

@ -14,10 +14,6 @@ type Point = Vector
type Vectors []Vector
type Points []Point
type PointContainer interface {
ContainsPoint(Point) bool
}
func V(x, y Float) Vector {
return Vector{x, y}
}