Engo is an open-source 2D game engine written in Go.

Engo

GoDoc Join the chat at https://gitter.im/EngoEngine/engo License Build Status Build status Go Report Card Coverage Status

A cross-platform game engine written in Go following an interpretation of the Entity Component System paradigm. Engo is currently compilable for Mac OSX, Linux and Windows. With the release of Go 1.4, supporting Android and the inception of iOS compatibility, mobile has been be added as a release target. Web support (wasm) is also available.

v1.0 is now available! To celebrate, there will be a game jam coming soon to celebrate the release, start actually building things and hopefully find any issues. Updates for this will come soon.

Getting in touch / Contributing

We have a gitter chat for people to join who want to further discuss engo. We are happy to discuss bugs, feature requests and would love to hear about the projects you are building!

Getting Started

Theory: common vs engo

There are currently two major important packages within this repository: github.com/EngoEngine/engo and github.com/EngoEngine/engo/common.

The top level engo package contains the functionality of creating windows, starting the game, creating an OpenGL context and handling input. It is designed to be used with Systems designed as per github.com/EngoEngine/ecs specifications. The common package contains our ECS implementations of common game development Systems like a RenderSystem or CameraSystem.

Practice: Getting it to Run

  1. First, you have to install some dependencies:
  2. If you're running on Debian/Ubuntu: sudo apt-get install libasound2-dev libglu1-mesa-dev freeglut3-dev mesa-common-dev xorg-dev libgl1-mesa-dev git-all
  3. If you're running on Windows you'll need a gcc compiler that the go tool can use and have gcc.exe in your PATH environmental variable. We recommend Mingw since it has been tested. You'll also need git installed, we recommend getting it from The official Git site
  4. If you're on OSX, you will also need Git. You can find instructions here. You can also use homebrew to install git as well. Open an issue if you have any issues
  5. Then, you can go get it: go get -u github.com/EngoEngine/engo
  6. You may also want to get the dependencies of platform specific builds, so that build tools like godef can use them: go get -u -tags js ./... go get -u -tags android ./...
  7. Now, you have two choices:
  8. Visit our website, which hosts a full-blown tutorial series on how to create your own game, and on top of that, has some conceptual explanations;
  9. Check out some demos in our demos folder.
  10. Finally, if you run into problems, if you've encountered a bug, or want to request a feature, feel free to shoot us a DM or create an issue.

Breaking Changes Since v1.0

Engo is always undergoing a lot of optimizations and constantly gets new features. However, this sometimes means things break. In order to make transitioning easier for you, we have a list of those changes, with the most recent being at the top. If you run into any problems, please contact us at gitter.

  • TMXObject Width and Height is in pixels, and can be fractional. This has changed from an int to a float64.
  • TMXTileset now uses a Spritesheet instead of a Texture. This helps keep track of the guid better and allows the gid to not start at zero and have skips in it, as well as for borders and spacing in the tile sheet.
  • TMX Level's objects have all been rolled into Object rather than have separate things like "PolyLineObject". This is to be consistent with the TMX format.
  • The Shader interface now has a SetCamera(*CameraSystem) method. This method allows shaders to automatically update the camera system as it changes, such as between scenes or when the camera system is added.
  • The domain engo.io has expired. Now use github.com/EngoEngine/engo as the import path, and the site can be located at engoengine.github.io

Roadmap to v1.1

A list of issues for v1.1 can be found here. There's always room for improvement! Feel free to submit proposals, open issues, and let us know how we can improve!

History

Engo, originally known as Engi was written by ajhager as a general purpose Go game engine. With a desire to build it into an "ECS" game engine, it was forked to github.com/paked/engi. After passing through several iterations, it was decided that the project would be rebranded and rereleased as Engo on its own GitHub organization.

Credits

Thank you to everyone who has worked on, or with Engo. None of this would be possible without you, and your help has been truly amazing.

These are 3rd party projects that have made engo possible.

  • The original engi game engine which engo was based off of (BSD license)
  • Oto, a low-level cross-platform library to play sound. The AudioSystem uses this and is based on the audio package used in Ebiten.
Owner
Engo
An open-source 2D game engine written in Go. It uses the Entity-Component-System paradigm.
Engo
Comments
  • Generic asset loader

    Generic asset loader

    It would be nice if users had the possibility to add their own filetype / extension / loader method to our asset loader.

    To be complete, we would then use that method ourselves.

    Thinking of a generic interface, let's brainstorm.

    type FileLoader interface {
        // Extensions returns the file extensions for which this FileLoader should be used, excluding the '.' in front of it
        Extensions() []string
    
        // Load is called with the url (location) of the file, and is called whenever the file must be loaded
        Load(url string) error
    
        // Unload is called with the url (location) of the file, and is called whenever the resources of the file should be freed from the memory
        Unload(url string) error
    }
    

    There'd also have to be a generic method of retrieving the actual resource? Or not? Kinda like our engo.Files.Image("url") returns an actual (loaded) image.

    Thoughts? Improvements? Changes? Always welcome.

  • Multithreading

    Multithreading

    As Go is such a nice language to do multithreading in, and most games lack multithreading, it'd be nice if we supported it.

    Currently, each frame, we are iterating over all Systems, and iterating over all Entitys "in" those Systems.

    I'm not sure if we can safely multithread multiple Systems at once, but we could easily multithread the iteration over Entitys?

    Current implementation

        for _, system := range w.Systems() {
            if headless && system.SkipOnHeadless() {
                continue // so skip it
            }
    
            system.Pre()
            for _, entity := range system.Entities() {
                if w.paused {
                    ok := entity.GetComponent(&unp)
                    if !ok {
                        continue // so skip it
                    }
                }
                if entity.Exists {
                    system.Update(entity, dt)
                }
            }
            system.Post()
        }
    

    Proposed implementation

        for _, system := range w.Systems() {
            if headless && system.SkipOnHeadless() {
                continue // so skip it
            }
    
            entities := system.Entities()
    
            system.Pre()
    
            // It's not always faster to multithread; so in this case we're not going to
            if len(entities) < 2*runtime.NumCPU() {
                for _, ent := range entities {
                    system.Update(ent, dt)
                }
                system.Post()
                continue // with other Systems
            }
    
            entityChannel := make(chan *Entity)
            wg := sync.WaitGroup{}
    
            // Launch workers
            for i := 0; i < runtime.NumCPU(); i++ {
                go func() {
                    for ent := range entityChannel {
                        system.Update(ent, dt)
                        wg.Done()
                    }
                }()
            }
    
            // Give them something to do
            for _, entity := range entities {
                if w.paused {
                    ok := entity.GetComponent(&unp)
                    if !ok {
                        continue // so skip it
                    }
                }
                if entity.Exists {
                    wg.Add(1)
                    entityChannel <- entity
                }
            }
    
            // Wait until they're done, before continuing to other Systems
            wg.Wait()
            close(entityChannel)
    
            system.Post()
        }
    

    I know it's a bit more code than the original implementation, but it sure is efficient.

  • Rotation support

    Rotation support

    Hi there,

    this is a PR (based on other ones) that adds rotation support for Engi.

    The rotation is implemented in the default shader. I'd like the changes I introduced in the shader interface.It may be possible to avoid this by passing the space width and height in the gl buffer.

  • HUD example compiles but crashes

    HUD example compiles but crashes

    This crashes as soon as I launch the example with the following traceback:

    fatal error: unexpected signal during runtime execution
    [signal 0xb code=0x1 addr=0x0 pc=0x7f90bf226ff0]
    
    runtime stack:
    runtime.throw(0x7bac40, 0x2a)
        /home/faide/tools/go/src/runtime/panic.go:527 +0x90
    runtime.sigpanic()
        /home/faide/tools/go/src/runtime/sigpanic_unix.go:12 +0x5a
    
    goroutine 1 [syscall, locked to thread]:
    runtime.cgocall(0x60d8e0, 0xc8200c7ad0, 0x0)
        /home/faide/tools/go/src/runtime/cgocall.go:120 +0x11b fp=0xc8200c7a88 sp=0xc8200c7a58
    github.com/go-gl/gl/v2.1/gl._Cfunc_glowDrawElements(0x7f90bef73760, 0x600000004, 0x1403, 0x0)
        github.com/go-gl/gl/v2.1/gl/_obj/_cgo_gotypes.go:12227 +0x35 fp=0xc8200c7ad0 sp=0xc8200c7a88
    github.com/go-gl/gl/v2.1/gl.DrawElements(0x600000004, 0xc800001403, 0x0)
        /home/faide/go/src/github.com/go-gl/gl/v2.1/gl/package.go:19385 +0x45 fp=0xc8200c7af8 sp=0xc8200c7ad0
    github.com/paked/webgl.(*Context).DrawElements(0xc8200f6000, 0x4, 0x6, 0x1403, 0x0)
        /home/faide/go/src/github.com/paked/webgl/webgl_gl2.go:775 +0x42 fp=0xc8200c7b18 sp=0xc8200c7af8
    github.com/paked/engi.(*HUDShader).flush(0xc8200be000)
        /home/faide/go/src/github.com/paked/engi/shaders.go:289 +0x168 fp=0xc8200c7b58 sp=0xc8200c7b18
    github.com/paked/engi.(*HUDShader).Post(0xc8200be000)
        /home/faide/go/src/github.com/paked/engi/shaders.go:294 +0x21 fp=0xc8200c7b68 sp=0xc8200c7b58
    github.com/paked/engi.(*RenderSystem).Post(0xc82000e420)
        /home/faide/go/src/github.com/paked/engi/render.go:291 +0xce fp=0xc8200c7ca0 sp=0xc8200c7b68
    github.com/paked/engi/ecs.(*World).Update(0xc820014720, 0x0)
        /home/faide/go/src/github.com/paked/engi/ecs/world.go:121 +0x2d5 fp=0xc8200c7d90 sp=0xc8200c7ca0
    github.com/paked/engi.RunIteration()
        /home/faide/go/src/github.com/paked/engi/engi_glfw.go:194 +0x53 fp=0xc8200c7da8 sp=0xc8200c7d90
    github.com/paked/engi.runLoop(0x7f90bc69f360, 0xc6fb60, 0x400)
        /home/faide/go/src/github.com/paked/engi/engi_glfw.go:226 +0xd9 fp=0xc8200c7e70 sp=0xc8200c7da8
    github.com/paked/engi.Open(0x0, 0x71d4b0, 0x8, 0x0, 0x400, 0x280, 0x0, 0x0, 0x7f90bc69f360, 0xc6fb60)
        /home/faide/go/src/github.com/paked/engi/engi.go:68 +0xf4 fp=0xc8200c7ea0 sp=0xc8200c7e70
    main.main()
        /home/faide/go/src/github.com/paked/engi/demos/hud/hud.go:108 +0xab fp=0xc8200c7f50 sp=0xc8200c7ea0
    runtime.main()
        /home/faide/tools/go/src/runtime/proc.go:111 +0x2b0 fp=0xc8200c7fa0 sp=0xc8200c7f50
    runtime.goexit()
        /home/faide/tools/go/src/runtime/asm_amd64.s:1721 +0x1 fp=0xc8200c7fa8 sp=0xc8200c7fa0
    
    goroutine 17 [syscall, locked to thread]:
    runtime.goexit()
        /home/faide/tools/go/src/runtime/asm_amd64.s:1721 +0x1
    

    if I suppress the call to w.AddEntity(hudBg) it works so I suspect something in generateHUDBackground but I can't see what really differs from generateBackground which works fine.

  • Cleanup: engi has both responder and Wo - global

    Cleanup: engi has both responder and Wo - global

    In engi.go, two variables are globally defined:

    var (
        responder   Responder
        Wo          Responder
    )
    

    They have exactly the same value, and are used for exactly the same. Which one are we keeping?

    Side-node, if it's a Responder (and not a World), should we even call it Wo? It took me a while before I noticed why Wo didn't have the functions / variables available that World has.

  • Changed Systemer to System interface

    Changed Systemer to System interface

    Fixes #119

    Breaking change

    Things like

    type MyCustomSystem struct {
        *ecs.System
    }
    

    have become

    type MyCustomSystem struct {
        *ecs.BasicSystemWrapper
    }
    

    Things like

    func (m *MyCustomSystem) New(*ecs.World) {
        m.System = ecs.NewSystem()
    }
    

    have become

    func (m *MyCustomSystem) New(*ecs.World) {
        m.BasicSystemWrapper = ecs.NewBasicSystemWrapper(m)
    }
    

    Things like

    func (*MyCustomSystem) Update(*ecs.Entity, float32) {}
    

    have become

    func (*MyCustomSystem) EUpdate(*ecs.Entity, float32) {}
    

    New features

    A valid System (which you can add to a World instance), is this:

    type MyCustomSystem struct {}
    func (*MyCustomSystem) Type() string { return "MyCustomSystem" }
    func (*MyCustomSystem) Priority() int { return 1 }
    func (*MyCustomSystem) AddEntity(*ecs.Entity) {}
    func (*MyCustomSystem) RemoveEntity(*ecs.Entity) {}
    func (*MyCustomSystem) New(*ecs.World) {}
    func (*MyCustomSystem) Update(dt float32) {}
    

    One can still use the 'old' behavior which does the looping-over-entities for you, this can be done like:

    type MyCustomSys struct {
        *ecs.BasicSystemWrapper
    }
    func (*MyCustomSys) Type() string { return "MyCustomSys" }
    func (*MyCustomSys) Pre() {}
    func (*MyCustomSys) Post() {}
    func (m *MyCustomSys) New(*ecs.World) {
        m.BasicSystemWrapper = ecs.NewBasicSystemWrapper(m)
    }
    func (*MyCustomSys) EUpdate(*ecs.Entity, float32) {}
    
  • Click handling

    Click handling

    How should clicks be handled according to the ECS?

    In javascript/html, there's some kind of propagation: the foremost element is clicked, then passed along to any other element that may have been involved ; and each time the element has the ability to stop the propagation.

    In ECS, I would assume there is some kind of System that monitors whether or not something gets clicked?

    Any best-practices here? Anything I misunderstood? (I imagine the "buttons" in the "main menu" I'm creating, to be some kind of clickable)


    Current status

    • [ ] Rightclick-handling
  • Keys namespace

    Keys namespace

    As of this moment, each key is under the same general namespace. So if you want the w key, you would get engo.W.

    My proposition: Namespace so we could get it with engo.Keys.W. This way we wouldn't "dirty" the general namespace and it would be easier with an IDE for example to understand what that engo.W means.

  • Remove

    Remove "ECS" branding

    From gitter:

    @paked 09:15 Thoughts on removing ECS from our branding? @paked 09:16 I have a theory some people are intimidated by the idea of "using ECS"

    Thoughts everyone?

    Basically I'd like to make us a "game engine", not an "ECS game engine" - even though we will still use ECS under the hood, and the users will still interact with it.

  • Mint Linux/Ubuntu setup error

    Mint Linux/Ubuntu setup error

    I'm new to go (learning by making a game with engo) so it may be a misunderstanding on my part.

    $ sudo apt-get install libopenal-dev libglu1-mesa-dev freeglut3-dev mesa-common-dev xorg-dev libgl1-mesa-dev golang gccgo-go
    $ go get -u engo.io/engo
    # github.com/go-gl/mathgl/mgl32
    ../go/src/github.com/go-gl/mathgl/mgl32/mempool.go:12: undefined: sync.Pool
    ../go/src/github.com/go-gl/mathgl/mgl32/mempool.go:29: undefined: sync.Pool
    ../go/src/github.com/go-gl/mathgl/mgl32/mempool.go:41: undefined: sync.Pool
    # github.com/luxengine/math
    ../go/src/github.com/luxengine/math/sqrt_amd64.s:6 6a: No such file or directory: textflag.h
    # golang.org/x/mobile/internal/mobileinit
    ../go/src/golang.org/x/mobile/internal/mobileinit/ctx_android.go:8:17: fatal error: jni.h: No such file or directory
     #include <jni.h>
                     ^
    compilation terminated.
    
  • Error upon trying to import engo

    Error upon trying to import engo

    I am running Linux Mint 17.2, if it helps.

    I installed the dependencies with the command sudo apt-get install libopenal-dev libglu1-mesa-dev freeglut3-dev mesa-common-dev xorg-dev libgl1-mesa-dev

    Then I used the command go get -u github.com/engoengine/engo to get the library.

    I made a new file ~/test.go to try the Getting Started example, and I pasted the contents into the file.

    When I ran go run test.go I got the following error message:

    test.go:4:5: cannot find package "github.com/EngoEngine/ecs" in any of:
        /home/ryan/bin/go/src/github.com/EngoEngine/ecs (from $GOROOT)
        /home/ryan/go_workspace/src/github.com/EngoEngine/ecs (from $GOPATH)
    test.go:5:9: cannot find package "github.com/EngoEngine/engo" in any of:
        /home/ryan/bin/go/src/github.com/EngoEngine/engo (from $GOROOT)
        /home/ryan/go_workspace/src/github.com/EngoEngine/engo (from $GOPATH)
    

    I checked, and the path /home/ryan/go_workspace/src/github.com/engoengine/engo exists. Is there a case sensitivity issue or is there another problem? If it's case sensitive how would I fix it?

    Thanks!

  • Cannot Compile on m1 mac

    Cannot Compile on m1 mac

    CleanShot 2022-05-21 at 09 43 17@2x

    Im using m1 mac on the latest Monterey, and I keep getting erros where GamePad is not available to me.

    CleanShot 2022-05-21 at 09 44 13@2x

    Looking at the source I believe it is not getting compiled due to my arch?

  • Question: Can you draw upon a transparent window/canvas?

    Question: Can you draw upon a transparent window/canvas?

    Hello, I was wondering if there was an equivalent to the ebiten example that draws on a transparent window giving the effect of drawing upon the desktop? The relevant relevant code they have is in their mascot example:

    $ go run -tags=example github.com/hajimehoshi/ebiten/v2/examples/[email protected]
    

    I tried setting my canvas background color but this doesn't seem to be enough, because the background still shows up as black.

    common.SetBackground(color.Transparent)
    

    Is there a way to manage the window's settings/configuration to do the same thing? Is there a way to signal this to the glfw library underneath?

  • TMX resources cannot handle tile sets that leave a rest at end of rows

    TMX resources cannot handle tile sets that leave a rest at end of rows

    I build this map with Tiled and imported into the adventure demo and somehow it mixes up some of the assets. It looks fine in the editor. Do you have any advice, or could this be a bug?

    In-Game render: Screenshot 2021-08-02 at 02 13 07 Tiled Map Editor: Screenshot 2021-08-02 at 02 13 20

    Those are the assets I tried out: https://opengameart.org/content/whispers-of-avalon-grassland-tileset

  • WSL to build on windows

    WSL to build on windows

    WSL's latest update includes monitor/window support. I'd like to test it out to and see if it's a viable alternative to MySys/Cygwin for building on windows yet.

  • Update isometric demo to use tiles of different sizes

    Update isometric demo to use tiles of different sizes

    When isometric tiles of different sizes are used, Tiled arranges them such that the tile lines up with the bottom-most point of the grid, and allows the tiles to overflow. Update the isometric demo to account for that.

AircraftWar - a game powered by Go+ spx game engine
AircraftWar - a game powered by Go+ spx game engine

AircraftWar - a game powered by Go+ spx game engine How to run Download Go+ and build it. See https://github.com/goplus/gop#how-to-build. Download thi

Jan 5, 2022
FlappyCalf - a game powered by Go+ spx game engine
FlappyCalf - a game powered by Go+ spx game engine

FlappyCalf - a game powered by Go+ spx game engine How to run Download Go+ and build it. See https://github.com/goplus/gop#how-to-build. Download this

Jan 10, 2022
FlappyCalf - a game powered by Go+ spx game engine
FlappyCalf - a game powered by Go+ spx game engine

FlappyCalf - a game powered by Go+ spx game engine How to run Download Go+ and build it. See https://github.com/goplus/gop#how-to-build. Download this

Jan 10, 2022
MazePlay - a game powered by Go+ spx game engine
MazePlay - a game powered by Go+ spx game engine

MazePlay - a game powered by Go+ spx game engine How to run Download Go+ and build it. See https://github.com/goplus/gop#how-to-build. Download this g

Dec 16, 2021
Blunder is an open-source UCI compatible chess engine.

A UCI compatible chess engine written in Golang

Jun 13, 2022
A simple game that I created with Ebiten game library as a way to teach myself Go. Enjoy!
A simple game that I created with Ebiten game library as a way to teach myself Go. Enjoy!

galactic-asteroid-belt Overview A simple game that I created with Ebiten game library as a way to teach myself Go. Enjoy! Run To run, you will need Go

Dec 2, 2021
RundQuiz-Game - This is a Go exercise that implements and builds a quiz game from a list of math questions in a CSV file.

Go RundQuiz Game Exercise details This exercise is broken into two parts to help simplify the process of explaining it as well as to make it easier to

Jan 5, 2022
Simple 2D game to teach myself various things about game development and ECS, etc

2d-grass-game I really don't know what to name this game. Its a big grass field, and its in 2d so....2D Grass game This is a simple 2D game to teach m

Jan 17, 2022
Go 3D Game Engine
Go 3D Game Engine

G3N - Go 3D Game Engine G3N (pronounced "gen") is an OpenGL 3D Game Engine written in Go. It can be used to write cross-platform Go applications that

Jun 26, 2022
Scalable Distributed Game Server Engine with Hot Swapping in Golang
Scalable Distributed Game Server Engine with Hot Swapping in Golang

GoWorld Scalable Distributed Game Server Engine with Hot Reload in Golang Features Architecture Introduction Get GoWorld Manage GoWorld Servers Demos

Jun 28, 2022
A pure Go game engine
A pure Go game engine

Oak A pure Go game engine Table of Contents Installation Motivation Features Support Quick Start Implementation and Examples Finished Games Installati

Jul 1, 2022
Terminal-based game engine for Go, built on top of Termbox
Terminal-based game engine for Go, built on top of Termbox

Termloop Termloop is a pure Go game engine for the terminal, built on top of the excellent Termbox. It provides a simple render loop for building game

Jun 17, 2022
A 2D ARPG game engine.
A 2D ARPG game engine.

Abyss Engine is an ARPG game engine in the same vein of the 2000's games, and supports playing games similar to Diablo 2. The engine is written in golang and is cross platform. This engine does not ship with game specific files, and will require a game's assets in order to run.

Jun 4, 2022
A small fantasy game engine in WASM using GoLang
A small fantasy game engine in WASM using GoLang

The GoLang Fantasy Engine (GoLF Engine) is a retro game engine. It draws inspiration from fantasy console projects like pico-8, tic-80, and pyxle. Like those projects it is designed to be a retro-feeling game creation/playing tool. Unlike those projects GoLF is more minimal in scope and only provides an API and a small set of tools to help you create your games. Tools like an image editor and code editor are not built in. Despite this minimalism creating games in GoLF is still easy and should still maintain the retro game feel.

May 25, 2022
golang powered game engine
golang powered game engine

Gobatch Go powered engine that offers features from low level opengl abstraction to UI framework. I created this to separate lot of logic from game am

May 22, 2022
spx - A 2D Game Engine for learning Go+
spx - A 2D Game Engine for learning Go+

spx - A 2D Game Engine for learning Go+ Tutorials How to run spx tutorials? Download Go+ and build it. See https://github.com/goplus/gop#how-to-build.

Jun 23, 2022
Go Game Engine using SDL for fun

nMage nMage is a (hopefully!) high performance 3D Game Engine written in Go being developed live, with recordings posted on YouTube. This project is b

Jun 5, 2022
HelloSpx - Hello world of Go+ spx game engine
HelloSpx - Hello world of Go+ spx game engine

HelloSpx - Hello world of Go+ spx game engine How to run Download Go+ and build it. See https://github.com/goplus/gop#how-to-build. Download this game

Nov 27, 2021
HelloWorldForSpx - Hello world of Go+ spx game engine
 HelloWorldForSpx - Hello world of Go+ spx game engine

HelloWorldForSpx - Hello world of Go+ spx game engineHelloWorldForSpx - Hello world of Go+ spx game engine

Nov 22, 2021