Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

github.com/thommil/tge

Package Overview
Dependencies
Alerts
File Explorer
Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

github.com/thommil/tge

  • v0.0.0-20230913094024-4f2bb112cebe
  • Source
  • Go
  • Socket score

Version published
Created
Source

TGE - Portable Runtime in GO

Godoc Go Report Card

TGE aims to provide a light, portable and unopiniated runtime to integrate your favorite Go libraries (at least mines) to portable applications (dektop, web & mobile) and package them in a proper way (not a mere executable).

TGE is not and should not be another new game engine but instead a way to focus on business code and not low level pipes and hacks. The core is intended to be as light as possible and depends on plugins to enable cool features (OpenGL, AL, Vulkan, GUI...)

TGE runtime benefits from power ful channels paradigm of Go to propose rendering across 2 synchronized loops Ticker and Render:

See it in action in tge-examples and look below for more details.

An online demo (Work in Progress) is also available here : http://tge-demo.thommil.com

TGE Core

Core implements a minimal runtime for several platforms:

  • Windows, MacOS & Linux
  • Android 5+ & IOS 8+
  • Web on Chrome, Firefox & Safari

TGE plugins

Plugins allow to create your game/application by choosing implementation for different parts (GUI, rendering, sound...). This way, you choose how to create your game/application. I'm trying to port as many features as I can in plugins, natively portable libraries are off course directly usable too (physics, AI...).

Plugin link   Details
tge-gestureGestures for touch screens with support for Android, IOS and mobile browsers. Implements longpress, swipe and pinch gestures.
tge-glOpenGL/ES 3+ API based on go-gl work. Expose OpenGL to App in a portable way, il you want a low level access to the graphical context. Needed by most graphical libraries and plugins.
tge-g3nBased on the awesome G3N game engine written in Go. This great piece of software engineering is brought to Mobile and Web by TGE.
tge-audioAudio support based on Web Audio API. Brings full support for sound effects and spacialization with a comprehensive API ;)

Getting started

Based on what is done with tools like Vue.js, Node or Spring, TGE offers a command line tool tge-cli to ease creation and build of TGE applications.

Install tge-cli

To get the client, run:

go get github.com/thommil/tge-cli

The command line tool should be available in the $GOPATH/bin folder.

Create new application

The create a new application workspace, run:

tge-cli init [package-name]

An application folder will be created with all needed resources to begin. See tge-cli and Go Doc for details and API.

Build the application

Once the application folder is created, releases can be generated using:

tge-cli build -target [target] [package-path]

Target allows to build your application for Desktop, Mobile or Web backend. See tge-cli for full details on how to use it and customize each target.

Coding

Applications

App is the main entry point of a TGE application. The code below is generated by tge-cli when creating a new project:

package main

import (
	"time"

	// Runtime package
	tge "github.com/thommil/tge"
	//Available plugins - Just uncomment to enable
	//gesture "github.com/thommil/tge-gesture"
	//gl "github.com/thommil/tge-gl"
	//g3n "github.com/thommil/tge-g3n"
)

// App instance context and definition
type App struct {
	// Put global attributes of your application here
}

// OnCreate is called at App instanciation, the Runtime resources are not
// yet available. Settings and treatments not related to Runtime should be done here.
func (app *App) OnCreate(settings *tge.Settings) error {
	// Settings is passed as a pointer can be modified to adapt App to your needs
	// Ex :
	//	settings.Name = "My Awesome App++"
	//	settings.Fullscreen = true
	//	settings.EventMask = tge.AllEventsEnable
	// 	...
	return nil
}

// OnStart is called when all Runtime resources are available but looping as not been
// started. Initializations should be done here (GL conf, physics engine ...).
func (app *App) OnStart(runtime tge.Runtime) error {
	// Here is the place where your initialize everything, the runtime is UP but the loops
	// are not started :
	// 	- OpenGL
	//	- Physics
	//	- AI
	//	- Load previous Save
	//	- State Machine setup
	// 	...
	return nil
}

// OnResume is called just after OnStart and also when the Runtime is awaken after a pause.
func (app *App) OnResume() {
	// This method is called to notify that loops are started, don't place heavey treatments here
	// Most of the time, this method is just used to hide/remove a pause screen
}

// OnRender is called each time the graphical context is redrawn. This method should only implements
// graphical calls and not logical ones. The syncChan is used to wait for Tick() loop draw commands
func (app *App) OnRender(elaspedTime time.Duration, syncChan <-chan interface{}) {
	// Always listen at least for one object from syncChan to synchronize it with Tick(), in other case the Tick() loop
	// will be blocked
	<-syncChan

	// This loop is dedicated to graphical/GPU treatments:
	//	- OpenGl Calls
	//	- Vulkan Calls (one day ;)
	//
	// Data becomes available from syncChan pipe and sent by the Tick loop, as mentioned below, it's possible to
	// reused syncChan several times in a single Render/Tick call for progressive rendering.
	//
	// As syncChan is a generic interface channel, it's also possible to select treatment to apply:
	//	data := <-syncChan
	//	switch data.(type) {
	//		...
	//	}
}

// OnTick handles logical operations like physics, AI or any background task not relatd to graphics.
// The syncChan is used to notify Render() loop with draw commands.
func (app *App) OnTick(elaspedTime time.Duration, syncChan chan<- interface{}) {
	// This loop is dedicated to logical/CPU treatments:
	//	- physics
	//	- AI
	//	- State Machine
	//	- File access ...
	//
	// Each time Tick loop needs to send data to Render loop, use the syncChan.
	//
	// In can be done once per call or several times if you want a progressive rendering
	//
	// As data can be shared between Tick and Render loops, a good practice is too handle heavy treatments
	// in Tick dedicated data, then copy data to Render dedicated data and send it through the syncChan.
	//
	// A good candidate for copy if the reflect.Copy() function:
	//   reflect.Copy(reflect.ValueOf(renderData), reflect.ValueOf(tickData))
	//
	// If your data is based on something else than slices but its size justifies low level memory copy, you can
	// also put ticker data in single element slice and use reflect.Copy().
	//
	// Tick loop is running in a dedicated Go routine, it's also possible to start subroutines in this loop to
	// benefit from availble cores and increase treatment speed using map/reduce oriented algorithms.
	//
	// Always send at least one object to syncChan to synchronize it with Render(), in other case the Tick() loop
	// will be a simple infinite loop and your App will destroy your Desktop/Mobile/Browser
	syncChan <- true
}

// OnPause is called when the Runtime lose focus (alt-tab, home button, tab change ...) This is a good entry point to
// set and display a pause screen
func (app *App) OnPause() {
	// Most of the time, just set a flag indicating the paused state of your App
}

// OnStop is called when the Runtime is ending, context saving should be done here. On current Android version this
// handler is also called when the application is paused (and restart after).
func (app *App) OnStop() {
	// This is where you backup everyting if needed (state machine, save ...) The runtime tries to call and execute
	// this method before leaving to allow proper exit but nothing is guaranteed on some targets (WEB)
}

// OnDispose is called when all exit treatments are done for cleaning task (memory, tmp files ...)
func (app *App) OnDispose() {
	// Optional but always good practice to clean up everything before leaving :)
}

// Main entry point, simply instanciates App and runs it through Runtime
func main() {
	// The line below should be the only one, code here is not portable!
	tge.Run(&App{})
}

Plugins

To create new TGE plugins for sharing or to defines dedicated libraries across your applications, use the code below:

package myplugin

import (
	// Always import TGE for initalization purpose
	tge "github.com/thommil/tge"
)

// Plugin implementation, no need to expose
type plugin struct {
}

// Go init function, register your plugin on TGE runtime HERE
func init() {
	tge.Register(plugin{})
}

// Init code of your plugin, called before runtime loops 
func (p *plugin) Init(runtime tge.Runtime) error {
	return nil
}

// GetName is used to identify the plugin in TGE registry
func (p *plugin) GetName() string {
	return "myplugin"
}

// Dispose allows to clean up plugin resources
func (p *plugin) Dispose() {
}

Targeting platform and debug mode

It's possible to write code for a specific platform the same way TGE does.

For desktop, add the following Go build directives:

 // +build darwin freebsd linux windows
 // +build !android
 // +build !ios
 // +build !js

for mobile (targeting only android or ios is also possible):

 // +build android ios

and for browser:

 // +build js

At last, it's also possible to create a dedicated file for debugging purpose by adding:

 // +build debug

The file will be used if the -dev flag is set in tge-cli command line for build.

FAQs

Package last updated on 13 Sep 2023

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc