gg/src/gx/main.go

184 lines
3 KiB
Go
Raw Normal View History

2023-02-17 07:04:29 +03:00
package gx
import (
"github.com/hajimehoshi/ebiten/v2"
2023-02-18 07:46:33 +03:00
"github.com/hajimehoshi/ebiten/v2/inpututil"
"github.com/surdeus/godat/src/sparsex"
2023-04-28 18:03:26 +03:00
"github.com/surdeus/godat/src/poolx"
2023-02-17 23:51:40 +03:00
//"fmt"
"time"
2023-05-22 23:39:01 +03:00
"math"
2023-02-17 07:04:29 +03:00
)
// The type is used in all Engine interactions
// where you need floating values.
type Float = float64
// The type represents order of drawing.
type Layer int
2023-05-02 17:38:34 +03:00
// Window configuration type.
2023-02-17 07:04:29 +03:00
type WindowConfig struct {
Title string
Width, Height int
FixedSize bool
VSync bool
2023-02-17 07:04:29 +03:00
}
2023-05-02 17:38:34 +03:00
// The main structure that represents current state of [game] engine.
2023-02-17 07:04:29 +03:00
type Engine struct {
wcfg *WindowConfig
2023-04-28 18:03:26 +03:00
layers *sparsex.Sparse[Layer, *poolx.Pool[Drawer]]
behavers *poolx.Pool[Behaver]
2023-02-17 23:51:40 +03:00
lastTime time.Time
dt Float
2023-02-18 03:51:43 +03:00
camera *Camera
2023-02-18 07:46:33 +03:00
keys []Key
2023-02-17 07:04:29 +03:00
}
type engine Engine
2023-05-22 23:39:01 +03:00
var (
Infinity = math.MaxFloat64
)
2023-05-02 17:38:34 +03:00
// Return current camera.
2023-02-18 03:51:43 +03:00
func (e *Engine) Camera() *Camera {
return e.camera
}
2023-05-02 17:38:34 +03:00
// Set new current camera.
func (e *Engine) SetCamera(c *Camera) {
e.camera = c
}
2023-05-02 17:38:34 +03:00
// Get currently pressed keys.
2023-02-18 07:46:33 +03:00
func (e *Engine) Keys() []Key {
return e.keys
}
2023-05-02 17:38:34 +03:00
// Returns new empty Engine.
2023-02-17 07:04:29 +03:00
func New(
cfg *WindowConfig,
) *Engine {
return &Engine{
wcfg: cfg,
layers: sparsex.New[
Layer,
2023-04-28 18:03:26 +03:00
*poolx.Pool[Drawer],
](true),
2023-02-18 03:51:43 +03:00
camera: &Camera{
T: Transform{
2023-02-18 07:46:33 +03:00
S: Vector{1, 1},
2023-02-18 03:51:43 +03:00
},
},
2023-04-28 18:03:26 +03:00
behavers: poolx.New[Behaver](),
}
}
2023-02-17 23:51:40 +03:00
// Add new object considering what
// interfaces it implements.
func (e *Engine) Add(l Layer, b any) {
beh, ok := b.(Behaver)
if ok {
2023-05-22 23:39:01 +03:00
e.addBehaver(beh)
2023-02-17 23:51:40 +03:00
}
drw, ok := b.(Drawer)
if ok {
2023-05-22 23:39:01 +03:00
e.addDrawer(l, drw)
2023-02-17 23:51:40 +03:00
}
}
2023-05-02 17:38:34 +03:00
// Del object from Engine.
2023-04-28 18:21:34 +03:00
func (e *Engine) Del(b any) {
drawer, ok := b.(Drawer)
if ok {
for layer := range e.layers.Vals() {
layer.V.Del(drawer)
}
}
behaver, ok := b.(Behaver)
if ok {
e.behavers.Del(behaver)
}
}
2023-05-22 23:39:01 +03:00
func (e *Engine) addDrawer(l Layer, d Drawer) {
g, ok := e.layers.Get(l)
if !ok {
2023-04-28 18:03:26 +03:00
layer := poolx.New[Drawer]()
e.layers.Set(
l,
2023-04-28 18:03:26 +03:00
layer,
)
2023-04-28 18:03:26 +03:00
layer.Append(d)
} else {
2023-04-28 18:03:26 +03:00
g.Append(d)
2023-02-17 07:04:29 +03:00
}
2023-02-17 23:51:40 +03:00
}
2023-05-22 23:39:01 +03:00
func (e *Engine) addBehaver(b Behaver) {
2023-04-28 18:03:26 +03:00
e.behavers.Append(b)
b.Start(e)
2023-02-17 07:04:29 +03:00
}
func (e *engine) Update() error {
var err error
eng := (*Engine)(e)
2023-02-17 23:51:40 +03:00
2023-02-18 07:46:33 +03:00
e.keys = inpututil.
AppendPressedKeys(e.keys[:0])
2023-02-18 02:03:28 +03:00
e.dt = time.Since(e.lastTime).Seconds()
2023-04-28 18:03:26 +03:00
for p := range eng.behavers.Range() {
err = p.V.Update(eng)
if err != nil {
return err
}
}
2023-02-18 02:03:28 +03:00
e.lastTime = time.Now()
2023-02-17 07:04:29 +03:00
return nil
}
2023-02-17 23:51:40 +03:00
func (e *engine) Draw(i *ebiten.Image) {
eng := (*Engine)(e)
for p := range e.layers.Vals() {
2023-04-28 18:03:26 +03:00
for pj := range p.V.Range() {
if !pj.V.IsVisible() {
continue
}
2023-04-28 18:03:26 +03:00
pj.V.Draw(eng, i)
2023-02-17 23:51:40 +03:00
}
}
2023-02-17 07:04:29 +03:00
}
func (e *engine) Layout(ow, oh int) (int, int) {
if e.wcfg.FixedSize {
return e.wcfg.Width, e.wcfg.Height
}
return ow, oh
2023-02-17 07:04:29 +03:00
}
2023-02-17 23:51:40 +03:00
// Return the delta time duration value.
func (e *Engine) DT() Float {
return e.dt
}
2023-02-17 07:04:29 +03:00
func (e *Engine) Run() error {
ebiten.SetWindowTitle(e.wcfg.Title)
ebiten.SetWindowSize(e.wcfg.Width, e.wcfg.Height)
2023-02-18 19:35:38 +03:00
ebiten.SetWindowSizeLimits(1, 1, e.wcfg.Width, e.wcfg.Height)
ebiten.SetVsyncEnabled(e.wcfg.VSync)
2023-02-17 07:04:29 +03:00
2023-02-18 00:17:51 +03:00
e.lastTime = time.Now()
2023-02-17 07:04:29 +03:00
return ebiten.RunGame((*engine)(e))
}