DEV Community

Hajime Hoshi
Hajime Hoshi

Posted on

Go Packages we developed for our games

We have released some games in Go like Clock of Atonement and Bluebird of Happiness. Unfortunately, we haven't made them open-source yet for some business reasons. However, we're now splitting the code into some public packages for games gradually so that Go game developers can utilize them, and game developing in Go would get more popular. In this article, I'd like to list the public Go packages we developed and used for the games!

github.com/hajimehoshi/ebiten

A dead simple 2D game library. Basically this is an OpenGL wrapper. This works on multiple platforms, not only desktop but also mobiles and even web browsers by GopherJS! Actually we were able to develop the games on desktops and browsers, and released for mobiles.

Ebiten (海老天) means a tempura of shrimp, which is one of my favorite Japanese food :-)

github.com/hajimehoshi/go-mp3

An MP3 decoder in pure Go. This is a port of PDMP3, an MP3 decoder in Public Domain license. As I just ported this automatically without understanding the spec, I am still struggling to understand what is going on in my lib :-)

The motivation I developed MP3 decoder instead of other decoder like Ogg is that we wanted to make games work on browsers. Now MP3 is supported by most modern browsers but others are not supported well (e.g. Ogg). We could utilize the browser-native decoder on browsers instead of MP3 decoder in Go for performance. MP3 had patent problems, but the patents were expired in 2017.

github.com/hajimehoshi/oto

A lower level audio lib. The great thing of this is portability: this works on Windows, macOS, Linux, Android, iOS and Web browsers. This just offers an io.Writer and you can play any sound by writing bytes to the writer. With go-mp3, you can play an MP3 file with io.Copy (Example)!

func run() error {
    f, err := os.Open("classic.mp3")
    if err != nil {
        return err
    }
    defer f.Close()

    // Decode MP3 stream and the result is an `io.Reader`
    d, err := mp3.NewDecoder(f)
    if err != nil {
        return err
    }
    defer d.Close()

    // Create an oto's player, which is an `io.Writer`
    p, err := oto.NewPlayer(d.SampleRate(), 2, 2, 8192)
    if err != nil {
        return err
    }
    defer p.Close()

    // With `io.Copy`, you can play the decoded MP3 on your machine!
    if _, err := io.Copy(p, d); err != nil {
        return err
    }
    return nil
}
Enter fullscreen mode Exit fullscreen mode

Oto (音) means 'sound' in Japanese.

github.com/hajimehoshi/file2byteslice

Yet another tool to embed binary to Go file, just like go-bindata. file2bytesslice is dead simple compared to other similar packages. This just converts one binary to one byte slice literal. That's it! The motivation I developed this is that there was an incident: go-bindata's original author deleted their GitHub account and another person used the same GitHub account again, and I thought the repository is no longer trusty. Thus, I tried to develop it myself.

Usage of file2byteslice:
  -compress
        use gzip compression
  -input string
        input filename
  -output string
        output filename
  -package string
        package name (default "main")
  -var string
        variable name (default "_")
Enter fullscreen mode Exit fullscreen mode

github.com/hajimehoshi/go-mplusbitmap

A package to offer font.Face object of M+ Bitmap font for 8/16 bitty style Japanese texts. font.Face is a semi-standard interface to represent a font face, and there is a TrueType parser in Go to make font.Face instances. You can draw the text with Ebiten's text package very easily! Of course, this can be used with (semi-)standard rendering package (Example).

const text = `Hello, World!

こんにちは世界!`

func run() error {
    const (
        ox = 16
        oy = 16
    )

    dst := image.NewRGBA(image.Rect(0, 0, 320, 240))

    // Initialize the destination image dst by filling with white.
    draw.Draw(dst, dst.Bounds(), image.NewUniform(color.White), image.ZP, draw.Src)

    f := mplusbitmap.Gothic12r

    // golang.org/x/image/font's Drawer draws a text on a specified image.
    d := font.Drawer{
        Dst:  dst,
        Src:  image.NewUniform(color.Black),
        Face: f,
        Dot:  fixed.P(ox, oy),
    }

    for _, l := range strings.Split(text, "\n") {
        d.DrawString(l)
        d.Dot.X = fixed.I(ox)
        d.Dot.Y += f.Metrics().Height
    }

    // Now the text is drawn to the image dst.

    return nil
}
Enter fullscreen mode Exit fullscreen mode

github.com/hajimehoshi/chinesegamefonts

This offers (compressed) TTF binaries of Noto CJK fonts. This package's fonts are different from original Noto CJK fonts in some points.

  • The fonts are TrueType, not OpenType since there is no actually-usable Go package to parse OpenType fonts so far (golang.org/x/image/font/sfnt is under development).
  • Many glyphs are removed from the originals' and chinesegamefonts fonts include only common CJK glyphs to reduce file size. The original file sizes are 46.1 MB (both Simplified and Traditional), and the reduced ones are 4.4 MB (Simplified) and 7.6 MB (Traditional)!

Our games don't have Chinese support so far, but we're now implementing that with this font package.


Besides above packges, we are now developing packages e.g. for user interface. Stay tuned!

Top comments (11)

Collapse
 
ntoooop profile image
ntop

Great job! In fact, I have watched your game-engine for a long time (Currently, I'm making my own - korok.io). I have introduced your game and game engine to my friends to tell them Go can make game very well. But Clock of Atonement and Bluebird of Happiness is not available in China and I cann't download it with a China region Appstore account. Can you changes this?

Collapse
 
hajimehoshi profile image
Hajime Hoshi • Edited

Hi, thank you for using Ebiten! We're now doing efforts to make our apps to fit with China market, so please stay tuned.

(Currently, I'm making my own - korok.io)

Awesome work! I'll take a look at your game lib.

Collapse
 
carrollgt91 profile image
Grayson Carroll

Great work! I have just started working on a game project and go, and am definitely planning on using some of these libraries! I'll definitely contribute back when I can.

Out of curiosity, did you use another library for collision detection or write something simple yourself?

Collapse
 
hajimehoshi profile image
Hajime Hoshi

Great work! I have just started working on a game project and go, and am definitely planning on using some of these libraries! I'll definitely contribute back when I can.

Thank you! I appreciate your feedback!

Out of curiosity, did you use another library for collision detection or write something simple yourself?

No, since our games don't need such physics engines or collision detections. There are some such engines like Box2D in Go (github.com/ByteArena/box2d) and you can use this with our engine.

Collapse
 
peppage profile image
Pepp

I used ebiten to make a very basic game and used pixel perfect collision you can check it out here github.com/ranchblt/geometry-jumpe...

Collapse
 
alexniver profile image
Alexniver

great work. I just find some sample game engine, unity and libgdx is so heavy and alot of rules, your engine just what i want.

Collapse
 
hajimehoshi profile image
Hajime Hoshi

Thank you! I'm glad that my lib fits your needs. I'd appreciate your feedback!

Collapse
 
math2001 profile image
Mathieu PATUREL

Awesome! I've been trying to go a bit more, and making games is great fun. So, thanks for the libraries! :+1:

Collapse
 
hajimehoshi profile image
Hajime Hoshi

Thank you! Yeah, that's definitely fun! I'd like to make developing games in Go more popular.

Feedbacks or contributions for our libs are always welcome!

Collapse
 
luccabiagi profile image
Lucca Biagi de Paula Prado

I played with Ebiten a long time ago and now again... It's really nice to see how it evolved!!! Great Job!!!

Collapse
 
pfortinurbn profile image
Paul Fortin

Excellent!!!