Jump to content
Search

This wiki is under development. Features may be missing. Data loss is unlikely, but possible. Read the announcement.

Ebitengine

From Ubuntu Wiki

Testing

This page has been identified as needing testing.
Note
This page was adapted from a blog that focused on cross-platform game development with WSL.

You can use Ubuntu to develop, build, and test a game for Windows, Linux, and the browser.

In this example, we'll use Ubuntu and the Ebitengine game engine for Go.

Set up the project

Install Go with snap:

sudo snap install go --classic

Make a Go project:

mkdir game && cd game
go mod init game

Write the code

Use a text editor to edit the game code:

vim main.go
# nano main.go

Paste this simple example, which bounces a ball around the window and changes the ball color based on the build target:

package main

import (
	"fmt"
	"image/color"
	"log"
	"runtime"

	"github.com/hajimehoshi/ebiten/v2"
	"github.com/hajimehoshi/ebiten/v2/ebitenutil"
	"github.com/hajimehoshi/ebiten/v2/vector"
)

const (
	screenW    = 480
	screenH    = 360
	ballRadius = 12
	textPadX   = 8
	textPadY   = 8
)

var label = fmt.Sprintf("This is a %s build", runtime.GOOS)

func ballColor() color.Color {
	switch runtime.GOOS {
	case "linux":
		return color.RGBA{R: 255, G: 0, B: 0, A: 255}
	case "windows":
		return color.RGBA{R: 0, G: 0, B: 255, A: 255}
	case "js":
		return color.RGBA{R: 0, G: 255, B: 0, A: 255}
	default:
		return color.White
	}
}

type Game struct {
	x, y   float64
	vx, vy float64
}

func (g *Game) Update() error {

	g.x += g.vx
	g.y += g.vy

	if g.x-ballRadius <= 0 || g.x+ballRadius >= screenW {
		g.vx = -g.vx
	} else if g.y-ballRadius <= 0 || g.y+ballRadius >= screenH {
		g.vy = -g.vy
	}

	return nil
}

func (g *Game) Draw(screen *ebiten.Image) {
	screen.Fill(color.Black)
	ebitenutil.DebugPrintAt(screen, label, textPadX, textPadY)
	vector.DrawFilledCircle(screen, float32(g.x), float32(g.y), ballRadius, ballColor(), true)
}

func (g *Game) Layout(_, _ int) (int, int) {
	return screenW, screenH
}

func main() {
	ebiten.SetWindowSize(screenW, screenH)
	ebiten.SetWindowTitle("Crossplatform builds on Ubuntu")
	log.Fatal(ebiten.RunGame(&Game{x: 40, y: 40, vx: 4, vy: 2.5}))
}

Resolve the Go dependencies:

go mod tidy

Build cross-platform

Windows build

Build for Windows:

GOOS=windows GOARCH=amd64 go build .

Linux build

To build for Linux, first install the dependencies required to compile the game for X11:

sudo apt update

sudo apt install \
        libx11-dev \
        libxrandr-dev \
        libxcursor-dev \
        libxinerama-dev \
        libxi-dev \
        libxxf86vm-dev \
        libgl1-mesa-dev \
        xorg-dev

Then build for Linux:

GOOS=linux GOARCH=amd64 go build .

Web build

To build for WebAssembly, run:

GOOS=js GOARCH=wasm go build -o game.wasm .

Next, copy wasm_exec.js to the current directory so that the WebAssembly binary can be executed:

# note: exact location depends on your Go version
cp $(go env GOROOT)/misc/wasm/wasm_exec.js .

Finally, create two HTML files: one that includes the game (game.html) and another that embeds the game in an iframe (index.html).

Game:

<!DOCTYPE html>
<script src="wasm_exec.js"></script>
<script>
  const go = new Go();
  WebAssembly.instantiateStreaming(fetch("game.wasm"), go.importObject).then(r => go.run(r.instance));
</script>

Embedder:

<!DOCTYPE html>
<style>
  body { margin: 0; background: #555; display: flex; justify-content: center; align-items: center; height: 100vh; overflow: hidden; }
</style>
<iframe src="game.html" width="480" height="360" frameborder="0"></iframe>

Run the builds

You now have three builds of your game for different platforms.

Run on Linux

Run the Linux build:

./game

Run on web

To run the game in a browser, create a simple Python server to serve files from localhost:

python3 -m http.server -b localhost

Then open http://127.0.0.1:8000/ in your browser.

Run on Windows

The steps to run on Windows depend on whether you are using Ubuntu Desktop or Ubuntu on WSL:

Install the Wine compatibility layer:

sudo apt install wine

Then run the game with:

wine game.exe

With WSL, you can simply run the Windows executable directly from an Ubuntu session:

 ./game.exe

Result

The ball is a different color depending on the platform:

  • Red: Linux
  • Blue: Windows
  • Green: Web