Bug fix: ui.Main should be suspended when error occurs in the loop

This commit is contained in:
Hajime Hoshi 2016-08-02 02:47:45 +09:00
parent c7106f595c
commit 6968e898c3
6 changed files with 28 additions and 15 deletions

View File

@ -30,11 +30,14 @@ import (
func TestMain(m *testing.M) { func TestMain(m *testing.M) {
code := 0 code := 0
// Run an Ebiten process so that (*Image).At is available. // Run an Ebiten process so that (*Image).At is available.
regularTermination := errors.New("regular termination")
f := func(screen *Image) error { f := func(screen *Image) error {
code = m.Run() code = m.Run()
return errors.New("regular termination") return regularTermination
}
if err := Run(f, 320, 240, 1, "Test"); err != nil && err != regularTermination {
panic(err)
} }
Run(f, 320, 240, 1, "Test")
os.Exit(code) os.Exit(code)
} }

View File

@ -86,7 +86,7 @@ type GraphicsContext interface {
UpdateAndDraw(context *opengl.Context, updateCount int) error UpdateAndDraw(context *opengl.Context, updateCount int) error
} }
func Run(g GraphicsContext, width, height int, scale float64, title string, fps int) error { func Run(g GraphicsContext, width, height int, scale float64, title string, fps int) (err error) {
if currentRunContext != nil { if currentRunContext != nil {
return errors.New("loop: The game is already running") return errors.New("loop: The game is already running")
} }
@ -100,7 +100,12 @@ func Run(g GraphicsContext, width, height int, scale float64, title string, fps
return err return err
} }
// TODO: Use the error value // TODO: Use the error value
defer ui.CurrentUI().Terminate() defer func() {
if err != nil {
return
}
err = ui.CurrentUI().Terminate()
}()
n := now() n := now()
currentRunContext.lastUpdated = n currentRunContext.lastUpdated = n

View File

@ -76,14 +76,19 @@ func initialize() error {
return nil return nil
} }
func Main() error { func Main(ch <-chan error) error {
return currentUI.main() return currentUI.main(ch)
} }
func (u *userInterface) main() error { func (u *userInterface) main(ch <-chan error) error {
// TODO: Check this is done on the main thread. // TODO: Check this is done on the main thread.
for f := range u.funcs { for {
f() select {
case f := <-u.funcs:
f()
case err := <-ch:
return err
}
} }
return nil return nil
} }

View File

@ -278,9 +278,8 @@ func devicePixelRatio() float64 {
return ratio return ratio
} }
func Main() error { func Main(ch <-chan error) error {
// Do nothing return <-ch
return nil
} }
func (u *userInterface) Start(width, height int, scale float64, title string) error { func (u *userInterface) Start(width, height int, scale float64, title string) error {

View File

@ -24,7 +24,7 @@ import (
"github.com/hajimehoshi/ebiten/internal/graphics/opengl" "github.com/hajimehoshi/ebiten/internal/graphics/opengl"
) )
func Main() error { func Main(ch <-chan error) error {
return errors.New("ui: don't call this: use RunWithoutMainLoop instead of Run") return errors.New("ui: don't call this: use RunWithoutMainLoop instead of Run")
} }

5
run.go
View File

@ -81,10 +81,11 @@ func Run(f func(*Image) error, width, height int, scale float64, title string) e
} }
close(ch) close(ch)
}() }()
if err := ui.Main(); err != nil { // TODO: Use context in Go 1.7?
if err := ui.Main(ch); err != nil {
return err return err
} }
return <-ch return nil
} }
// RunWithoutMainLoop runs the game, but don't call the loop on the main (UI) thread. // RunWithoutMainLoop runs the game, but don't call the loop on the main (UI) thread.