mandala

package module
v0.0.0-...-a34aaf7 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 8, 2014 License: MIT Imports: 8 Imported by: 0

README

Mandala

GoDoc

Mandala is a framework for writing Android native applications in Go using the Goandroid toolchain. You can develop, test and run your application on your desktop and then deploy it to an Android device. It encourages the use of idiomatic Go for writing Android applications: communication happens through channels and not callbacks. The framework should not be considered a high-level game engine but as a basic layer onto which game engines can be built or existing ones can be used. In my opinion, this opens interesting scenarios in the developing of native Android applications/games in Go. Goandroid's native_activity example was the initial source of inspiration for this project.

Please consider that Mandala is in a very early stage of development: API will change, test coverage is not so good for now. Last but not least, Go doesn't officially support native Android development. Regarding this point, I hope that the present work could act as a sort of incentive in the direction of an official Android support by the Go Team.

Have a nice Mandala!

Key features

  • Code/test/run on your desktop and deploy on the device.
  • Build/deploy/run your application using simple shell commands.
  • On-device black-box testing.
  • Communicate through channels, no callbacks.
  • Quick bootstrap using a predefined template.

Supported desktop platforms

  • Linux (xorg)
  • OSX (see the wiki page)

Techonologies involved

How does it work?

Mandala uses the Goandroid toolchain to compile Go applications for Android. The graphics abstraction between desktop and device is obtained using a bunch of technologies. In particular

  • EGL
  • OpenGL ES 2.0
  • GLFW 3

The EGL layer is necessary to use an OpenGL ES 2 context on a desktop environment. The GLFW library is responsible of managing the rendering context and the handling of events in a window.

The framework itself provides an event channel from which client code listen for events happening during program execution. Examples of events are the interaction with the screen, the creation of the native rendering context, pausing/resuming/destroying of the application, etc.

The framework abstracts the Android native events providing a way to build, run and test the application on the desktop with the promise that it will behave the same on the device once deployed. Oh well, this is the long-term aim, at least!

A typical Mandala application has two loops: one continuously listens for events, the other is responsible for rendering the scene. In order to dealing with application resources (images, sounds, configuration files, etc.), the framework provides a ResourceManager object. Client code sends requests to it in order to obtain resources as slices of bytes. In the desktop application this simply means opening the file at the given path. In the Android application the framework will unpack the apk archive on the fly getting the requested resources from it. However, it is the framework's responsibility to deal with the right native method for opening a file. From the client-code point of view the request will be the same.

The bothersome steps needed to build, package and deploy the application on the device are simplified using a set of predefined gotask tasks.

Examples

Please visit mandala-examples.

Prerequisites

  • Android NDK
  • Goandroid
  • EGL
  • OpenGL ES 2
  • GLFW3
  • gotask (to run the tests)
  • xdotool (to run the tests on xorg)

Android NDK

See here.

Goandroid

See here.

After installing Goandroid you have to export a new environment variable GOANDROID. It should point to the Go bin folder of the Goandroid distribution. For example,

export GOANDROID=$HOME/src/goandroid/go/bin

Also note that on a 32 bit host machine, it would be necessary to generate the toolchain with:

$NDK/build/tools/make-standalone-toolchain.sh --platform=android-9 --toolchain=arm-linux-androideabi-4.8 --install-dir=ndk-toolchain

See here for further info about the issue.

EGL/OpenGL ES 2

On a debian-like system:

sudo apt-get install libgles2-mesa-dev libegl1-mesa-dev

Then you should install the Go bindings for EGL and OpenGL ES 2. This is as simple as:

go get github.com/remogatto/egl
go get github.com/remogatto/opengles2

GLFW3

Install from source following the instructions here. Please note that you have to configure GLFW in order to use EGL and OpenGL ES 2. For further information, see here and here. Be sure to build GLFW as a shared object!

After installing GLFW3, in order to install the Go binding, see here.

gotask

go get github.com/jingweno/gotask

xdotool

On a debian-like system:

sudo apt-get install xdotool

This is needed for black-box testing only.

Install

Once you have satisfied all the prerequisites:

go get github.com/remogatto/mandala

This will install all the remaining dependencies.

Quick start

To create a basic application install mandala-template:

go get github.com/remogatto/mandala-template

Then, in a folder inside $GOPATH/src run the following commands:

mandala-template myapp
cd myapp
gotask init
gotask run android # deploy and run on a connected device
gotask run xorg    # run on a desktop window

This will generate a simple Android application showing a red screen. See mandala-template for furher info.

Testing

Setup a testing environment on Android was not straightforward. The main issue is related to the flag package. To avoid dependency from it I had to hack PrettyTest in order to remove the dependency from testing (which in turn depends on flag). So basically, testing a native Android application is now possible using PrettyTest but we have to renounce the benefits of testing (at least for now). See test for further info about testing. To run the tests on your desktop window you need the xdotool (see the Prerequisites section)

To do

  • Write a complete game using the framework
  • Sound support
  • More tests

Credits

  • @jingweno for his cool build tool gotask

  • @eliasnaur for his Goandroid, the necessary condition for this work

  • @aded for patiently testing the pre-announcement release on his 32bit broken machine.

License

See LICENSE.

Documentation

Overview

Mandala is a framework for writing Android native applications in Go using the Goandroid[1] toolchain. You can develop, test and run your application on your desktop and then deploy it to an Android device. It encourages the use of idiomatic Go for writing Android applications: communication happens through channels, no callbacks. The framework is not to be considered as an high-level game engine but as a basic layer onto which game engines can be build or existing ones can be used. In my opinion, this opens interesting scenarios in the developing of native Android applications/games in Go. Goandroid's native_activity[2] example was the initial source of inspiration for this project.

Please consider that Mandala is in a very early stage of development: API will change, test coverage is not so good for now. Last but not least, Go doesn't officially supports native Android development. Regarding this point, I hope that the present work could act as a sort of incentive in the direction of an official Android support by the Go Team.

Have a nice Mandala!

[1] - https://github.com/eliasnaur/goandroid

[2] - https://github.com/eliasnaur/goandroid/tree/master/native-activity

Index

Constants

View Source
const (
	// The number of event messages buffered by the event
	// channel. This is an heuristic value.
	NumOfBufferedEvents = 10
)

Variables

View Source
var (
	// If Verbose is true Logf will print on the stdout.
	Verbose bool

	// If Debug is true Debugf will print on the stdout.
	Debug bool
)
View Source
var (
	// The path in which the framework will search for resources.
	ResourcePath string = "android/res"
)

Functions

func Debugf

func Debugf(format string, v ...interface{})

If Debug is true then Debugf will print on stdout.

func Events

func Events() <-chan interface{}

Events() returns a receive-only channel from which client-code receive events. Events are sent in the form of anonymous interfaces. Please refer to events.go for a complete list of the supported events. For a worthwhile reading take a look a this document by NVIDIA:

http://developer.download.nvidia.com/assets/mobile/files/AndroidLifecycleAppNote_v100.pdf

func Fatalf

func Fatalf(format string, v ...interface{})

Fatalf simply calls log.Fatalf

func Init

func Init(window *glfw.Window)

Init initializes a glfw.Window to be used in a xorg Mandala application. It has to be called after the GLFW initialization boilerplate. See https://github.com/remogatto/mandala-examples/triangle/src/triangle/main.go for an example.

func Logf

func Logf(format string, v ...interface{})

If Verbose is true then Logf will print on stdout.

func ReadResource

func ReadResource(filename string, responseCh chan LoadResourceResponse)

ReadResource reads a resource named filename and send the response to the given responseCh channel.

func ResourceManager

func ResourceManager() chan<- interface{}

ResourceManager() returns a send-only channel to which client-code send request for resources. Please refer to resourcemanager.go for a complete list of supported requests.

func Stacktrace

func Stacktrace() string

Stacktrace returns the stacktrace of the goroutine that calls it.

Types

type ActionMoveEvent

type ActionMoveEvent struct {
	Activity unsafe.Pointer

	// Coordinates of the touched point in movement
	X, Y float32
}

ActionMoveEvent is triggered when the user moves the finger on the device surface.

type ActionUpDownEvent

type ActionUpDownEvent struct {
	Activity unsafe.Pointer

	// The finger is down on the surface
	Down bool

	// Coordinates of the touched point
	X, Y float32
}

ActionUpDownEvent is triggered when the user has the finger down/up the device's surface.

type AudioPlayer

type AudioPlayer struct {
	// contains filtered or unexported fields
}

func NewAudioPlayer

func NewAudioPlayer() (*AudioPlayer, error)

CreateAudioPlayer instantiates a player for the given filename.

func (*AudioPlayer) Destroy

func (ap *AudioPlayer) Destroy()

func (*AudioPlayer) GetMaxVolumeLevel

func (ap *AudioPlayer) GetMaxVolumeLevel() (int, error)

GetVolumeScale returns the [min,max] values for volume. If the device doesn't support volume controls, it returns an error.

func (*AudioPlayer) Play

func (ap *AudioPlayer) Play(buffer []byte, doneCh chan bool)

Play tells the player to play the named track and send a value to doneCh when done. The channel can be nil, in that case nothing is sent to it.

func (*AudioPlayer) SetVolumeLevel

func (ap *AudioPlayer) SetVolumeLevel(value int) error

SetVolume sets the volume for the player.

type ConfigurationChangedEvent

type ConfigurationChangedEvent struct {
	Activity unsafe.Pointer
}

A ConfigurationChangedEvent is triggered when the application changes its configuration.

type CreateEvent

type CreateEvent struct {
	Activity       unsafe.Pointer
	SavedState     unsafe.Pointer
	SavedStateSize int
}

CreateEvent is the first event triggered by the application.

type DestroyEvent

type DestroyEvent struct {
	Activity unsafe.Pointer
}

DestroyEvent is the last event triggered by the application before terminate.

type LoadResourceRequest

type LoadResourceRequest struct {
	// The path of the resource file, for example
	// "res/drawable/gopher.png". ResourcePath will be prefixed to
	// Filename.
	Filename string

	// Response is a channel for receiving the response from the
	// resource manager.
	Response chan LoadResourceResponse
}

The type of request to send to ResourceManager in order to read the resource.

type LoadResourceResponse

type LoadResourceResponse struct {
	// The buffer containing the resource.
	Buffer []byte

	// The error eventually generated by the reading operation.
	Error error
}

type NativeWindowCreatedEvent

type NativeWindowCreatedEvent struct {
	Activity unsafe.Pointer
	Window   Window
}

A NativeWindowCreatedEvent is triggered when the native window is created. It indicates that the native surface is ready for rendering.

type NativeWindowDestroyedEvent

type NativeWindowDestroyedEvent struct {
	Activity unsafe.Pointer
	Window   Window
}

A NativeWindowDestroyedEvent is triggered when the native window is destroyed and nothing can be rendered on it anymore.

type NativeWindowRedrawNeededEvent

type NativeWindowRedrawNeededEvent struct {
	Activity unsafe.Pointer
	Window   Window
}

A NativeWindowRedrawNeededEvent is triggered when the native window needs to be redrawn.

type NativeWindowResizedEvent

type NativeWindowResizedEvent struct {
	Activity unsafe.Pointer
	Window   Window
}

A NativeWindowResizedEvent is triggered when the native window is resized. It happens, for example, when the device is rotated.

type PauseEvent

type PauseEvent struct {
	Activity unsafe.Pointer
	Paused   chan bool
}

A PauseEvent is triggered when the application is paused. It happens, for example, when the back button is pressed and the application goes in background. Please note that the framework will wait for a value from Paused channel before actually pause the application.

type ResumeEvent

type ResumeEvent struct {
	Activity unsafe.Pointer
}

A ResumeEvent is triggered when the application goes foreground. This doesn't mean that a native surface is ready for rendering.

type StartEvent

type StartEvent struct {
	Activity unsafe.Pointer
}

A StartEvent is triggered after a CreateEvent. It initiates the "visible" lifespan of the application.

type Window

type Window interface {

	// Swap display <-> surface buffers.
	SwapBuffers()

	// Bind context to the current rendering thread.
	MakeContextCurrent()

	// Get the size of the window as width,height values.
	GetSize() (int, int)
}

Window is an interface that abstracts native EGL surfaces.

type WindowFocusChangedEvent

type WindowFocusChangedEvent struct {
	Activity unsafe.Pointer
	HasFocus bool
}

A WindowFocusChangedEvent is triggered when the native window gain or lost its focus.

Directories

Path Synopsis
test

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL