From bb68ebfcad3dce1eb772116570dd4eed8082c330 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Fri, 9 Dec 2022 14:07:04 +0900 Subject: [PATCH] ebiten: add RunGameWithOptions to specify graphics library This also adds mobile.SetGameWithOptions. Updates #2378 --- examples/windowsize/main.go | 50 +++++++++++++++++++------- graphics.go | 22 ++++++++---- image.go | 2 +- internal/ui/globalstate.go | 1 + internal/ui/graphics.go | 57 +++++++++++++++++++++++++----- internal/ui/run_notsinglethread.go | 4 +-- internal/ui/run_singlethread.go | 4 +-- internal/ui/ui.go | 13 +++---- internal/ui/ui_glfw.go | 4 +-- internal/ui/ui_js.go | 4 +-- internal/ui/ui_mobile.go | 16 ++++----- internal/ui/ui_nintendosdk.go | 4 +-- mobile/ebitenmobileview/mobile.go | 4 +-- mobile/impl_mobile.go | 4 +-- mobile/impl_notmobile.go | 2 +- mobile/mobile.go | 11 +++++- run.go | 57 ++++++++++++++++++++++++++++-- run_mobile.go | 4 +-- 18 files changed, 198 insertions(+), 65 deletions(-) diff --git a/examples/windowsize/main.go b/examples/windowsize/main.go index c3ad33fad..b50562c68 100644 --- a/examples/windowsize/main.go +++ b/examples/windowsize/main.go @@ -26,6 +26,7 @@ import ( "regexp" "strconv" "strings" + "sync" "time" "github.com/hajimehoshi/ebiten/v2" @@ -35,18 +36,19 @@ import ( ) var ( - flagFullscreen = flag.Bool("fullscreen", false, "fullscreen") - flagResizable = flag.Bool("resizable", false, "make the window resizable") - flagWindowPosition = flag.String("windowposition", "", "window position (e.g., 100,200)") - flagTransparent = flag.Bool("transparent", false, "screen transparent") - flagAutoAdjusting = flag.Bool("autoadjusting", false, "make the game screen auto-adjusting") - flagFloating = flag.Bool("floating", false, "make the window floating") - flagMaximize = flag.Bool("maximize", false, "maximize the window") - flagVsync = flag.Bool("vsync", true, "enable vsync") - flagAutoRestore = flag.Bool("autorestore", false, "restore the window automatically") - flagInitFocused = flag.Bool("initfocused", true, "whether the window is focused on start") - flagMinWindowSize = flag.String("minwindowsize", "", "minimum window size (e.g., 100x200)") - flagMaxWindowSize = flag.String("maxwindowsize", "", "maximium window size (e.g., 1920x1080)") + flagFullscreen = flag.Bool("fullscreen", false, "fullscreen") + flagResizable = flag.Bool("resizable", false, "make the window resizable") + flagWindowPosition = flag.String("windowposition", "", "window position (e.g., 100,200)") + flagTransparent = flag.Bool("transparent", false, "screen transparent") + flagAutoAdjusting = flag.Bool("autoadjusting", false, "make the game screen auto-adjusting") + flagFloating = flag.Bool("floating", false, "make the window floating") + flagMaximize = flag.Bool("maximize", false, "maximize the window") + flagVsync = flag.Bool("vsync", true, "enable vsync") + flagAutoRestore = flag.Bool("autorestore", false, "restore the window automatically") + flagInitFocused = flag.Bool("initfocused", true, "whether the window is focused on start") + flagMinWindowSize = flag.String("minwindowsize", "", "minimum window size (e.g., 100x200)") + flagMaxWindowSize = flag.String("maxwindowsize", "", "maximium window size (e.g., 1920x1080)") + flagGraphicsLibrary = flag.String("graphicslibrary", "", "graphics library (e.g. opengl)") ) func init() { @@ -93,6 +95,8 @@ type game struct { width float64 height float64 transparent bool + + logOnce sync.Once } func (g *game) Layout(outsideWidth, outsideHeight int) (int, int) { @@ -111,6 +115,12 @@ func (g *game) LayoutF(outsideWidth, outsideHeight float64) (float64, float64) { } func (g *game) Update() error { + g.logOnce.Do(func() { + var debug ebiten.DebugInfo + ebiten.ReadDebugInfo(&debug) + fmt.Printf("Graphics library: %s\n", debug.GraphicsLibrary) + }) + var ( screenWidth float64 screenHeight float64 @@ -441,12 +451,26 @@ func main() { ebiten.SetWindowResizingMode(ebiten.WindowResizingModeEnabled) } + op := &ebiten.RunGameOptions{} + switch *flagGraphicsLibrary { + case "": + op.GraphicsLibrary = ebiten.GraphicsLibraryAuto + case "opengl": + op.GraphicsLibrary = ebiten.GraphicsLibraryOpenGL + case "directx": + op.GraphicsLibrary = ebiten.GraphicsLibraryDirectX + case "metal": + op.GraphicsLibrary = ebiten.GraphicsLibraryMetal + default: + log.Fatalf("unexpected graphics library: %s", *flagGraphicsLibrary) + } + const title = "Window Size (Ebitengine Demo)" ww := int(float64(g.width) * initScreenScale) wh := int(float64(g.height) * initScreenScale) ebiten.SetWindowSize(ww, wh) ebiten.SetWindowTitle(title) - if err := ebiten.RunGame(g); err != nil { + if err := ebiten.RunGameWithOptions(g, op); err != nil { log.Fatal(err) } } diff --git a/graphics.go b/graphics.go index 95dca10aa..eb7a21b1b 100644 --- a/graphics.go +++ b/graphics.go @@ -127,23 +127,33 @@ func (c CompositeMode) blend() Blend { } // GraphicsLibrary represets graphics libraries supported by the engine. -type GraphicsLibrary = ui.GraphicsLibrary +type GraphicsLibrary int const ( + GraphicsLibraryAuto GraphicsLibrary = GraphicsLibrary(ui.GraphicsLibraryAuto) + // GraphicsLibraryUnknown represents the state at which graphics library cannot be determined, // e.g. hasn't loaded yet or failed to initialize. - GraphicsLibraryUnknown GraphicsLibrary = ui.GraphicsLibraryUnknown + GraphicsLibraryUnknown GraphicsLibrary = GraphicsLibrary(ui.GraphicsLibraryUnknown) // GraphicsLibraryOpenGL represents the graphics library OpenGL. - GraphicsLibraryOpenGL GraphicsLibrary = ui.GraphicsLibraryOpenGL + GraphicsLibraryOpenGL GraphicsLibrary = GraphicsLibrary(ui.GraphicsLibraryOpenGL) // GraphicsLibraryDirectX represents the graphics library Microsoft DirectX. - GraphicsLibraryDirectX GraphicsLibrary = ui.GraphicsLibraryDirectX + GraphicsLibraryDirectX GraphicsLibrary = GraphicsLibrary(ui.GraphicsLibraryDirectX) // GraphicsLibraryMetal represents the graphics library Apple's Metal. - GraphicsLibraryMetal GraphicsLibrary = ui.GraphicsLibraryMetal + GraphicsLibraryMetal GraphicsLibrary = GraphicsLibrary(ui.GraphicsLibraryMetal) ) +// String returns a string representing the graphics library. +func (g GraphicsLibrary) String() string { + return ui.GraphicsLibrary(g).String() +} + +// Ensures GraphicsLibraryAuto is zero (the default value for RunOptions). +var _ [GraphicsLibraryAuto]int = [0]int{} + // DebugInfo is a struct to store debug info about the graphics. type DebugInfo struct { // GraphicsLibrary represents the graphics library currently in use. @@ -152,5 +162,5 @@ type DebugInfo struct { // ReadDebugInfo writes debug info (e.g. current graphics library) into a provided struct. func ReadDebugInfo(d *DebugInfo) { - d.GraphicsLibrary = ui.GetGraphicsLibrary() + d.GraphicsLibrary = GraphicsLibrary(ui.GetGraphicsLibrary()) } diff --git a/image.go b/image.go index 7e64fae90..0716007c4 100644 --- a/image.go +++ b/image.go @@ -543,7 +543,7 @@ type DrawTrianglesShaderOptions struct { } // Check the number of images. -var _ [len(DrawTrianglesShaderOptions{}.Images)]struct{} = [graphics.ShaderImageCount]struct{}{} +var _ [len(DrawTrianglesShaderOptions{}.Images) - graphics.ShaderImageCount]struct{} = [0]struct{}{} // DrawTrianglesShader draws triangles with the specified vertices and their indices with the specified shader. // diff --git a/internal/ui/globalstate.go b/internal/ui/globalstate.go index 0b1f5c216..bb0a2a32d 100644 --- a/internal/ui/globalstate.go +++ b/internal/ui/globalstate.go @@ -21,6 +21,7 @@ import ( var theGlobalState = globalState{ isScreenClearedEveryFrame_: 1, + graphicsLibrary_: int32(GraphicsLibraryUnknown), } // globalState represents a global state in this package. diff --git a/internal/ui/graphics.go b/internal/ui/graphics.go index 552083152..a87c5a608 100644 --- a/internal/ui/graphics.go +++ b/internal/ui/graphics.go @@ -28,7 +28,7 @@ type graphicsDriverCreator interface { newMetal() (graphicsdriver.Graphics, error) } -func newGraphicsDriver(creator graphicsDriverCreator) (graphicsdriver.Graphics, error) { +func newGraphicsDriver(creator graphicsDriverCreator, graphicsLibrary GraphicsLibrary) (graphicsdriver.Graphics, error) { envName := "EBITENGINE_GRAPHICS_LIBRARY" env := os.Getenv(envName) if env == "" { @@ -39,6 +39,20 @@ func newGraphicsDriver(creator graphicsDriverCreator) (graphicsdriver.Graphics, switch env { case "", "auto": + // Use the specified graphics library. + // Otherwise, prefer the environment variable. + case "opengl": + graphicsLibrary = GraphicsLibraryOpenGL + case "directx": + graphicsLibrary = GraphicsLibraryDirectX + case "metal": + graphicsLibrary = GraphicsLibraryMetal + default: + return nil, fmt.Errorf("ui: an unsupported graphics library is specified by the environment variable: %s", env) + } + + switch graphicsLibrary { + case GraphicsLibraryAuto: g, lib, err := creator.newAuto() if err != nil { return nil, err @@ -48,41 +62,68 @@ func newGraphicsDriver(creator graphicsDriverCreator) (graphicsdriver.Graphics, } theGlobalState.setGraphicsLibrary(lib) return g, nil - case "opengl": + case GraphicsLibraryOpenGL: g, err := creator.newOpenGL() if err != nil { return nil, err } if g == nil { - return nil, fmt.Errorf("ui: %s=%s is specified but OpenGL is not available", envName, env) + return nil, fmt.Errorf("ui: %s is specified but OpenGL is not available", graphicsLibrary) } theGlobalState.setGraphicsLibrary(GraphicsLibraryOpenGL) return g, nil - case "directx": + case GraphicsLibraryDirectX: g, err := creator.newDirectX() if err != nil { return nil, err } if g == nil { - return nil, fmt.Errorf("ui: %s=%s is specified but DirectX is not available.", envName, env) + return nil, fmt.Errorf("ui: %s is specified but DirectX is not available.", graphicsLibrary) } theGlobalState.setGraphicsLibrary(GraphicsLibraryDirectX) return g, nil - case "metal": + case GraphicsLibraryMetal: g, err := creator.newMetal() if err != nil { return nil, err } if g == nil { - return nil, fmt.Errorf("ui: %s=%s is specified but Metal is not available", envName, env) + return nil, fmt.Errorf("ui: %s is specified but Metal is not available", graphicsLibrary) } theGlobalState.setGraphicsLibrary(GraphicsLibraryMetal) return g, nil default: - return nil, fmt.Errorf("ui: an unsupported graphics library is specified: %s", env) + return nil, fmt.Errorf("ui: an unsupported graphics library is specified: %d", graphicsLibrary) } } func GraphicsDriverForTesting() graphicsdriver.Graphics { return theUI.graphicsDriver } + +type GraphicsLibrary int + +const ( + GraphicsLibraryAuto GraphicsLibrary = iota + GraphicsLibraryOpenGL + GraphicsLibraryDirectX + GraphicsLibraryMetal + GraphicsLibraryUnknown +) + +func (g GraphicsLibrary) String() string { + switch g { + case GraphicsLibraryAuto: + return "Auto" + case GraphicsLibraryOpenGL: + return "OpenGL" + case GraphicsLibraryDirectX: + return "DirectX" + case GraphicsLibraryMetal: + return "Metal" + case GraphicsLibraryUnknown: + return "Unknown" + default: + return fmt.Sprintf("GraphicsLibrary(%d)", g) + } +} diff --git a/internal/ui/run_notsinglethread.go b/internal/ui/run_notsinglethread.go index 6a66e4f1f..a57f499c0 100644 --- a/internal/ui/run_notsinglethread.go +++ b/internal/ui/run_notsinglethread.go @@ -21,7 +21,7 @@ import ( "github.com/hajimehoshi/ebiten/v2/internal/thread" ) -func (u *userInterfaceImpl) Run(game Game) error { +func (u *userInterfaceImpl) Run(game Game, options *RunOptions) error { u.context = newContext(game) // Initialize the main thread first so the thread is available at u.run (#809). @@ -36,7 +36,7 @@ func (u *userInterfaceImpl) Run(game Game) error { var err error if u.t.Call(func() { - err = u.init() + err = u.init(options) }); err != nil { ch <- err return diff --git a/internal/ui/run_singlethread.go b/internal/ui/run_singlethread.go index 8ce2387e8..736cf3008 100644 --- a/internal/ui/run_singlethread.go +++ b/internal/ui/run_singlethread.go @@ -21,7 +21,7 @@ import ( "github.com/hajimehoshi/ebiten/v2/internal/thread" ) -func (u *userInterfaceImpl) Run(game Game) error { +func (u *userInterfaceImpl) Run(game Game, options *RunOptions) error { u.context = newContext(game) // Initialize the main thread first so the thread is available at u.run (#809). @@ -30,7 +30,7 @@ func (u *userInterfaceImpl) Run(game Game) error { u.setRunning(true) - if err := u.init(); err != nil { + if err := u.init(options); err != nil { return err } diff --git a/internal/ui/ui.go b/internal/ui/ui.go index 2c6f00aca..f41f4a09b 100644 --- a/internal/ui/ui.go +++ b/internal/ui/ui.go @@ -73,15 +73,6 @@ const ( WindowResizingModeEnabled ) -type GraphicsLibrary int - -const ( - GraphicsLibraryUnknown GraphicsLibrary = iota - GraphicsLibraryOpenGL - GraphicsLibraryDirectX - GraphicsLibraryMetal -) - type UserInterface struct { userInterfaceImpl } @@ -104,3 +95,7 @@ func (u *UserInterface) dumpScreenshot(mipmap *mipmap.Mipmap, name string, black func (u *UserInterface) dumpImages(dir string) (string, error) { return atlas.DumpImages(u.graphicsDriver, dir) } + +type RunOptions struct { + GraphicsLibrary GraphicsLibrary +} diff --git a/internal/ui/ui_glfw.go b/internal/ui/ui_glfw.go index a0fae48da..6b48e417f 100644 --- a/internal/ui/ui_glfw.go +++ b/internal/ui/ui_glfw.go @@ -888,7 +888,7 @@ event: u.framebufferSizeCallbackCh = nil } -func (u *userInterfaceImpl) init() error { +func (u *userInterfaceImpl) init(options *RunOptions) error { glfw.WindowHint(glfw.AutoIconify, glfw.False) decorated := glfw.False @@ -906,7 +906,7 @@ func (u *userInterfaceImpl) init() error { g, err := newGraphicsDriver(&graphicsDriverCreatorImpl{ transparent: transparent, - }) + }, options.GraphicsLibrary) if err != nil { return err } diff --git a/internal/ui/ui_js.go b/internal/ui/ui_js.go index f2e951eb5..b8834de58 100644 --- a/internal/ui/ui_js.go +++ b/internal/ui/ui_js.go @@ -637,7 +637,7 @@ func (u *userInterfaceImpl) forceUpdateOnMinimumFPSMode() { }() } -func (u *userInterfaceImpl) Run(game Game) error { +func (u *userInterfaceImpl) Run(game Game, options *RunOptions) error { if u.initFocused && window.Truthy() { // Do not focus the canvas when the current document is in an iframe. // Otherwise, the parent page tries to focus the iframe on every loading, which is annoying (#1373). @@ -649,7 +649,7 @@ func (u *userInterfaceImpl) Run(game Game) error { u.running = true g, err := newGraphicsDriver(&graphicsDriverCreatorImpl{ canvas: canvas, - }) + }, options.GraphicsLibrary) if err != nil { return err } diff --git a/internal/ui/ui_mobile.go b/internal/ui/ui_mobile.go index a5fb6cf27..953fe9b70 100644 --- a/internal/ui/ui_mobile.go +++ b/internal/ui/ui_mobile.go @@ -235,10 +235,10 @@ func (u *userInterfaceImpl) SetForeground(foreground bool) error { } } -func (u *userInterfaceImpl) Run(game Game) error { +func (u *userInterfaceImpl) Run(game Game, options *RunOptions) error { u.setGBuildSizeCh = make(chan struct{}) go func() { - if err := u.run(game, true); err != nil { + if err := u.run(game, true, options); err != nil { // As mobile apps never ends, Loop can't return. Just panic here. panic(err) } @@ -247,19 +247,19 @@ func (u *userInterfaceImpl) Run(game Game) error { return nil } -func RunWithoutMainLoop(game Game) { - theUI.runWithoutMainLoop(game) +func RunWithoutMainLoop(game Game, options *RunOptions) { + theUI.runWithoutMainLoop(game, options) } -func (u *userInterfaceImpl) runWithoutMainLoop(game Game) { +func (u *userInterfaceImpl) runWithoutMainLoop(game Game, options *RunOptions) { go func() { - if err := u.run(game, false); err != nil { + if err := u.run(game, false, options); err != nil { u.errCh <- err } }() } -func (u *userInterfaceImpl) run(game Game, mainloop bool) (err error) { +func (u *userInterfaceImpl) run(game Game, mainloop bool, options *RunOptions) (err error) { // Convert the panic to a regular error so that Java/Objective-C layer can treat this easily e.g., for // Crashlytics. A panic is treated as SIGABRT, and there is no way to handle this on Java/Objective-C layer // unfortunately. @@ -284,7 +284,7 @@ func (u *userInterfaceImpl) run(game Game, mainloop bool) (err error) { g, err := newGraphicsDriver(&graphicsDriverCreatorImpl{ gomobileContext: mgl, - }) + }, options.GraphicsLibrary) if err != nil { return err } diff --git a/internal/ui/ui_nintendosdk.go b/internal/ui/ui_nintendosdk.go index 08250b317..c095ff418 100644 --- a/internal/ui/ui_nintendosdk.go +++ b/internal/ui/ui_nintendosdk.go @@ -56,9 +56,9 @@ type userInterfaceImpl struct { input Input } -func (u *userInterfaceImpl) Run(game Game) error { +func (u *userInterfaceImpl) Run(game Game, options *RunOptions) error { u.context = newContext(game) - g, err := newGraphicsDriver(&graphicsDriverCreatorImpl{}) + g, err := newGraphicsDriver(&graphicsDriverCreatorImpl{}, options.GraphicsLibrary) if err != nil { return err } diff --git a/mobile/ebitenmobileview/mobile.go b/mobile/ebitenmobileview/mobile.go index 6616b45f8..692f1037d 100644 --- a/mobile/ebitenmobileview/mobile.go +++ b/mobile/ebitenmobileview/mobile.go @@ -49,11 +49,11 @@ func (s *state) run() { atomic.StoreInt32(&s.running, 1) } -func SetGame(game ebiten.Game) { +func SetGame(game ebiten.Game, options *ebiten.RunGameOptions) { if theState.isRunning() { panic("ebitenmobileview: SetGame cannot be called twice or more") } - ebiten.RunGameWithoutMainLoop(game) + ebiten.RunGameWithoutMainLoop(game, options) theState.run() } diff --git a/mobile/impl_mobile.go b/mobile/impl_mobile.go index b8b864762..d8290d42e 100644 --- a/mobile/impl_mobile.go +++ b/mobile/impl_mobile.go @@ -21,6 +21,6 @@ import ( "github.com/hajimehoshi/ebiten/v2/mobile/ebitenmobileview" ) -func setGame(game ebiten.Game) { - ebitenmobileview.SetGame(game) +func setGame(game ebiten.Game, options *ebiten.RunGameOptions) { + ebitenmobileview.SetGame(game, options) } diff --git a/mobile/impl_notmobile.go b/mobile/impl_notmobile.go index 93364daa3..948e9bda9 100644 --- a/mobile/impl_notmobile.go +++ b/mobile/impl_notmobile.go @@ -20,6 +20,6 @@ import ( "github.com/hajimehoshi/ebiten/v2" ) -func setGame(game ebiten.Game) { +func setGame(game ebiten.Game, options *ebiten.RunGameOptions) { panic("mobile: setGame is not implemented in this environment") } diff --git a/mobile/mobile.go b/mobile/mobile.go index 80319d60a..96b61b8ba 100644 --- a/mobile/mobile.go +++ b/mobile/mobile.go @@ -29,5 +29,14 @@ import ( // // SetGame can be called anytime. Until SetGame is called, the game does not start. func SetGame(game ebiten.Game) { - setGame(game) + SetGameWithOptions(game, nil) +} + +// SetGameWithOptions sets a mobile game with the specified options. +// +// SetGameWithOptions is expected to be called only once. +// +// SetGameWithOptions can be called anytime. Until SetGameWithOptions is called, the game does not start. +func SetGameWithOptions(game ebiten.Game, options *ebiten.RunGameOptions) { + setGame(game, options) } diff --git a/run.go b/run.go index e6d4967f4..7ac42eaa6 100644 --- a/run.go +++ b/run.go @@ -224,13 +224,57 @@ var Termination = ui.RegularTermination // // The size unit is device-independent pixel. // -// Don't call RunGame twice or more in one process. +// Don't call RunGame or RunGameWithOptions twice or more in one process. func RunGame(game Game) error { + return RunGameWithOptions(game, nil) +} + +// RungameOptions represents options for RunGameWithOptions. +type RunGameOptions struct { + // GraphicsLibrary is a graphics library Ebitengine will use. + // The default (zero) value is GraphicsLibraryAuto, which lets Ebitengine choose the graphics library. + GraphicsLibrary GraphicsLibrary +} + +// RunGameWithOptions starts the main loop and runs the game with the specified options. +// game's Update function is called every tick to update the game logic. +// game's Draw function is called every frame to draw the screen. +// game's Layout function is called when necessary, and you can specify the logical screen size by the function. +// +// options can be nil. In this case, the default options are used. +// +// If game implements FinalScreenDrawer, its DrawFinalScreen is called after Draw. +// The argument screen represents the final screen. The argument offscreen is an offscreen modified at Draw. +// If game does not implement FinalScreenDrawer, the dafault rendering for the final screen is used. +// +// game's functions are called on the same goroutine. +// +// On browsers, it is strongly recommended to use iframe if you embed an Ebitengine application in your website. +// +// RunGameWithOptions must be called on the main thread. +// Note that Ebitengine bounds the main goroutine to the main OS thread by runtime.LockOSThread. +// +// Ebitengine tries to call game's Update function 60 times a second by default. In other words, +// TPS (ticks per second) is 60 by default. +// This is not related to framerate (display's refresh rate). +// +// RunGameWithOptions returns error when 1) an error happens in the underlying graphics driver, 2) an audio error happens +// or 3) Update returns an error. In the case of 3), RunGameWithOptions returns the same error so far, but it is recommended to +// use errors.Is when you check the returned error is the error you want, rather than comparing the values +// with == or != directly. +// +// If you want to terminate a game on desktops, it is recommended to return Termination at Update, which will halt +// execution without returning an error value from RunGameWithOptions. +// +// The size unit is device-independent pixel. +// +// Don't call RunGame or RunGameWithOptions twice or more in one process. +func RunGameWithOptions(game Game, options *RunGameOptions) error { defer atomic.StoreInt32(&isRunGameEnded_, 1) initializeWindowPositionIfNeeded(WindowSize()) g := newGameForUI(game) - if err := ui.Get().Run(g); err != nil { + if err := ui.Get().Run(g, toUIRunOptions(options)); err != nil { if errors.Is(err, Termination) { return nil } @@ -557,3 +601,12 @@ func SetScreenTransparent(transparent bool) { func SetInitFocused(focused bool) { ui.Get().SetInitFocused(focused) } + +func toUIRunOptions(options *RunGameOptions) *ui.RunOptions { + if options == nil { + return &ui.RunOptions{} + } + return &ui.RunOptions{ + GraphicsLibrary: ui.GraphicsLibrary(options.GraphicsLibrary), + } +} diff --git a/run_mobile.go b/run_mobile.go index 543b61324..6bed87d6e 100644 --- a/run_mobile.go +++ b/run_mobile.go @@ -27,6 +27,6 @@ import ( // Instead, functions in github.com/hajimehoshi/ebiten/v2/mobile package calls this. // // TODO: Remove this. In order to remove this, the gameForUI should be in another package. -func RunGameWithoutMainLoop(game Game) { - ui.RunWithoutMainLoop(newGameForUI(game)) +func RunGameWithoutMainLoop(game Game, options *RunGameOptions) { + ui.RunWithoutMainLoop(newGameForUI(game), toUIRunOptions(options)) }