Skip to content

Commit 9621d1e

Browse files
committed
[bugfix] Run Draw method at most 30 times per second
Draw method must be executed at most 30 times per second. The frequency should not depend on display frequency.
1 parent 706b317 commit 9621d1e

File tree

1 file changed

+35
-6
lines changed

1 file changed

+35
-6
lines changed

ebitengine.go

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,18 @@ import (
77
"errors"
88
"fmt"
99
"math"
10+
"time"
1011

1112
"github.com/hajimehoshi/ebiten/v2"
1213
)
1314

1415
var gameStoppedErr = errors.New("game stopped")
1516

17+
const tps = 30
18+
1619
func run() error {
17-
ebiten.SetMaxTPS(30)
20+
ebiten.SetMaxTPS(tps)
21+
ebiten.SetScreenClearedEveryFrame(false)
1822
ebiten.SetRunnableOnUnfocused(true)
1923
ebiten.SetWindowResizingMode(ebiten.WindowResizingModeEnabled)
2024
ebiten.SetWindowSize(scrWidth*scale(), scrHeight*scale())
@@ -37,10 +41,14 @@ func scale() int {
3741
}
3842

3943
type ebitengineGame struct {
40-
screenDataRGBA []byte // reused RGBA pixels
44+
screenDataRGBA []byte // reused RGBA pixels
45+
screenChanged bool
46+
shouldSkipNextDraw bool
4147
}
4248

4349
func (e *ebitengineGame) Update() error {
50+
updateStartedTime := time.Now()
51+
4452
updateTime()
4553
updateController()
4654

@@ -52,15 +60,36 @@ func (e *ebitengineGame) Update() error {
5260
return gameStoppedErr
5361
}
5462

63+
// Ebitengine treats Draw differently than π. In π Draw must be executed at most 30 times per second.
64+
// That's why π runs Draw() from inside Ebitengine's Update().
65+
if Draw != nil {
66+
if e.shouldSkipNextDraw {
67+
e.shouldSkipNextDraw = false
68+
return nil
69+
}
70+
71+
Draw()
72+
73+
elapsed := time.Since(updateStartedTime)
74+
if elapsed.Seconds() > 1/float64(tps) {
75+
e.shouldSkipNextDraw = true
76+
}
77+
}
78+
79+
e.screenChanged = true
80+
5581
return nil
5682
}
5783

5884
func (e *ebitengineGame) Draw(screen *ebiten.Image) {
59-
if Draw != nil {
60-
Draw()
85+
// Ebitengine executes Draw based on display frequency.
86+
// But the screen is changed at most 30 times per second.
87+
// That's why there is no need to replace pixels more often
88+
// than 30 times per second.
89+
if e.screenChanged {
90+
e.replaceScreenPixels(screen)
91+
e.screenChanged = false
6192
}
62-
63-
e.replaceScreenPixels(screen)
6493
}
6594

6695
func (e *ebitengineGame) replaceScreenPixels(screen *ebiten.Image) {

0 commit comments

Comments
 (0)