Skip to content
Hajime Hoshi edited this page Sep 23, 2022 · 23 revisions

This document is deprecated. See

Ebiten game can be built for Android and iOS by using both gomobile bind and gomobile build. gomobile bind generates a shared library file (.aar for Android or .framework for iOS), while gomobile build generates a complete application (.apk for Android or .app for iOS).

Although Ebiten accepts both, it is recommended to use gomobile bind for actual use. gomobile build is difficult to build an actual application in Play store or Apple store. gomobile build is very easy to use to generate an application written only in Go, but the application includes only one OpenGL surface. Even if you want to an advertisement or use inputting via a software keyboard, it is almost impossible. On the other hand, gomobile bind generates a shared library and you'd need some glue Java/Objective-C code to use this, but that offers flexibility where you can do everything.

Actual example

Inovation 2007 is an actual Android/iOS game using Ebiten. This application has been released in Play Store and Apple Store.

Context lost

OpenGL context lost usually happens, e.g. when you switch applications. When this happens, all data in GPU are invalidated.

Ebiten automatically records all drawing command history and pixel data, and they are used when recovering from context lost.

How to build an application (gomobile build)

Simply run gomobile build.

gomobile build

If you want to run Ebiten examples that require example build tags, run

gomobile build -tags=example

gomobile install builds and installs a package to your Android device. If you want to build and install go-inovation on Android at the same time, run

gomobile install

And you can find go-inovation runs on your Android device.

For iOS, installing is a little complicated. See the official Wiki page.

How to build an application (gomobile bind)

Create a package for mobiles

You need to create a package for mobiles with Package for your game. This package has exported functions to Java/Objetive-C side.

For an actual example, see

package mobile

import (

var (
        running bool

const (
        ScreenWidth  = 320
        ScreenHeight = 240

// IsRunning returns a boolean value indicating whether the game is running.
func IsRunning() bool {
        return running

// Start starts the game.
func Start(scale float64) error {
        running = true
        game, err := yourgame.NewGame()
        if err != nil {
                return err
        // mobile.Start starts the game.
        // In this function, scale is passed from Java/Objecitve-C side
        // and pass it to mobile.Start. You can also receive the screen
        // size from Java/Objetive-C side by adding arguments to this
        // function if you want to make Java/Objective-C side decide the
        // screen size.
        // Note that the screen size unit is dp (device-independent pixel)
        // on Android.
        if err := mobile.Start(game.Update, ScreenWidth, ScreenHeight, scale, "Your Game's Title"); err != nil {
                return err
        return nil

// Update proceeds the game.
func Update() error {
        return mobile.Update()

// UpdateTouchesOnAndroid dispatches touch events on Android.
func UpdateTouchesOnAndroid(action int, id int, x, y int) {
        mobile.UpdateTouchesOnAndroid(action, id, x, y)

// UpdateTouchesOnIOS dispatches touch events on iOS.
func UpdateTouchesOnIOS(phase int, ptr int64, x, y int) {
        // Prepare this function if you also want to make your game run on iOS.
        mobile.UpdateTouchesOnIOS(phase, ptr, x, y)