Mobile

TL;DR

Use ebitenmobile command to create a shared library. The generated library includes a complete and easy-to-use view (or view controller) class.

Creating a shared library with ebitenmobile bind

Installing ebitenmobile

Install ebitenmobile command first.

go install github.com/hajimehoshi/ebiten/v2/cmd/ebitenmobile@latest

Creating a binding

Create a package for mobiles to use github.com/hajimehoshi/ebiten/v2/mobile:

package yourgamemobile

import (
    "github.com/hajimehoshi/ebiten/v2"
    "github.com/hajimehoshi/ebiten/v2/mobile"

    "github.com/yourname/yourgame"
)

func init() {
    // yourgame.Game must implement ebiten.Game interface.
    // For more details, see
    // * https://pkg.go.dev/github.com/hajimehoshi/ebiten/v2#Game
    mobile.SetGame(&yourgame.Game{})
}

// Dummy is a dummy exported function.
//
// gomobile doesn't compile a package that doesn't include any exported function.
// Dummy forces gomobile to compile this package.
func Dummy() {}

The key function is SetGame. Do not call RunGame, which you usually use for desktop games.

Android

Set up these environment variables:

  • ANDROID_HOME
  • ANDROID_NDK_HOME (Optional)

ANDROID_NDK_HOME is optional. If $ANDROID_HOME/ndk-bundle exists, you don't have to set this. Even if this directory doesn't exist, you can create ndk-bundle as a symbolic link like:

cd $ANDROID_HOME
ln -s ndk/<NDK version> ndk-bundle

Run ebitenmobile bind command for your package:

cd /path/to/yourgame
ebitenmobile bind -target android -javapkg your.package.name -o path/to/yourgame.aar .

Then your can get a .aar file. This .aar file defines a view class named EbitenView under the specified Java package (-javapkg option + your package name). You can put it on your screen. That's it!

The view class is defined like this:

package your.package.name.yourgamemobile;

import android.view.ViewGroup;

public class EbitenView extends ViewGroup {
    // onErrorOnGameUpdate is called on the main thread when an error happens when updating a game.
    // You can define your own error handler, e.g., using Crashlytics, by overwriting this method.
    protected void onErrorOnGameUpdate(Exception e) {
        // Default error handling implementation.
    }

    // suspendGame suspends the game.
    // It is recommended to call this when the application is being suspended e.g.,
    // Activity's onPause is called.
    public void suspendGame() {
        // ...
    }

    // resumeGame resumes the game.
    // It is recommended to call this when the application is being resumed e.g.,
    // Activity's onResume is called.
    public void resumeGame() {
        // ...
    }
}

Note that you have to call Seq.setContext at the Activity creation like this:

package your.package.name.yourgamemobile;

import androidx.appcompat.app.AppCompatActivity;
import go.Seq;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Seq.setContext(getApplicationContext());
        // ...
    }
}

iOS

Run ebitenmobile bind command for your package:

cd /path/to/yourgame
ebitenmobile bind -target ios -o path/to/yourgame.xcframework .

This command generates a .xcframework file. This .xcframework defines a view controller class named (Package Name)EbitenViewController. You can put it on your screen by connecting with any UIView. That's it!

The view controller class is defined like this:

#import <UIKit/UIKit.h>

@interface YourgamemobileEbitenViewController : UIViewController

// onErrorOnGameUpdate is called on the main thread when an error happens when updating a game.
// You can define your own error handler, e.g., using Crashlytics, by overwriting this method.
- (void)onErrorOnGameUpdate:(NSError*)err;

// suspendGame suspends the game.
// It is recommended to call this when the application is being suspended e.g.,
// UIApplicationDelegate's applicationWillResignActive is called.
- (void)suspendGame;

// resumeGame resumes the game.
// It is recommended to call this when the application is being resumed e.g.,
// UIApplicationDelegate's applicationDidBecomeActive is called.
- (void)resumeGame;

@end

Integrating Into Xcode

Part of the appeal of using Ebitengine is that you don't have to have a lot of experience in Xcode in order to build games for iOS. Once you import the ebitenmobile-generated framework and setup the View Controller within Xcode, the rest of your coding can take place in Go. When you need to test a new change, run the ebitenmobile command again and then build your project in Xcode.

In its simplest form, the Xcode project will have these files:

  • AppDelegate.h
  • AppDelegate.m
  • Assets.xcassets
  • Base.lproj
  • Info.plist
  • EbitenViewController.h
  • EbitenViewController.m
  • main.m
  • Yourgame.xcframework

When you start a new project, you are given the choice of many different types of apps to create. If you're just beginning to work with Xcode, you may want to start with a simple one like the Single View Application or Document Viewer App. And then modifying it to use the above files.

Setting Up The View Controller

While viewing main.m in Xcode, click the Attributes Inspector tab and select Is Initial View Controller. This will configure your Go code to be the first thing that is run. Many iOS apps have a separate LaunchScreen View Controller, which you can implement if desired, but the above will allow everything else to happen within your Go code.

The example below is a great reference when you start building out your own app.

Example

go-inovation is a complete example to use ebitenmobile bind.

Why ebitenmobile bind?

  • ebitenmobile bind requires less boilerplate code than gomobile bind.
  • ebitenmobile bind's views hide implementation details completely. Now Android uses OpenGL ES and iOS uses Metal, and this fact is hid by ebitenmobile. Android might migrate to Vulkan in the future. Even when migration happens, you don't have to care anything as long as you use ebitenmobile bind.

Why not a complete application instead of a shared library?

It is because it is not feasible to write a mobile application only in Go yet.

  • You'd need to access native APIs to access many features.
  • It is very common to add a native component (e.g., ad banners) to your application.
  • To launch your application on the stores, you'd need to insert certifications or other files. Android Studio or Xcode care them. It'd be really hard for the IDEs to treat a complete application generated by other tools.

Creating an application with gomobile build (For testing only)

NOTICE: Now gomobile build does not work for iOS. See the Go issue.

Ebitengine application also works with gomobile build. This is useful for testing, but not suitable for actual applications in the stores.

Install gomobile command first.

go install golang.org/x/mobile/cmd/...@latest

Then, run gomobile build

gomobile build github.com/yourname/yourpackage

That's it!

You can install an Ebitengine's example directly with gomobile install on your Android device:

gomobile install -tags=example github.com/hajimehoshi/ebiten/v2/examples/paint

For more details, see the official Wiki page about gomobile.

TL;DR

使用 ebitenmobile 命令创建共享库. The generated library includes a complete and easy-to-use view (or view controller) class.

使用 ebitenmobile bind 命令创建共享库

安装 ebitenmobile

首先,安装 ebitenmobile.

go install github.com/hajimehoshi/ebiten/v2/cmd/ebitenmobile@latest

Creating a binding

Create a package for mobiles to use github.com/hajimehoshi/ebiten/v2/mobile:

package yourgamemobile
  
  import (
      "github.com/hajimehoshi/ebiten/v2"
      "github.com/hajimehoshi/ebiten/v2/mobile"
  
      "github.com/yourname/yourgame"
  )
  
  func init() {
      // yourgame.Game must implement ebiten.Game interface.
      // For more details, see
      // * https://pkg.go.dev/github.com/hajimehoshi/ebiten/v2#Game
      mobile.SetGame(&yourgame.Game{})
  }
  
  // Dummy is a dummy exported function.
  //
  // gomobile doesn't compile a package that doesn't include any exported function.
  // Dummy forces gomobile to compile this package.
  func Dummy() {}

The key function is SetGame. Do not call RunGame, which you usually use for desktop games.

Android

Set up these environment variables:

  • ANDROID_HOME
  • ANDROID_NDK_HOME (Optional)

ANDROID_NDK_HOME is optional. If $ANDROID_HOME/ndk-bundle exists, you don't have to set this. Even if this directory doesn't exist, you can create ndk-bundle as a symbolic link like:

cd $ANDROID_HOME
  ln -s ndk/<NDK version> ndk-bundle

Run ebitenmobile bind command for your package:

cd /path/to/yourgame
  ebitenmobile bind -target android -javapkg your.package.name -o path/to/yourgame.aar .

然后,你会得到一个.aar文件. .aar文件 defines a view class named EbitenView under the specified Java package (-javapkg option + your package name). You can put it on your screen. That's it!

The view class is defined like this:

package your.package.name.yourgamemobile;
  
  import android.view.ViewGroup;
  
  public class EbitenView extends ViewGroup {
      // onErrorOnGameUpdate is called on the main thread when an error happens when updating a game.
      // You can define your own error handler, e.g., using Crashlytics, by overwriting this method.
      protected void onErrorOnGameUpdate(Exception e) {
          // Default error handling implementation.
      }
  
      // suspendGame suspends the game.
      // It is recommended to call this when the application is being suspended e.g.,
      // Activity's onPause is called.
      public void suspendGame() {
          // ...
      }
  
      // resumeGame resumes the game.
      // It is recommended to call this when the application is being resumed e.g.,
      // Activity's onResume is called.
      public void resumeGame() {
          // ...
      }
  }

Note that you have to call Seq.setContext at the Activity creation like this:

package your.package.name.yourgamemobile;
  
  import androidx.appcompat.app.AppCompatActivity;
  import go.Seq;
  
  public class MainActivity extends AppCompatActivity {
      @Override
      protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          Seq.setContext(getApplicationContext());
          // ...
      }
  }

iOS

在您的包下运行ebitenmobile bind:

cd /path/to/yourgame
  ebitenmobile bind -target ios -o path/to/yourgame.framework .

This command generates a .framework file. This .framework defines a view controller class named (Package Name)EbitenViewController. You can put it on your screen by connecting with any UIView. That's it!

The view controller class is defined like this:

#import <UIKit/UIKit.h>
  
  @interface YourgamemobileEbitenViewController : UIViewController
  
  // onErrorOnGameUpdate is called on the main thread when an error happens when updating a game.
  // You can define your own error handler, e.g., using Crashlytics, by overwriting this method.
  - (void)onErrorOnGameUpdate:(NSError*)err;
  
  // suspendGame suspends the game.
  // It is recommended to call this when the application is being suspended e.g.,
  // UIApplicationDelegate's applicationWillResignActive is called.
  - (void)suspendGame;
  
  // resumeGame resumes the game.
  // It is recommended to call this when the application is being resumed e.g.,
  // UIApplicationDelegate's applicationDidBecomeActive is called.
  - (void)resumeGame;
  
  @end

Integrating Into Xcode

Part of the appeal of using Ebiten is that you don't have to have a lot of experience in Xcode in order to build games for iOS. Once you import the ebitenmobile-generated framework and setup the View Controller within Xcode, the rest of your coding can take place in Go. When you need to test a new change, run the ebitenmobile command again and then build your project in Xcode.

In its simplest form, the Xcode project will have these files:

  • AppDelegate.h
  • AppDelegate.m
  • Assets.xcassets
  • Base.lproj
  • Info.plist
  • EbitenViewController.h
  • EbitenViewController.m
  • main.m
  • Yourgame.framework

When you start a new project, you are given the choice of many different types of apps to create. If you're just beginning to work with Xcode, you may want to start with a simple one like the Single View Application or Document Viewer App. And then modifying it to use the above files.

Setting Up The View Controller

While viewing main.m in Xcode, click the Attributes Inspector tab and select Is Initial View Controller. This will configure your Go code to be the first thing that is run. Many iOS apps have a separate LaunchScreen View Controller, which you can implement if desired, but the above will allow everything else to happen within your Go code.

The example below is a great reference when you start building out your own app.

Example

go-inovation is a complete example to use ebitenmobile bind.

Why ebitenmobile bind?

  • ebitenmobile bind requires less boilerplate code than gomobile bind.
  • ebitenmobile bind's views hide implementation details completely. Now Android uses OpenGL ES and iOS uses Metal, and this fact is hid by ebitenmobile. Android might migrate to Vulkan in the future. Even when migration happens, you don't have to care anything as long as you use ebitenmobile bind.

Why not a complete application instead of a shared library?

It is because it is not feasible to write a mobile application only in Go yet.

  • You'd need to access native APIs to access many features.
  • It is very common to add a native component (e.g., ad banners) to your application.
  • To launch your application on the stores, you'd need to insert certifications or other files. Android Studio or Xcode care them. It'd be really hard for the IDEs to treat a complete application generated by other tools.

Creating an application with gomobile build (For testing only)

NOTICE: Now gomobile build does not work for iOS. See the Go issue.

Ebiten application also works with gomobile build. This is useful for testing, but not suitable for actual applications in the stores.

Install gomobile command first.

go install golang.org/x/mobile/cmd/...@latest

Then, run gomobile build

gomobile build github.com/yourname/yourpackage

That's it!

You can install an Ebiten's example directly with gomobile install on your Android device:

gomobile install -tags=example github.com/hajimehoshi/ebiten/v2/examples/paint

更多内容,请见gomobile官方wiki.