mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-12-24 18:58:54 +01:00
ui: Use events in the game loop
This commit is contained in:
parent
49c156d2b5
commit
5c68ee4034
21
internal/ui/event.go
Normal file
21
internal/ui/event.go
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2016 Hajime Hoshi
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package ui
|
||||
|
||||
type CloseEvent struct {
|
||||
}
|
||||
|
||||
type RenderEvent struct {
|
||||
}
|
@ -196,7 +196,14 @@ func (u *UserInterface) pollEvents() error {
|
||||
return currentInput.update(u.window, u.windowScale())
|
||||
}
|
||||
|
||||
func (u *UserInterface) Update() error {
|
||||
func (u *UserInterface) Update() (interface{}, error) {
|
||||
shouldClose := false
|
||||
u.runOnMainThread(func() {
|
||||
shouldClose = u.window.ShouldClose()
|
||||
})
|
||||
if shouldClose {
|
||||
return CloseEvent{}, nil
|
||||
}
|
||||
var ferr error
|
||||
u.runOnMainThread(func() {
|
||||
if err := u.pollEvents(); err != nil {
|
||||
@ -215,7 +222,10 @@ func (u *UserInterface) Update() error {
|
||||
}
|
||||
}
|
||||
})
|
||||
return ferr
|
||||
if ferr != nil {
|
||||
return nil, ferr
|
||||
}
|
||||
return RenderEvent{}, nil
|
||||
}
|
||||
|
||||
func (u *UserInterface) Terminate() {
|
||||
@ -226,14 +236,6 @@ func (u *UserInterface) Terminate() {
|
||||
u.funcs = nil
|
||||
}
|
||||
|
||||
func (u *UserInterface) IsClosed() bool {
|
||||
r := false
|
||||
u.runOnMainThread(func() {
|
||||
r = u.window.ShouldClose()
|
||||
})
|
||||
return r
|
||||
}
|
||||
|
||||
func (u *UserInterface) SwapBuffers() {
|
||||
u.runOnMainThread(func() {
|
||||
u.swapBuffers()
|
||||
|
@ -83,19 +83,15 @@ func vsync() {
|
||||
<-ch
|
||||
}
|
||||
|
||||
func (u *UserInterface) Update() error {
|
||||
func (u *UserInterface) Update() (interface{}, error) {
|
||||
currentInput.UpdateGamepads()
|
||||
return nil
|
||||
return RenderEvent{}, nil
|
||||
}
|
||||
|
||||
func (u *UserInterface) Terminate() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
func (u *UserInterface) IsClosed() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (u *UserInterface) SwapBuffers() {
|
||||
vsync()
|
||||
for !shown() {
|
||||
|
66
run.go
66
run.go
@ -204,46 +204,50 @@ func run(f func(*Image) error, width, height, scale int, title string) error {
|
||||
beforeForUpdate := n
|
||||
beforeForFPS := n
|
||||
for {
|
||||
// TODO: setSize should be called after swapping buffers?
|
||||
if err := currentRunContext.updateScreenSize(graphicsContext); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ui.CurrentUI().Update(); err != nil {
|
||||
e, err := ui.CurrentUI().Update()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if ui.CurrentUI().IsClosed() {
|
||||
switch e.(type) {
|
||||
case ui.CloseEvent:
|
||||
return nil
|
||||
}
|
||||
now := ui.Now()
|
||||
// If beforeForUpdate is too old, we assume that screen is not shown.
|
||||
if int64(5*time.Second/FPS) < now-beforeForUpdate {
|
||||
currentRunContext.setRunningSlowly(false)
|
||||
beforeForUpdate = now
|
||||
} else {
|
||||
// Note that generally t is a little different from 1/60[sec].
|
||||
t := now - beforeForUpdate
|
||||
currentRunContext.setRunningSlowly(t*FPS >= int64(time.Second*5/2))
|
||||
tt := int(t * FPS / int64(time.Second))
|
||||
// As t is not accurate 1/60[sec], errors are accumulated.
|
||||
// To make the FPS stable, set tt 1 if t is a little less than 1/60[sec].
|
||||
if tt == 0 && (int64(time.Second)/FPS-int64(5*time.Millisecond)) < t {
|
||||
tt = 1
|
||||
}
|
||||
for i := 0; i < tt; i++ {
|
||||
if err := graphicsContext.update(f); err != nil {
|
||||
return err
|
||||
case ui.RenderEvent:
|
||||
now := ui.Now()
|
||||
// If beforeForUpdate is too old, we assume that screen is not shown.
|
||||
if int64(5*time.Second/FPS) < now-beforeForUpdate {
|
||||
currentRunContext.setRunningSlowly(false)
|
||||
beforeForUpdate = now
|
||||
} else {
|
||||
// Note that generally t is a little different from 1/60[sec].
|
||||
t := now - beforeForUpdate
|
||||
currentRunContext.setRunningSlowly(t*FPS >= int64(time.Second*5/2))
|
||||
tt := int(t * FPS / int64(time.Second))
|
||||
// As t is not accurate 1/60[sec], errors are accumulated.
|
||||
// To make the FPS stable, set tt 1 if t is a little less than 1/60[sec].
|
||||
if tt == 0 && (int64(time.Second)/FPS-int64(5*time.Millisecond)) < t {
|
||||
tt = 1
|
||||
}
|
||||
for i := 0; i < tt; i++ {
|
||||
if err := graphicsContext.update(f); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
ui.CurrentUI().SwapBuffers()
|
||||
beforeForUpdate += int64(tt) * int64(time.Second) / FPS
|
||||
frames++
|
||||
}
|
||||
ui.CurrentUI().SwapBuffers()
|
||||
beforeForUpdate += int64(tt) * int64(time.Second) / FPS
|
||||
frames++
|
||||
}
|
||||
|
||||
// Calc the current FPS.
|
||||
if time.Second <= time.Duration(now-beforeForFPS) {
|
||||
currentRunContext.updateFPS(float64(frames) * float64(time.Second) / float64(now-beforeForFPS))
|
||||
beforeForFPS = now
|
||||
frames = 0
|
||||
// Calc the current FPS.
|
||||
if time.Second <= time.Duration(now-beforeForFPS) {
|
||||
currentRunContext.updateFPS(float64(frames) * float64(time.Second) / float64(now-beforeForFPS))
|
||||
beforeForFPS = now
|
||||
frames = 0
|
||||
}
|
||||
default:
|
||||
panic("not reach")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user