feat: implemented layering for DrawableTriangles.

This commit is contained in:
Andrey Parhomenko 2024-01-11 06:39:57 +03:00
parent 08c950a669
commit 0f6732bcf9
9 changed files with 103 additions and 121 deletions

View file

@ -11,17 +11,17 @@ type Debug struct {
gg.Object
}
func (d *Debug) Draw(c *Context) {
func (d *Debug) Draw(c *Context) []gg.EVertex {
e := c.Engine
keyStrs := []string{}
keyStrs = append(keyStrs, fmt.Sprintf(
"counter: %d", counter,
))
keyStrs = append(keyStrs, fmt.Sprintf(
"tps: %d", int(c.TPS()),
"tps: %d", int(c.Tps()),
))
keyStrs = append(keyStrs, fmt.Sprintf(
"fps: %d", int(c.FPS()),
"fps: %d", int(c.Fps()),
))
keyStrs = append(keyStrs, fmt.Sprintf(
"relPlayerPos: %v", player.Position,
@ -75,6 +75,7 @@ func (d *Debug) Draw(c *Context) {
e.DebugPrint(c.Image,
strings.Join(keyStrs, "\n"))
return nil
}
func (d *Debug) IsVisible() bool { return true }

View file

@ -36,27 +36,11 @@ func NewPlayer() *Player {
func (p *Player) Start(c *Context) {
}
// Custom drawing function.
func (p *Player) Draw(c *Context) {
p.Sprite.Draw(c)
return
t := p.Transform
t.Scale.X *= 4.
t.Scale.Y *= 4.
r := &gg.DrawableRectangle{}
r.Color = gg.Rgba(0, 0, 1, 1)
r.Rectangle = gg.Rectangle{
Transform: t,
}
r.Draw(c)
}
func (p *Player) Update(c *Context) {
if p.Spawned {
return
}
dt := c.DT()
dt := c.Dt()
cam := c.Camera
keys := c.Keys()
@ -140,7 +124,7 @@ func (p *Player) Update(c *Context) {
c.Camera.Position = pos.Sub(ec.Abs)
case *gg.WheelChange:
c.Camera.Scale = c.Camera.Scale.Add(gg.V2(
ec.Offset.Y * c.DT() * p.ScaleSpeed * 40,
ec.Offset.Y * c.Dt() * p.ScaleSpeed * 40,
))
}}
}

View file

@ -32,7 +32,7 @@ func NewTri() *Tri {
}
func (t *Tri) Update(c *Context) {
dt := c.DT()
dt := c.Dt()
if t.ContainsPoint(c.AbsCursorPosition()) {
t.Color = gg.Rgba(0, 1, 0, 1)
} else {
@ -53,12 +53,12 @@ func (t *Tri) Update(c *Context) {
case gg.KeyM:
absPos := t.AbsPosition()
t.SetAbsPosition(
absPos.Add(gg.V(0, 100*c.DT()*d)),
absPos.Add(gg.V(0, 100*c.Dt()*d)),
)
case gg.KeyN:
absPos := t.AbsPosition()
t.SetAbsPosition(
absPos.Add(gg.V(100*c.DT()*d, 0)),
absPos.Add(gg.V(100*c.Dt()*d, 0)),
)
case gg.KeyV:
t.Rotation += d * gg.Pi * 0.3 * dt

View file

@ -11,7 +11,7 @@ import (
)
const (
LayerBufSize = 0
MaxVertices = 1 << 16
)
type GraphicsLibrary = ebiten.GraphicsLibrary
@ -64,7 +64,7 @@ type Engine struct {
// The same delta time for all frames
// and all objects.
lastTime time.Time
dt Float
dt, fdt Float
// Temporary stuff
keys, prevKeys []Key
@ -75,8 +75,8 @@ type Engine struct {
wg sync.WaitGroup
//bufs [LayerBufSize]*Image
vertices []ebiten.Vertex
vindices []uint16
vertices map[Layer] []ebiten.Vertex
//vindices []uint16
}
type engine Engine
@ -297,9 +297,22 @@ func (e *engine) Update() error {
return nil
}
func (e *engine) Draw(i *ebiten.Image) {
e.vindices = []uint16{}
e.vertices = []ebiten.Vertex{}
var (
fullPageIndexes = func() [MaxVertices]uint16 {
ret := [MaxVertices]uint16{}
for i:=0 ; i<len(ret) ; i++ {
ret[i] = uint16(i)
}
return ret
}()
defaultPageImg = func() *Image {
img := NewImage(1, 1)
img.Set(0, 0, Rgba(1, 1, 1, 1))
return img
}()
defaultTriOptions = &ebiten.DrawTrianglesOptions{}
)
func (e *engine) Draw(img *ebiten.Image) {
e.dt = time.Since(e.lastTime).Seconds()
eng := (*Engine)(e)
m := map[Layer][]Drawer{}
@ -319,17 +332,39 @@ func (e *engine) Draw(i *ebiten.Image) {
m[l] = append(layer, object)
}
// Drawing layers.
// Drawing layers via the sparse array.
// First drawing via the inside function
// and then the returned []EVertex.
layers := maps.NewSparse[Layer, []Drawer](nil, m)
c := &Context{Engine: eng, typ: drawContext, Image: i}
c := &Context{Engine: eng, typ: drawContext, Image: img}
for layer := range layers.Chan() {
vertices := []EVertex{}
for _, drawer := range layer {
drawer.Draw(c)
vs := drawer.Draw(c)
if vs != nil {
vertices = append(vertices, vs...)
}
}
pn := len(vertices) / MaxVertices
mod := len(vertices) % MaxVertices
for i := 0 ; i<pn ; i++ {
cur := i*MaxVertices
img.DrawTriangles(
vertices[cur:cur+MaxVertices],
fullPageIndexes[:],
defaultPageImg,
defaultTriOptions,
)
}
st := pn*MaxVertices
img.DrawTriangles(
vertices[st:],
fullPageIndexes[:mod],
defaultPageImg,
defaultTriOptions,
)
}
img := NewImage(1, 1)
img.Set(0, 0, Rgba(1, 1, 1, 1))
i.DrawTriangles(e.vertices, e.vindices, img, &ebiten.DrawTrianglesOptions{})
// Empty the buff to generate it again.
eng.Camera.buffered = false
@ -344,15 +379,21 @@ func (e *engine) Layout(ow, oh int) (int, int) {
return ow, oh
}
// Return the delta time duration value.
func (e *Engine) DT() Float {
// Return the delta time.
func (e *Engine) Dt() Float {
return e.dt
}
func (e *Engine) FPS() float64 {
// Return the current fixed delta time.
func (e *Engine) Fdt() Float {
return 1/60
}
func (e *Engine) Fps() float64 {
return ebiten.ActualFPS()
}
func (e *Engine) TPS() float64 {
func (e *Engine) Tps() float64 {
return ebiten.ActualTPS()
}

View file

@ -40,7 +40,7 @@ type Colority struct {
// drawn. It will be drew corresponding to
// the layers order so the layer must be returned.
type Drawer interface {
Draw(*Context)
Draw(*Context) []EVertex
GetLayer() Layer
IsVisible() bool
}
@ -66,6 +66,6 @@ func (o *Object) Input() chan *Context { return o.input }
func (o *Object) Start(c *Context) {}
func (o *Object) Update(c *Context) {}
func (o *Object) Draw(c *Context) {}
func (o *Object) Draw(c *Context) []EVertex { return nil}
func (o *Object) Delete(c *Context) {}

View file

@ -37,12 +37,10 @@ func (p Polygon) MakeTriangles() Triangles {
return ret
}
func (p *DrawablePolygon) Draw(c *Context) {
(&DrawableTriangles{
Visibility: p.Visibility,
func (p *DrawablePolygon) Draw(c *Context) []EVertex {
return (&DrawableTriangles{
Colority: p.Colority,
ShaderOptions: p.ShaderOptions,
Triangles: p.MakeTriangles(),
}).Draw(c)
}).MakeEVertices(c)
}

31
rect.go
View file

@ -1,7 +1,7 @@
package gg
import (
"github.com/hajimehoshi/ebiten/v2"
//"github.com/hajimehoshi/ebiten/v2"
//"github.com/hajimehoshi/ebiten/v2/vector"
//"fmt"
//"image"
@ -48,7 +48,7 @@ func (r Rectangle) Edges() Edges {
}
// Get 2 triangles that the rectangle consists of.
func (r Rectangle) Triangles() Triangles {
func (r Rectangle) MakeTriangles() Triangles {
pts := r.Vertices()
p1 := pts[0]
p2 := pts[1]
@ -63,7 +63,7 @@ func (r Rectangle) Triangles() Triangles {
// Check whether the rectangle contains the point.
func (r Rectangle) ContainsPoint(p Point) bool {
return r.Triangles().ContainsPoint(p)
return r.MakeTriangles().ContainsPoint(p)
}
// Check whether the drawable rectangle should be drawn.
@ -71,23 +71,13 @@ func (r *DrawableRectangle) IsVisible() bool {
return r.Visible
}
func (r *DrawableRectangle) Draw(c *Context) {
m := r.Matrix()
rm := c.Camera.RealMatrix()
m.Concat(rm)
// Draw solid color if no shader.
if r.Shader == nil {
img := NewImage(1, 1)
img.Set(0, 0, r.Color)
func (r *DrawableRectangle) Draw(c *Context) []EVertex {
return (&DrawableTriangles{
Colority: r.Colority,
Triangles: r.MakeTriangles(),
}).MakeEVertices(c)
c.DrawImage(img, &ebiten.DrawImageOptions{
GeoM: m,
})
return
}
// Use the Color as base image if no is provided.
/*// Use the Color as base image if no is provided.
//var did bool
if r.Images[0] == nil {
r.Images[0] = NewImage(1, 1)
@ -101,6 +91,7 @@ func (r *DrawableRectangle) Draw(c *Context) {
GeoM: m,
Images: r.Images,
Uniforms: r.Uniforms,
})
})*/
return nil
}

View file

@ -17,10 +17,10 @@ var (
//spritesOp DrawImageOptions
)
func (s *Sprite) Draw(c *Context) {
func (s *Sprite) Draw(c *Context) []EVertex {
// Nothing to draw.
if s.Images[0] == nil {
return
return nil
}
t := s.Rectangle().Transform
@ -34,7 +34,7 @@ func (s *Sprite) Draw(c *Context) {
c.DrawImage(s.Images[0], &ebiten.DrawImageOptions{
GeoM: m,
})
return
return nil
}
w, h := s.Images[0].Size()
@ -44,6 +44,7 @@ func (s *Sprite) Draw(c *Context) {
Uniforms: s.Uniforms,
GeoM: m,
})
return nil
}
// Return the rectangle that contains the sprite.
@ -64,7 +65,7 @@ func (s *Sprite) Rectangle() Rectangle {
// Get triangles of the rectangle that contains the sprite
// and has the same widght and height.
func (s *Sprite) Triangles() Triangles {
return s.Rectangle().Triangles()
func (s *Sprite) MakeTriangles() Triangles {
return s.Rectangle().MakeTriangles()
}

View file

@ -5,6 +5,8 @@ import (
"github.com/hajimehoshi/ebiten/v2"
)
type EVertex = ebiten.Vertex
// Ebitens vector in better abstractions like Vectors.
type Vertex struct {
Dst Vector
@ -16,14 +18,11 @@ type Triangle [3]Vector
type Triangles []Triangle
type DrawableTriangles struct {
Triangles
Visibility
Colority
ShaderOptions
ebiten.DrawTrianglesOptions
}
func (v Vertex) Ebiten() ebiten.Vertex {
return ebiten.Vertex {
func (v Vertex) Ebiten() EVertex {
return EVertex {
DstX: float32(v.Dst.X),
DstY: float32(v.Dst.Y),
SrcX: float32(v.Src.X),
@ -88,50 +87,17 @@ func (ts Triangles) ContainsPoint(p Point) bool {
return false
}
func (r *DrawableTriangles) Draw(c *Context) {
func (r *DrawableTriangles) MakeEVertices(c *Context) []EVertex {
m := c.Camera.RealMatrix()
// Draw solid color if no shader.
if r.Shader == nil {
vs := make([]ebiten.Vertex, len(r.Triangles) * 3)
var buf Vertex
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 := make([]ebiten.Vertex, len(r.Triangles) * 3)
var buf Vertex
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()
}
is := make([]uint16, len(r.Triangles) * 3)
start := len(c.Engine.vindices)
for i := 0 ; i < len(is) ; i++ {
is[i] = uint16(start + i)
}
c.Engine.vertices = append(c.Engine.vertices, vs...)
c.Engine.vindices = append(c.Engine.vindices, is...)
return
//c.DrawTriangles(vs, is, img, &r.DrawTrianglesOptions)
return
}
// Use the Color as base image if no is provided.
/*if r.Images[0] == nil {
r.Images[0] = NewImage(1, 1)
r.Images[0].Set(0, 0, r.Color)
}
w, h := r.Images[0].Size()
// Drawing with shader.
opts := &ebiten.DrawRectShaderOptions{
GeoM: m,
Images: r.Images,
Uniforms: r.Uniforms,
}
i.DrawRectShader(w, h, r.Shader, opts)*/
return vs
}