mirror of
https://github.com/hajimehoshi/ebiten.git
synced 2024-11-09 20:47:26 +01:00
ebiten: add RunGameWithOptions to specify graphics library
This also adds mobile.SetGameWithOptions. Updates #2378
This commit is contained in:
parent
032f55d19a
commit
bb68ebfcad
@ -26,6 +26,7 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
@ -35,18 +36,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
flagFullscreen = flag.Bool("fullscreen", false, "fullscreen")
|
flagFullscreen = flag.Bool("fullscreen", false, "fullscreen")
|
||||||
flagResizable = flag.Bool("resizable", false, "make the window resizable")
|
flagResizable = flag.Bool("resizable", false, "make the window resizable")
|
||||||
flagWindowPosition = flag.String("windowposition", "", "window position (e.g., 100,200)")
|
flagWindowPosition = flag.String("windowposition", "", "window position (e.g., 100,200)")
|
||||||
flagTransparent = flag.Bool("transparent", false, "screen transparent")
|
flagTransparent = flag.Bool("transparent", false, "screen transparent")
|
||||||
flagAutoAdjusting = flag.Bool("autoadjusting", false, "make the game screen auto-adjusting")
|
flagAutoAdjusting = flag.Bool("autoadjusting", false, "make the game screen auto-adjusting")
|
||||||
flagFloating = flag.Bool("floating", false, "make the window floating")
|
flagFloating = flag.Bool("floating", false, "make the window floating")
|
||||||
flagMaximize = flag.Bool("maximize", false, "maximize the window")
|
flagMaximize = flag.Bool("maximize", false, "maximize the window")
|
||||||
flagVsync = flag.Bool("vsync", true, "enable vsync")
|
flagVsync = flag.Bool("vsync", true, "enable vsync")
|
||||||
flagAutoRestore = flag.Bool("autorestore", false, "restore the window automatically")
|
flagAutoRestore = flag.Bool("autorestore", false, "restore the window automatically")
|
||||||
flagInitFocused = flag.Bool("initfocused", true, "whether the window is focused on start")
|
flagInitFocused = flag.Bool("initfocused", true, "whether the window is focused on start")
|
||||||
flagMinWindowSize = flag.String("minwindowsize", "", "minimum window size (e.g., 100x200)")
|
flagMinWindowSize = flag.String("minwindowsize", "", "minimum window size (e.g., 100x200)")
|
||||||
flagMaxWindowSize = flag.String("maxwindowsize", "", "maximium window size (e.g., 1920x1080)")
|
flagMaxWindowSize = flag.String("maxwindowsize", "", "maximium window size (e.g., 1920x1080)")
|
||||||
|
flagGraphicsLibrary = flag.String("graphicslibrary", "", "graphics library (e.g. opengl)")
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@ -93,6 +95,8 @@ type game struct {
|
|||||||
width float64
|
width float64
|
||||||
height float64
|
height float64
|
||||||
transparent bool
|
transparent bool
|
||||||
|
|
||||||
|
logOnce sync.Once
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *game) Layout(outsideWidth, outsideHeight int) (int, int) {
|
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 {
|
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 (
|
var (
|
||||||
screenWidth float64
|
screenWidth float64
|
||||||
screenHeight float64
|
screenHeight float64
|
||||||
@ -441,12 +451,26 @@ func main() {
|
|||||||
ebiten.SetWindowResizingMode(ebiten.WindowResizingModeEnabled)
|
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)"
|
const title = "Window Size (Ebitengine Demo)"
|
||||||
ww := int(float64(g.width) * initScreenScale)
|
ww := int(float64(g.width) * initScreenScale)
|
||||||
wh := int(float64(g.height) * initScreenScale)
|
wh := int(float64(g.height) * initScreenScale)
|
||||||
ebiten.SetWindowSize(ww, wh)
|
ebiten.SetWindowSize(ww, wh)
|
||||||
ebiten.SetWindowTitle(title)
|
ebiten.SetWindowTitle(title)
|
||||||
if err := ebiten.RunGame(g); err != nil {
|
if err := ebiten.RunGameWithOptions(g, op); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
22
graphics.go
22
graphics.go
@ -127,23 +127,33 @@ func (c CompositeMode) blend() Blend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GraphicsLibrary represets graphics libraries supported by the engine.
|
// GraphicsLibrary represets graphics libraries supported by the engine.
|
||||||
type GraphicsLibrary = ui.GraphicsLibrary
|
type GraphicsLibrary int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
GraphicsLibraryAuto GraphicsLibrary = GraphicsLibrary(ui.GraphicsLibraryAuto)
|
||||||
|
|
||||||
// GraphicsLibraryUnknown represents the state at which graphics library cannot be determined,
|
// GraphicsLibraryUnknown represents the state at which graphics library cannot be determined,
|
||||||
// e.g. hasn't loaded yet or failed to initialize.
|
// 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 represents the graphics library OpenGL.
|
||||||
GraphicsLibraryOpenGL GraphicsLibrary = ui.GraphicsLibraryOpenGL
|
GraphicsLibraryOpenGL GraphicsLibrary = GraphicsLibrary(ui.GraphicsLibraryOpenGL)
|
||||||
|
|
||||||
// GraphicsLibraryDirectX represents the graphics library Microsoft DirectX.
|
// 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 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.
|
// DebugInfo is a struct to store debug info about the graphics.
|
||||||
type DebugInfo struct {
|
type DebugInfo struct {
|
||||||
// GraphicsLibrary represents the graphics library currently in use.
|
// 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.
|
// ReadDebugInfo writes debug info (e.g. current graphics library) into a provided struct.
|
||||||
func ReadDebugInfo(d *DebugInfo) {
|
func ReadDebugInfo(d *DebugInfo) {
|
||||||
d.GraphicsLibrary = ui.GetGraphicsLibrary()
|
d.GraphicsLibrary = GraphicsLibrary(ui.GetGraphicsLibrary())
|
||||||
}
|
}
|
||||||
|
2
image.go
2
image.go
@ -543,7 +543,7 @@ type DrawTrianglesShaderOptions struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check the number of images.
|
// 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.
|
// DrawTrianglesShader draws triangles with the specified vertices and their indices with the specified shader.
|
||||||
//
|
//
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
|
|
||||||
var theGlobalState = globalState{
|
var theGlobalState = globalState{
|
||||||
isScreenClearedEveryFrame_: 1,
|
isScreenClearedEveryFrame_: 1,
|
||||||
|
graphicsLibrary_: int32(GraphicsLibraryUnknown),
|
||||||
}
|
}
|
||||||
|
|
||||||
// globalState represents a global state in this package.
|
// globalState represents a global state in this package.
|
||||||
|
@ -28,7 +28,7 @@ type graphicsDriverCreator interface {
|
|||||||
newMetal() (graphicsdriver.Graphics, error)
|
newMetal() (graphicsdriver.Graphics, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newGraphicsDriver(creator graphicsDriverCreator) (graphicsdriver.Graphics, error) {
|
func newGraphicsDriver(creator graphicsDriverCreator, graphicsLibrary GraphicsLibrary) (graphicsdriver.Graphics, error) {
|
||||||
envName := "EBITENGINE_GRAPHICS_LIBRARY"
|
envName := "EBITENGINE_GRAPHICS_LIBRARY"
|
||||||
env := os.Getenv(envName)
|
env := os.Getenv(envName)
|
||||||
if env == "" {
|
if env == "" {
|
||||||
@ -39,6 +39,20 @@ func newGraphicsDriver(creator graphicsDriverCreator) (graphicsdriver.Graphics,
|
|||||||
|
|
||||||
switch env {
|
switch env {
|
||||||
case "", "auto":
|
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()
|
g, lib, err := creator.newAuto()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -48,41 +62,68 @@ func newGraphicsDriver(creator graphicsDriverCreator) (graphicsdriver.Graphics,
|
|||||||
}
|
}
|
||||||
theGlobalState.setGraphicsLibrary(lib)
|
theGlobalState.setGraphicsLibrary(lib)
|
||||||
return g, nil
|
return g, nil
|
||||||
case "opengl":
|
case GraphicsLibraryOpenGL:
|
||||||
g, err := creator.newOpenGL()
|
g, err := creator.newOpenGL()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if g == nil {
|
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)
|
theGlobalState.setGraphicsLibrary(GraphicsLibraryOpenGL)
|
||||||
return g, nil
|
return g, nil
|
||||||
case "directx":
|
case GraphicsLibraryDirectX:
|
||||||
g, err := creator.newDirectX()
|
g, err := creator.newDirectX()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if g == nil {
|
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)
|
theGlobalState.setGraphicsLibrary(GraphicsLibraryDirectX)
|
||||||
return g, nil
|
return g, nil
|
||||||
case "metal":
|
case GraphicsLibraryMetal:
|
||||||
g, err := creator.newMetal()
|
g, err := creator.newMetal()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if g == nil {
|
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)
|
theGlobalState.setGraphicsLibrary(GraphicsLibraryMetal)
|
||||||
return g, nil
|
return g, nil
|
||||||
default:
|
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 {
|
func GraphicsDriverForTesting() graphicsdriver.Graphics {
|
||||||
return theUI.graphicsDriver
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -21,7 +21,7 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/internal/thread"
|
"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)
|
u.context = newContext(game)
|
||||||
|
|
||||||
// Initialize the main thread first so the thread is available at u.run (#809).
|
// 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
|
var err error
|
||||||
if u.t.Call(func() {
|
if u.t.Call(func() {
|
||||||
err = u.init()
|
err = u.init(options)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
ch <- err
|
ch <- err
|
||||||
return
|
return
|
||||||
|
@ -21,7 +21,7 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/internal/thread"
|
"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)
|
u.context = newContext(game)
|
||||||
|
|
||||||
// Initialize the main thread first so the thread is available at u.run (#809).
|
// 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)
|
u.setRunning(true)
|
||||||
|
|
||||||
if err := u.init(); err != nil {
|
if err := u.init(options); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,15 +73,6 @@ const (
|
|||||||
WindowResizingModeEnabled
|
WindowResizingModeEnabled
|
||||||
)
|
)
|
||||||
|
|
||||||
type GraphicsLibrary int
|
|
||||||
|
|
||||||
const (
|
|
||||||
GraphicsLibraryUnknown GraphicsLibrary = iota
|
|
||||||
GraphicsLibraryOpenGL
|
|
||||||
GraphicsLibraryDirectX
|
|
||||||
GraphicsLibraryMetal
|
|
||||||
)
|
|
||||||
|
|
||||||
type UserInterface struct {
|
type UserInterface struct {
|
||||||
userInterfaceImpl
|
userInterfaceImpl
|
||||||
}
|
}
|
||||||
@ -104,3 +95,7 @@ func (u *UserInterface) dumpScreenshot(mipmap *mipmap.Mipmap, name string, black
|
|||||||
func (u *UserInterface) dumpImages(dir string) (string, error) {
|
func (u *UserInterface) dumpImages(dir string) (string, error) {
|
||||||
return atlas.DumpImages(u.graphicsDriver, dir)
|
return atlas.DumpImages(u.graphicsDriver, dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RunOptions struct {
|
||||||
|
GraphicsLibrary GraphicsLibrary
|
||||||
|
}
|
||||||
|
@ -888,7 +888,7 @@ event:
|
|||||||
u.framebufferSizeCallbackCh = nil
|
u.framebufferSizeCallbackCh = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *userInterfaceImpl) init() error {
|
func (u *userInterfaceImpl) init(options *RunOptions) error {
|
||||||
glfw.WindowHint(glfw.AutoIconify, glfw.False)
|
glfw.WindowHint(glfw.AutoIconify, glfw.False)
|
||||||
|
|
||||||
decorated := glfw.False
|
decorated := glfw.False
|
||||||
@ -906,7 +906,7 @@ func (u *userInterfaceImpl) init() error {
|
|||||||
|
|
||||||
g, err := newGraphicsDriver(&graphicsDriverCreatorImpl{
|
g, err := newGraphicsDriver(&graphicsDriverCreatorImpl{
|
||||||
transparent: transparent,
|
transparent: transparent,
|
||||||
})
|
}, options.GraphicsLibrary)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -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() {
|
if u.initFocused && window.Truthy() {
|
||||||
// Do not focus the canvas when the current document is in an iframe.
|
// 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).
|
// 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
|
u.running = true
|
||||||
g, err := newGraphicsDriver(&graphicsDriverCreatorImpl{
|
g, err := newGraphicsDriver(&graphicsDriverCreatorImpl{
|
||||||
canvas: canvas,
|
canvas: canvas,
|
||||||
})
|
}, options.GraphicsLibrary)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -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{})
|
u.setGBuildSizeCh = make(chan struct{})
|
||||||
go func() {
|
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.
|
// As mobile apps never ends, Loop can't return. Just panic here.
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -247,19 +247,19 @@ func (u *userInterfaceImpl) Run(game Game) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunWithoutMainLoop(game Game) {
|
func RunWithoutMainLoop(game Game, options *RunOptions) {
|
||||||
theUI.runWithoutMainLoop(game)
|
theUI.runWithoutMainLoop(game, options)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *userInterfaceImpl) runWithoutMainLoop(game Game) {
|
func (u *userInterfaceImpl) runWithoutMainLoop(game Game, options *RunOptions) {
|
||||||
go func() {
|
go func() {
|
||||||
if err := u.run(game, false); err != nil {
|
if err := u.run(game, false, options); err != nil {
|
||||||
u.errCh <- err
|
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
|
// 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
|
// Crashlytics. A panic is treated as SIGABRT, and there is no way to handle this on Java/Objective-C layer
|
||||||
// unfortunately.
|
// unfortunately.
|
||||||
@ -284,7 +284,7 @@ func (u *userInterfaceImpl) run(game Game, mainloop bool) (err error) {
|
|||||||
|
|
||||||
g, err := newGraphicsDriver(&graphicsDriverCreatorImpl{
|
g, err := newGraphicsDriver(&graphicsDriverCreatorImpl{
|
||||||
gomobileContext: mgl,
|
gomobileContext: mgl,
|
||||||
})
|
}, options.GraphicsLibrary)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -56,9 +56,9 @@ type userInterfaceImpl struct {
|
|||||||
input Input
|
input Input
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *userInterfaceImpl) Run(game Game) error {
|
func (u *userInterfaceImpl) Run(game Game, options *RunOptions) error {
|
||||||
u.context = newContext(game)
|
u.context = newContext(game)
|
||||||
g, err := newGraphicsDriver(&graphicsDriverCreatorImpl{})
|
g, err := newGraphicsDriver(&graphicsDriverCreatorImpl{}, options.GraphicsLibrary)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -49,11 +49,11 @@ func (s *state) run() {
|
|||||||
atomic.StoreInt32(&s.running, 1)
|
atomic.StoreInt32(&s.running, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetGame(game ebiten.Game) {
|
func SetGame(game ebiten.Game, options *ebiten.RunGameOptions) {
|
||||||
if theState.isRunning() {
|
if theState.isRunning() {
|
||||||
panic("ebitenmobileview: SetGame cannot be called twice or more")
|
panic("ebitenmobileview: SetGame cannot be called twice or more")
|
||||||
}
|
}
|
||||||
ebiten.RunGameWithoutMainLoop(game)
|
ebiten.RunGameWithoutMainLoop(game, options)
|
||||||
theState.run()
|
theState.run()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,6 +21,6 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2/mobile/ebitenmobileview"
|
"github.com/hajimehoshi/ebiten/v2/mobile/ebitenmobileview"
|
||||||
)
|
)
|
||||||
|
|
||||||
func setGame(game ebiten.Game) {
|
func setGame(game ebiten.Game, options *ebiten.RunGameOptions) {
|
||||||
ebitenmobileview.SetGame(game)
|
ebitenmobileview.SetGame(game, options)
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,6 @@ import (
|
|||||||
"github.com/hajimehoshi/ebiten/v2"
|
"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")
|
panic("mobile: setGame is not implemented in this environment")
|
||||||
}
|
}
|
||||||
|
@ -29,5 +29,14 @@ import (
|
|||||||
//
|
//
|
||||||
// SetGame can be called anytime. Until SetGame is called, the game does not start.
|
// SetGame can be called anytime. Until SetGame is called, the game does not start.
|
||||||
func SetGame(game ebiten.Game) {
|
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)
|
||||||
}
|
}
|
||||||
|
57
run.go
57
run.go
@ -224,13 +224,57 @@ var Termination = ui.RegularTermination
|
|||||||
//
|
//
|
||||||
// The size unit is device-independent pixel.
|
// 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 {
|
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)
|
defer atomic.StoreInt32(&isRunGameEnded_, 1)
|
||||||
|
|
||||||
initializeWindowPositionIfNeeded(WindowSize())
|
initializeWindowPositionIfNeeded(WindowSize())
|
||||||
g := newGameForUI(game)
|
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) {
|
if errors.Is(err, Termination) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -557,3 +601,12 @@ func SetScreenTransparent(transparent bool) {
|
|||||||
func SetInitFocused(focused bool) {
|
func SetInitFocused(focused bool) {
|
||||||
ui.Get().SetInitFocused(focused)
|
ui.Get().SetInitFocused(focused)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func toUIRunOptions(options *RunGameOptions) *ui.RunOptions {
|
||||||
|
if options == nil {
|
||||||
|
return &ui.RunOptions{}
|
||||||
|
}
|
||||||
|
return &ui.RunOptions{
|
||||||
|
GraphicsLibrary: ui.GraphicsLibrary(options.GraphicsLibrary),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -27,6 +27,6 @@ import (
|
|||||||
// Instead, functions in github.com/hajimehoshi/ebiten/v2/mobile package calls this.
|
// 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.
|
// TODO: Remove this. In order to remove this, the gameForUI should be in another package.
|
||||||
func RunGameWithoutMainLoop(game Game) {
|
func RunGameWithoutMainLoop(game Game, options *RunGameOptions) {
|
||||||
ui.RunWithoutMainLoop(newGameForUI(game))
|
ui.RunWithoutMainLoop(newGameForUI(game), toUIRunOptions(options))
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user