feat: fixed camera matrix bufferization.

This commit is contained in:
Andrey Parhomenko 2024-01-08 10:22:09 +03:00
parent f4bf94a0e6
commit d378490396
6 changed files with 49 additions and 25 deletions

View file

@ -7,7 +7,8 @@ type Camera struct {
// that the camera shows. // that the camera shows.
ShaderOptions ShaderOptions
Transform Transform
buf *Matrix buffered bool
buf Matrix
engine *Engine engine *Engine
} }
@ -24,20 +25,20 @@ func (e *Engine) NewCamera() *Camera {
// transform to display on the screen. // transform to display on the screen.
func (c *Camera)RealMatrix() Matrix { func (c *Camera)RealMatrix() Matrix {
// Bufferization // Bufferization
if c.buf != nil { if c.buffered {
return *(c.buf) return c.buf
} }
g := &Matrix{} g := Matrix{}
g.Translate(-c.Position.X, -c.Position.Y) g.Translate(-c.Position.X, -c.Position.Y)
g.Rotate(c.Rotation) g.Rotate(c.Rotation)
siz := c.engine.AbsWinSize() siz := c.engine.AbsWinSize()
g.Translate(c.Around.X * siz.X, c.Around.Y * siz.Y) g.Translate(c.Around.X * siz.X, c.Around.Y * siz.Y)
g.Scale(c.Scale.X, c.Scale.Y) g.Scale(c.Scale.X, c.Scale.Y)
c.buf = g c.buf = g
c.buffered = true
return *g return g
} }
// The matrix to convert things into the // The matrix to convert things into the

View file

@ -3,6 +3,7 @@ package main
import ( import (
"vultras.su/core/gg" "vultras.su/core/gg"
"github.com/hajimehoshi/ebiten/v2/examples/resources/images" "github.com/hajimehoshi/ebiten/v2/examples/resources/images"
_ "github.com/silbinarywolf/preferdiscretegpu"
"bytes" "bytes"
"log" "log"
//"strings" //"strings"
@ -34,6 +35,7 @@ func main() {
Width: 720, Width: 720,
Height: 480, Height: 480,
VSync: true, VSync: true,
Fullscreen: true,
}) })
var err error var err error

View file

@ -63,6 +63,15 @@ func (t *Tri) Update(c *Context) {
case gg.KeyV: case gg.KeyV:
t.Rotation += d * gg.Pi * 0.3 * dt t.Rotation += d * gg.Pi * 0.3 * dt
case gg.Key2 : 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),
gg.V(0, -10 - gg.Float(counter)),
})
case gg.Key3 :
if t.Spawned { if t.Spawned {
break break
} }

View file

@ -40,6 +40,10 @@ type WindowConfig struct {
VSync bool VSync bool
} }
type Objects struct {
store []Objecter
}
// The main structure that represents current state of [game] engine. // The main structure that represents current state of [game] engine.
type Engine struct { type Engine struct {
wcfg *WindowConfig wcfg *WindowConfig
@ -47,7 +51,7 @@ type Engine struct {
// The main holder for objects. // The main holder for objects.
// Uses the map structure to quickly // Uses the map structure to quickly
// delete and create new objects. // delete and create new objects.
Objects maps.Map[Objecter, struct{}] Objects *Objects
// The main camera to display in window. // The main camera to display in window.
// If is set to nil then the engine will panic. // If is set to nil then the engine will panic.
@ -103,16 +107,22 @@ func NewEngine(
ret.Camera = ret.NewCamera() ret.Camera = ret.NewCamera()
ret.outerEvents = make(EventChan) ret.outerEvents = make(EventChan)
ret.handleEvents = make(EventChan) ret.handleEvents = make(EventChan)
ret.Objects = maps.NewOrdered[Objecter, struct{}]() ret.Objects = &Objects{}
ret.buttons = MouseButtonMap{} ret.buttons = MouseButtonMap{}
return ret return ret
} }
// Get the real window size in the current context. // Get the real window size in the current context.
func (c *Engine) RealWinSize() Vector { func (c *Engine) RealWinSize() Vector {
var w, h int
if c.wcfg.Fullscreen {
w, h = ebiten.ScreenSizeInFullscreen()
} else {
w, h = c.wcfg.Width, c.wcfg.Height
}
return V( return V(
Float(c.wcfg.Width), Float(w),
Float(c.wcfg.Height), Float(h),
) )
} }
@ -127,35 +137,32 @@ func (e *Engine) EventInput() EventChan {
// Add new object considering what // Add new object considering what
// interfaces it implements. // interfaces it implements.
func (e *Engine) Spawn(b Objecter) error { func (e *Engine) Spawn(b Objecter) error {
if e.Objects.Has(b) { /*if e.Objects.Has(b) {
return ObjectExistErr return ObjectExistErr
} }*/
b.Start(&Context{Engine: e}) b.Start(&Context{Engine: e})
obj := b.GetObject() obj := b.GetObject()
obj.input = make(chan *Context) obj.input = make(chan *Context)
go func() { go func() {
for c := range obj.input { for c := range obj.input {
switch c.typ {
case updateContext:
b.Update(c) b.Update(c)
}
e.wg.Done() e.wg.Done()
} }
}() }()
e.Objects.Set(b, struct{}{}) e.Objects.store = append(e.Objects.store, b)
return nil return nil
} }
// Delete object from Engine. // Delete object from Engine.
func (e *Engine) Del(b Objecter) error { func (e *Engine) Del(b Objecter) error {
if !e.Objects.Has(b) { /*if !e.Objects.Has(b) {
return ObjectNotExistErr return ObjectNotExistErr
} }
b.Delete(&Context{Engine: e}) b.Delete(&Context{Engine: e})
e.Objects.Del(b) e.Objects.Del(b)*/
return nil return nil
} }
@ -206,7 +213,6 @@ func (e *Engine) AbsCursorPosition() Vector {
func (e *engine) Update() error { func (e *engine) Update() error {
eng := (*Engine)(e) eng := (*Engine)(e)
e.dt = time.Since(e.lastTime).Seconds()
// Buffering the context for faster. // Buffering the context for faster.
e.prevKeys = e.keys e.prevKeys = e.keys
@ -274,20 +280,20 @@ func (e *engine) Update() error {
typ: updateContext, typ: updateContext,
Events: events, Events: events,
} }
for object := range e.Objects.KeyChan() { for _, object := range e.Objects.store {
e.wg.Add(1) e.wg.Add(1)
object.Input() <- c object.Input() <- c
} }
e.wg.Wait() e.wg.Wait()
e.lastTime = time.Now()
return nil return nil
} }
func (e *engine) Draw(i *ebiten.Image) { func (e *engine) Draw(i *ebiten.Image) {
e.dt = time.Since(e.lastTime).Seconds()
eng := (*Engine)(e) eng := (*Engine)(e)
m := map[Layer][]Drawer{} m := map[Layer][]Drawer{}
for object := range eng.Objects.KeyChan() { for _, object := range eng.Objects.store {
// Skipping the ones we do not need to draw. // Skipping the ones we do not need to draw.
if !object.IsVisible() { if !object.IsVisible() {
continue continue
@ -311,8 +317,10 @@ func (e *engine) Draw(i *ebiten.Image) {
drawer.Draw(c) drawer.Draw(c)
} }
} }
// Empty the buff to generate it again. // Empty the buff to generate it again.
eng.Camera.buf = nil eng.Camera.buffered = false
e.lastTime = time.Now()
} }
func (e *engine) Layout(ow, oh int) (int, int) { func (e *engine) Layout(ow, oh int) (int, int) {
@ -341,6 +349,7 @@ func (e *Engine) Run() error {
ebiten.SetWindowSize(e.wcfg.Width, e.wcfg.Height) ebiten.SetWindowSize(e.wcfg.Width, e.wcfg.Height)
ebiten.SetWindowSizeLimits(1, 1, e.wcfg.Width, e.wcfg.Height) ebiten.SetWindowSizeLimits(1, 1, e.wcfg.Width, e.wcfg.Height)
ebiten.SetFullscreen(e.wcfg.Fullscreen)
ebiten.SetVsyncEnabled(e.wcfg.VSync) ebiten.SetVsyncEnabled(e.wcfg.VSync)
e.lastTime = time.Now() e.lastTime = time.Now()

3
go.mod
View file

@ -7,6 +7,8 @@ toolchain go1.21.3
require ( require (
github.com/di4f/gods v0.0.0-20231214190239-d523423d8d5e github.com/di4f/gods v0.0.0-20231214190239-d523423d8d5e
github.com/hajimehoshi/ebiten/v2 v2.6.0-alpha.3.0.20230521122940-90562ee84b9b github.com/hajimehoshi/ebiten/v2 v2.6.0-alpha.3.0.20230521122940-90562ee84b9b
github.com/silbinarywolf/preferdiscretegpu v1.0.0
golang.org/x/image v0.7.0
) )
require ( require (
@ -14,7 +16,6 @@ require (
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b // indirect github.com/go-gl/glfw/v3.3/glfw v0.0.0-20221017161538-93cebf72946b // indirect
github.com/jezek/xgb v1.1.0 // indirect github.com/jezek/xgb v1.1.0 // indirect
golang.org/x/exp/shiny v0.0.0-20230522175609-2e198f4a06a1 // indirect golang.org/x/exp/shiny v0.0.0-20230522175609-2e198f4a06a1 // indirect
golang.org/x/image v0.7.0 // indirect
golang.org/x/mobile v0.0.0-20230427221453-e8d11dd0ba41 // indirect golang.org/x/mobile v0.0.0-20230427221453-e8d11dd0ba41 // indirect
golang.org/x/sync v0.2.0 // indirect golang.org/x/sync v0.2.0 // indirect
golang.org/x/sys v0.8.0 // indirect golang.org/x/sys v0.8.0 // indirect

2
go.sum
View file

@ -8,6 +8,8 @@ github.com/hajimehoshi/ebiten/v2 v2.6.0-alpha.3.0.20230521122940-90562ee84b9b h1
github.com/hajimehoshi/ebiten/v2 v2.6.0-alpha.3.0.20230521122940-90562ee84b9b/go.mod h1:+fFI6Ag5YvbX1ivNQD2TxNhpWFDPuxEoew421TTQAxI= github.com/hajimehoshi/ebiten/v2 v2.6.0-alpha.3.0.20230521122940-90562ee84b9b/go.mod h1:+fFI6Ag5YvbX1ivNQD2TxNhpWFDPuxEoew421TTQAxI=
github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk= github.com/jezek/xgb v1.1.0 h1:wnpxJzP1+rkbGclEkmwpVFQWpuE2PUGNUzP8SbfFobk=
github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk= github.com/jezek/xgb v1.1.0/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
github.com/silbinarywolf/preferdiscretegpu v1.0.0 h1:tuvXLRCnoFMFyk74/8PFvO0B5rjDmXm0JgNTaOYAHT0=
github.com/silbinarywolf/preferdiscretegpu v1.0.0/go.mod h1:h3s2GkfAP2sWqoS7v/PxAlFOQ1azMRsZxUJNw47QhLc=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=