2023-10-23 15:45:18 +03:00
|
|
|
package gg
|
2023-02-17 07:04:29 +03:00
|
|
|
|
|
|
|
import (
|
|
|
|
"github.com/hajimehoshi/ebiten/v2"
|
2023-02-18 07:46:33 +03:00
|
|
|
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
2024-01-09 06:44:40 +03:00
|
|
|
"vultras.su/core/gods/maps"
|
2024-01-16 04:11:42 +03:00
|
|
|
//"fmt"
|
2023-02-17 23:51:40 +03:00
|
|
|
"time"
|
2023-12-24 15:05:34 +03:00
|
|
|
"slices"
|
2023-12-24 22:33:01 +03:00
|
|
|
"sync"
|
2023-02-17 07:04:29 +03:00
|
|
|
)
|
|
|
|
|
2024-01-08 12:25:18 +03:00
|
|
|
const (
|
2024-01-11 06:39:57 +03:00
|
|
|
MaxVertices = 1 << 16
|
2024-01-08 12:25:18 +03:00
|
|
|
)
|
|
|
|
|
2023-12-25 23:41:12 +03:00
|
|
|
type GraphicsLibrary = ebiten.GraphicsLibrary
|
|
|
|
type RunOptions = ebiten.RunGameOptions
|
|
|
|
|
2023-02-17 16:40:46 +03:00
|
|
|
// The type represents order of drawing.
|
2023-08-31 11:29:37 +03:00
|
|
|
// Higher values are drawn later.
|
|
|
|
type Layer float64
|
|
|
|
|
|
|
|
func (l Layer) GetLayer() Layer {
|
|
|
|
return l
|
|
|
|
}
|
2023-02-17 16:40:46 +03:00
|
|
|
|
2023-05-02 17:38:34 +03:00
|
|
|
// Window configuration type.
|
2023-02-17 07:04:29 +03:00
|
|
|
type WindowConfig struct {
|
2023-12-25 23:41:12 +03:00
|
|
|
DebugInfo ebiten.DebugInfo
|
|
|
|
Options *RunOptions
|
2023-12-23 00:09:07 +03:00
|
|
|
// The title of the window.
|
2023-02-17 07:04:29 +03:00
|
|
|
Title string
|
2023-05-26 18:31:04 +03:00
|
|
|
|
2023-12-23 00:09:07 +03:00
|
|
|
// Width and height of the window
|
|
|
|
// in pixels.
|
2023-05-26 18:31:04 +03:00
|
|
|
Width,
|
|
|
|
Height int
|
|
|
|
|
2023-12-23 00:09:07 +03:00
|
|
|
// Optional settings with
|
|
|
|
// self describing names.
|
2023-05-26 18:31:04 +03:00
|
|
|
FixedSize,
|
|
|
|
Fullscreen,
|
2023-05-04 19:31:33 +03:00
|
|
|
VSync bool
|
2023-02-17 07:04:29 +03:00
|
|
|
}
|
|
|
|
|
2024-01-08 10:22:09 +03:00
|
|
|
type Objects struct {
|
|
|
|
store []Objecter
|
|
|
|
}
|
|
|
|
|
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-12-23 00:09:07 +03:00
|
|
|
|
|
|
|
// The main holder for objects.
|
|
|
|
// Uses the map structure to quickly
|
|
|
|
// delete and create new objects.
|
2024-01-08 10:22:09 +03:00
|
|
|
Objects *Objects
|
2023-12-23 00:09:07 +03:00
|
|
|
|
|
|
|
// The main camera to display in window.
|
|
|
|
// If is set to nil then the engine will panic.
|
|
|
|
Camera *Camera
|
|
|
|
|
2024-01-13 23:46:12 +03:00
|
|
|
drawLastTime time.Time
|
|
|
|
drawdt Duration
|
2024-01-13 21:45:56 +03:00
|
|
|
|
|
|
|
// Frame delta time.
|
2024-01-13 23:46:12 +03:00
|
|
|
dt Duration
|
|
|
|
lastTime time.Time
|
2023-12-23 00:09:07 +03:00
|
|
|
|
|
|
|
// Temporary stuff
|
2023-11-23 22:05:22 +03:00
|
|
|
keys, prevKeys []Key
|
2023-12-24 15:05:34 +03:00
|
|
|
buttons MouseButtonMap
|
|
|
|
wheel Vector
|
|
|
|
cursorPos Vector
|
2023-11-23 22:05:22 +03:00
|
|
|
outerEvents, handleEvents EventChan
|
2024-01-08 06:09:36 +03:00
|
|
|
wg sync.WaitGroup
|
2024-01-08 12:25:18 +03:00
|
|
|
|
2024-01-11 04:45:28 +03:00
|
|
|
//bufs [LayerBufSize]*Image
|
2024-01-11 06:39:57 +03:00
|
|
|
vertices map[Layer] []ebiten.Vertex
|
|
|
|
//vindices []uint16
|
2024-01-13 21:45:56 +03:00
|
|
|
|
|
|
|
// Draw frame.
|
|
|
|
dframe uint
|
|
|
|
|
|
|
|
// Frame.
|
|
|
|
frame uint
|
2024-01-14 03:51:11 +03:00
|
|
|
|
|
|
|
runes []rune
|
2023-02-17 07:04:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
type engine Engine
|
|
|
|
|
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-12-25 23:41:12 +03:00
|
|
|
func (e *Engine) GraphicsLibrary() GraphicsLibrary {
|
|
|
|
return e.wcfg.DebugInfo.GraphicsLibrary
|
|
|
|
}
|
|
|
|
|
2023-12-24 15:05:34 +03:00
|
|
|
// Returns currently pressed buttons.
|
|
|
|
func (e *Engine) MouseButtons() []MouseButton {
|
|
|
|
ret := make([]MouseButton, len(e.buttons))
|
|
|
|
i := 0
|
|
|
|
for v := range e.buttons {
|
|
|
|
ret[i] = v
|
|
|
|
i++
|
|
|
|
}
|
|
|
|
slices.Sort(ret)
|
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
2023-05-02 17:38:34 +03:00
|
|
|
// Returns new empty Engine.
|
2023-06-03 10:39:15 +03:00
|
|
|
func NewEngine(
|
2023-02-17 07:04:29 +03:00
|
|
|
cfg *WindowConfig,
|
|
|
|
) *Engine {
|
2023-12-23 00:09:07 +03:00
|
|
|
/*w := Float(cfg.Width)
|
|
|
|
h := Float(cfg.Height)*/
|
|
|
|
|
|
|
|
ret := &Engine{}
|
|
|
|
|
|
|
|
ret.wcfg = cfg
|
|
|
|
ret.Camera = ret.NewCamera()
|
|
|
|
ret.outerEvents = make(EventChan)
|
|
|
|
ret.handleEvents = make(EventChan)
|
2024-01-08 10:22:09 +03:00
|
|
|
ret.Objects = &Objects{}
|
2023-12-24 15:05:34 +03:00
|
|
|
ret.buttons = MouseButtonMap{}
|
2023-12-23 00:09:07 +03:00
|
|
|
return ret
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the real window size in the current context.
|
|
|
|
func (c *Engine) RealWinSize() Vector {
|
2024-01-08 10:22:09 +03:00
|
|
|
var w, h int
|
|
|
|
if c.wcfg.Fullscreen {
|
|
|
|
w, h = ebiten.ScreenSizeInFullscreen()
|
|
|
|
} else {
|
|
|
|
w, h = c.wcfg.Width, c.wcfg.Height
|
|
|
|
}
|
2023-12-23 00:09:07 +03:00
|
|
|
return V(
|
2024-01-08 10:22:09 +03:00
|
|
|
Float(w),
|
|
|
|
Float(h),
|
2023-12-23 00:09:07 +03:00
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *Engine) AbsWinSize() Vector {
|
|
|
|
return c.RealWinSize().Div(c.Camera.Scale)
|
2023-02-17 16:40:46 +03:00
|
|
|
}
|
|
|
|
|
2023-11-23 22:05:22 +03:00
|
|
|
func (e *Engine) EventInput() EventChan {
|
|
|
|
return e.outerEvents
|
|
|
|
}
|
|
|
|
|
2023-02-17 23:51:40 +03:00
|
|
|
// Add new object considering what
|
|
|
|
// interfaces it implements.
|
2024-01-08 06:09:36 +03:00
|
|
|
func (e *Engine) Spawn(b Objecter) error {
|
2024-01-08 10:22:09 +03:00
|
|
|
/*if e.Objects.Has(b) {
|
2023-08-31 11:29:37 +03:00
|
|
|
return ObjectExistErr
|
2024-01-08 10:22:09 +03:00
|
|
|
}*/
|
2023-02-17 23:51:40 +03:00
|
|
|
|
2024-01-08 06:09:36 +03:00
|
|
|
b.Start(&Context{Engine: e})
|
|
|
|
obj := b.GetObject()
|
|
|
|
obj.input = make(chan *Context)
|
|
|
|
go func() {
|
|
|
|
for c := range obj.input {
|
2024-01-16 04:11:42 +03:00
|
|
|
switch c.typ{
|
|
|
|
case updateContext :
|
|
|
|
b.Update(c)
|
|
|
|
case resolveContext :
|
|
|
|
b.Resolve(c)
|
|
|
|
}
|
2024-01-08 06:09:36 +03:00
|
|
|
e.wg.Done()
|
|
|
|
}
|
|
|
|
}()
|
2024-01-08 10:22:09 +03:00
|
|
|
e.Objects.store = append(e.Objects.store, b)
|
2023-08-31 11:29:37 +03:00
|
|
|
|
|
|
|
return nil
|
2023-02-17 23:51:40 +03:00
|
|
|
}
|
|
|
|
|
2023-05-26 18:31:04 +03:00
|
|
|
// Delete object from Engine.
|
2024-01-08 06:09:36 +03:00
|
|
|
func (e *Engine) Del(b Objecter) error {
|
2024-01-08 10:22:09 +03:00
|
|
|
/*if !e.Objects.Has(b) {
|
2023-08-31 11:29:37 +03:00
|
|
|
return ObjectNotExistErr
|
2023-04-28 18:21:34 +03:00
|
|
|
}
|
2023-08-31 11:29:37 +03:00
|
|
|
|
2024-01-08 06:09:36 +03:00
|
|
|
b.Delete(&Context{Engine: e})
|
2024-01-08 10:22:09 +03:00
|
|
|
e.Objects.Del(b)*/
|
2023-02-17 16:40:46 +03:00
|
|
|
|
2023-08-31 11:29:37 +03:00
|
|
|
return nil
|
2023-02-17 23:51:40 +03:00
|
|
|
}
|
|
|
|
|
2023-12-24 15:05:34 +03:00
|
|
|
var (
|
|
|
|
allButtons = []MouseButton{
|
|
|
|
MouseButton0,
|
|
|
|
MouseButton1,
|
|
|
|
MouseButton2,
|
|
|
|
MouseButton3,
|
|
|
|
MouseButton4,
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
func (e *Engine) IsPressed(k Key) bool {
|
|
|
|
keys := e.Keys()
|
|
|
|
for _, v := range keys {
|
|
|
|
if v == k {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Engine) IsButtoned(b MouseButton) bool {
|
|
|
|
_, ok := e.buttons[b]
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Engine) Wheel() Vector {
|
|
|
|
return e.wheel
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Engine) cursorPosition() Vector {
|
|
|
|
x, y := ebiten.CursorPosition()
|
|
|
|
return V(Float(x), Float(y))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Engine) CursorPosition() Vector {
|
|
|
|
return e.cursorPos
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Engine) AbsCursorPosition() Vector {
|
2024-01-08 02:53:00 +03:00
|
|
|
return e.CursorPosition().Apply(e.Camera.AbsMatrix())
|
2023-12-24 15:05:34 +03:00
|
|
|
}
|
2023-02-17 07:04:29 +03:00
|
|
|
|
2024-01-14 03:51:11 +03:00
|
|
|
func (e *Engine) Runes() []rune {
|
|
|
|
return e.runes
|
|
|
|
}
|
|
|
|
|
2024-01-16 01:08:21 +03:00
|
|
|
func (e *engine) UpdateEvents() []any {
|
2023-12-24 22:33:01 +03:00
|
|
|
|
2024-01-16 01:08:21 +03:00
|
|
|
eng := (*Engine)(e)
|
2023-11-23 22:05:22 +03:00
|
|
|
e.prevKeys = e.keys
|
2023-02-18 07:46:33 +03:00
|
|
|
e.keys = inpututil.
|
|
|
|
AppendPressedKeys(e.keys[:0])
|
|
|
|
|
2023-11-23 22:05:22 +03:00
|
|
|
events := []any{}
|
2023-12-24 15:05:34 +03:00
|
|
|
btns := e.buttons
|
|
|
|
for _, btn := range allButtons {
|
|
|
|
if inpututil.IsMouseButtonJustPressed(btn) {
|
|
|
|
btns[btn] = struct{}{}
|
|
|
|
events = append(events, &MouseButtonDown{
|
|
|
|
MouseButton: btn,
|
|
|
|
})
|
|
|
|
} else if inpututil.IsMouseButtonJustReleased(btn) {
|
|
|
|
delete(btns, btn)
|
|
|
|
events = append(events, &MouseButtonUp{
|
|
|
|
MouseButton: btn,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
x, y := ebiten.Wheel()
|
2024-01-16 01:08:21 +03:00
|
|
|
e.wheel = V(x, y)
|
|
|
|
if !(e.wheel.Eq(ZV)) {
|
2023-12-24 15:05:34 +03:00
|
|
|
events = append(events, &WheelChange{
|
2024-01-16 01:08:21 +03:00
|
|
|
Offset: e.wheel,
|
2023-12-24 15:05:34 +03:00
|
|
|
})
|
|
|
|
}
|
2023-11-23 22:05:22 +03:00
|
|
|
|
2023-12-24 15:05:34 +03:00
|
|
|
keyDiff := diffEm(e.prevKeys, e.keys)
|
|
|
|
for _, key := range keyDiff {
|
2023-11-23 22:05:22 +03:00
|
|
|
var event any
|
|
|
|
if eng.IsPressed(key) {
|
|
|
|
event = &KeyDown{
|
|
|
|
Key: key,
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
event = &KeyUp{
|
|
|
|
Key: key,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
events = append(events, event)
|
|
|
|
}
|
|
|
|
|
2023-12-24 15:05:34 +03:00
|
|
|
realPos := eng.cursorPosition()
|
2024-01-16 01:08:21 +03:00
|
|
|
if !realPos.Eq(e.cursorPos) {
|
2023-12-24 15:05:34 +03:00
|
|
|
absM := eng.Camera.AbsMatrix()
|
|
|
|
|
2024-01-16 01:08:21 +03:00
|
|
|
absPrevPos := e.cursorPos.Apply(absM)
|
2024-01-08 02:53:00 +03:00
|
|
|
absPos := realPos.Apply(absM)
|
2023-12-24 15:05:34 +03:00
|
|
|
|
|
|
|
events = append(events, &MouseMove{
|
2024-01-16 01:08:21 +03:00
|
|
|
Real: realPos.Sub(e.cursorPos),
|
2023-12-24 15:05:34 +03:00
|
|
|
Abs: absPos.Sub(absPrevPos),
|
|
|
|
})
|
2024-01-16 01:08:21 +03:00
|
|
|
e.cursorPos = realPos
|
2023-12-24 15:05:34 +03:00
|
|
|
}
|
2024-01-16 01:08:21 +03:00
|
|
|
return events
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *engine) Update() error {
|
2023-12-24 22:33:01 +03:00
|
|
|
|
2024-01-16 01:08:21 +03:00
|
|
|
eng := (*Engine)(e)
|
|
|
|
e.dt = time.Since(e.lastTime)
|
|
|
|
|
|
|
|
e.runes = ebiten.AppendInputChars(e.runes[:0])
|
2024-01-16 04:11:42 +03:00
|
|
|
//fmt.Println("runes:", e.runes)
|
2024-01-16 01:08:21 +03:00
|
|
|
// Buffering the context for faster.
|
2023-12-24 22:33:01 +03:00
|
|
|
// Providing the events to the objects.
|
|
|
|
// Maybe should think of the better way,
|
|
|
|
// but for it is simple enough.
|
2024-01-16 01:08:21 +03:00
|
|
|
|
|
|
|
events := e.UpdateEvents()
|
2024-01-08 07:12:35 +03:00
|
|
|
c := &Context{
|
|
|
|
Engine: eng,
|
|
|
|
typ: updateContext,
|
|
|
|
Events: events,
|
|
|
|
}
|
2024-01-08 10:22:09 +03:00
|
|
|
for _, object := range e.Objects.store {
|
2024-01-08 06:09:36 +03:00
|
|
|
e.wg.Add(1)
|
|
|
|
object.Input() <- c
|
2023-02-17 16:40:46 +03:00
|
|
|
}
|
2024-01-08 07:12:35 +03:00
|
|
|
e.wg.Wait()
|
2024-01-16 01:08:21 +03:00
|
|
|
e.Resolve()
|
|
|
|
|
2024-01-13 23:46:12 +03:00
|
|
|
e.lastTime = time.Now()
|
2024-01-13 21:45:56 +03:00
|
|
|
e.frame++
|
2023-02-17 07:04:29 +03:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2024-01-16 01:08:21 +03:00
|
|
|
func (e *engine) Resolve() {
|
2024-01-16 04:11:42 +03:00
|
|
|
eng := (*Engine)(e)
|
|
|
|
type resHold struct{
|
|
|
|
Resolver Resolver
|
|
|
|
input chan *Context
|
|
|
|
}
|
2024-01-16 07:37:53 +03:00
|
|
|
colliders := map[CollisionType] []Collider{}
|
2024-01-16 04:11:42 +03:00
|
|
|
|
|
|
|
resolvers := []resHold{}
|
2024-01-16 01:08:21 +03:00
|
|
|
for _, object := range e.Objects.store {
|
|
|
|
if object.IsResolvable() {
|
2024-01-16 07:37:53 +03:00
|
|
|
interests := object.GetCollisionInterest()
|
|
|
|
for _, interest := range interests {
|
|
|
|
_, ok := colliders[interest]
|
|
|
|
if !ok {
|
|
|
|
colliders[interest] = []Collider{}
|
|
|
|
}
|
|
|
|
}
|
2024-01-16 04:11:42 +03:00
|
|
|
resolvers = append(resolvers, resHold{
|
|
|
|
object,
|
|
|
|
object.Input(),
|
|
|
|
})
|
2024-01-16 01:08:21 +03:00
|
|
|
}
|
|
|
|
}
|
2024-01-16 04:11:42 +03:00
|
|
|
|
2024-01-16 07:37:53 +03:00
|
|
|
for _, object := range e.Objects.store {
|
|
|
|
if object.IsCollidable() {
|
|
|
|
typ := object.CollisionType()
|
|
|
|
_, ok := colliders[typ]
|
|
|
|
if !ok {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
colliders[typ] = append(colliders[typ], object)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-01-16 04:11:42 +03:00
|
|
|
for _, resolver := range resolvers {
|
2024-01-16 07:37:53 +03:00
|
|
|
interests := resolver.Resolver.GetCollisionInterest()
|
|
|
|
cols := []Collision{}
|
|
|
|
for _, interest := range interests {
|
|
|
|
cols = append(cols, GetCollisions(resolver.Resolver, colliders[interest])...)
|
|
|
|
}
|
2024-01-16 04:11:42 +03:00
|
|
|
if len(cols) > 0 {
|
|
|
|
c := &Context{
|
|
|
|
typ: resolveContext,
|
|
|
|
Collisions: cols,
|
|
|
|
Engine: eng,
|
|
|
|
}
|
|
|
|
e.wg.Add(1)
|
|
|
|
resolver.input <- c
|
|
|
|
}
|
|
|
|
}
|
|
|
|
e.wg.Wait()
|
2024-01-16 01:08:21 +03:00
|
|
|
}
|
|
|
|
|
2024-01-11 06:39:57 +03:00
|
|
|
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) {
|
2024-01-13 23:46:12 +03:00
|
|
|
e.drawdt = time.Since(e.drawLastTime)
|
2023-02-17 23:51:40 +03:00
|
|
|
eng := (*Engine)(e)
|
2023-11-12 13:29:38 +03:00
|
|
|
m := map[Layer][]Drawer{}
|
2024-01-08 10:22:09 +03:00
|
|
|
for _, object := range eng.Objects.store {
|
2024-01-08 06:09:36 +03:00
|
|
|
// Skipping the ones we do not need to draw.
|
|
|
|
if !object.IsVisible() {
|
2023-08-31 11:29:37 +03:00
|
|
|
continue
|
|
|
|
}
|
2024-01-08 06:09:36 +03:00
|
|
|
l := object.GetLayer()
|
2023-11-12 13:29:38 +03:00
|
|
|
layer, ok := m[l]
|
|
|
|
// Create new if has no the layer
|
2023-08-31 11:29:37 +03:00
|
|
|
if !ok {
|
2024-01-08 06:09:36 +03:00
|
|
|
m[l] = []Drawer{object}
|
2023-08-31 11:29:37 +03:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
2024-01-08 06:09:36 +03:00
|
|
|
m[l] = append(layer, object)
|
2023-08-31 11:29:37 +03:00
|
|
|
}
|
|
|
|
|
2024-01-11 06:39:57 +03:00
|
|
|
// Drawing layers via the sparse array.
|
|
|
|
// First drawing via the inside function
|
|
|
|
// and then the returned []EVertex.
|
2023-11-12 13:29:38 +03:00
|
|
|
layers := maps.NewSparse[Layer, []Drawer](nil, m)
|
2024-01-11 06:39:57 +03:00
|
|
|
c := &Context{Engine: eng, typ: drawContext, Image: img}
|
2023-08-31 11:29:37 +03:00
|
|
|
for layer := range layers.Chan() {
|
2024-01-11 06:39:57 +03:00
|
|
|
vertices := []EVertex{}
|
2023-08-31 11:29:37 +03:00
|
|
|
for _, drawer := range layer {
|
2024-01-11 06:39:57 +03:00
|
|
|
vs := drawer.Draw(c)
|
|
|
|
if vs != nil {
|
|
|
|
vertices = append(vertices, vs...)
|
|
|
|
}
|
2023-02-17 23:51:40 +03:00
|
|
|
}
|
2024-01-11 06:39:57 +03:00
|
|
|
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,
|
|
|
|
)
|
2023-02-17 23:51:40 +03:00
|
|
|
}
|
2024-01-11 06:39:57 +03:00
|
|
|
|
2024-01-08 10:22:09 +03:00
|
|
|
|
2023-12-23 00:09:07 +03:00
|
|
|
// Empty the buff to generate it again.
|
2024-01-08 10:22:09 +03:00
|
|
|
eng.Camera.buffered = false
|
2024-01-13 23:46:12 +03:00
|
|
|
e.drawLastTime = time.Now()
|
2024-01-13 21:45:56 +03:00
|
|
|
e.dframe++
|
2023-02-17 07:04:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (e *engine) Layout(ow, oh int) (int, int) {
|
2023-02-18 09:11:09 +03:00
|
|
|
if e.wcfg.FixedSize {
|
|
|
|
return e.wcfg.Width, e.wcfg.Height
|
|
|
|
}
|
2023-02-18 15:38:28 +03:00
|
|
|
|
2023-02-18 09:11:09 +03:00
|
|
|
return ow, oh
|
2023-02-17 07:04:29 +03:00
|
|
|
}
|
|
|
|
|
2024-01-11 06:39:57 +03:00
|
|
|
// Return the delta time.
|
2024-01-13 23:46:12 +03:00
|
|
|
func (e *Engine) DrawDt() Duration {
|
|
|
|
return e.drawdt
|
2023-02-17 23:51:40 +03:00
|
|
|
}
|
2024-01-11 06:39:57 +03:00
|
|
|
|
2024-01-13 21:45:56 +03:00
|
|
|
func (e *Engine) Dframe() uint {
|
|
|
|
return e.dframe
|
|
|
|
}
|
|
|
|
|
2024-01-11 06:39:57 +03:00
|
|
|
// Return the current fixed delta time.
|
2024-01-16 07:37:53 +03:00
|
|
|
func (e *Engine) RealDt() Duration {
|
2024-01-13 23:46:12 +03:00
|
|
|
return e.dt
|
2024-01-11 06:39:57 +03:00
|
|
|
}
|
|
|
|
|
2024-01-16 07:37:53 +03:00
|
|
|
func (e *Engine) Dt() Duration {
|
|
|
|
return time.Second/60
|
|
|
|
}
|
|
|
|
|
2024-01-13 21:45:56 +03:00
|
|
|
func (e *Engine) Frame() uint {
|
|
|
|
return e.frame
|
|
|
|
}
|
|
|
|
|
2024-01-11 06:39:57 +03:00
|
|
|
func (e *Engine) Fps() float64 {
|
2023-12-26 23:31:04 +03:00
|
|
|
return ebiten.ActualFPS()
|
|
|
|
}
|
|
|
|
|
2024-01-11 06:39:57 +03:00
|
|
|
func (e *Engine) Tps() float64 {
|
2023-12-26 23:31:04 +03:00
|
|
|
return ebiten.ActualTPS()
|
|
|
|
}
|
2023-02-17 23:51:40 +03:00
|
|
|
|
2023-02-17 07:04:29 +03:00
|
|
|
func (e *Engine) Run() error {
|
2023-12-25 23:41:12 +03:00
|
|
|
ebiten.ReadDebugInfo(&e.wcfg.DebugInfo)
|
2023-02-17 07:04:29 +03:00
|
|
|
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)
|
2023-05-04 19:31:33 +03:00
|
|
|
|
2024-01-08 10:22:09 +03:00
|
|
|
ebiten.SetFullscreen(e.wcfg.Fullscreen)
|
2023-05-04 19:31:33 +03:00
|
|
|
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-12-23 00:09:07 +03:00
|
|
|
//fmt.Println(e.Objects)
|
2023-12-25 23:41:12 +03:00
|
|
|
return ebiten.RunGameWithOptions((*engine)(e), e.wcfg.Options)
|
2023-02-17 07:04:29 +03:00
|
|
|
}
|
|
|
|
|