2019-08-06 23:34:32

So, I've been playing with go again, and am, as I was last time, certainly enjoying it. (How can you not enjoy programming in Go?)
I've been thinking how you might make a game in Go. I've reevaluated some of the available gaming libraries out there, and have come up with a nice set of libraries:

  • SDL2 for game window, keyboard handling, etc.

  • Beep for audio processing (if you need FX like Reverb, this allows you to make custom "streamers", so you could call out to other libraries to do that for you).

  • gl for graphics

The only thing missing here is Tolk/TTS. However, that shouldn't be overly hard to implement (just load the DLL and make DLL calls). The only major difficulty would be figuring out what OS your on and loading the DLL with those system interfaces.
Thoughts? I'd be happy to make a small game framework with it for you guys to check it out.

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.

Thumbs up

2019-08-07 00:55:26

I'll certainly want to see it.
I like experimenting with new languages, maybe not like one of the forum members but still, why not?

Raduvay se, raduvay
Raduvay se domaki ne
Kolko liste po gorach
Tolko zdrave na taz kyshcha

2019-08-07 01:12:25

Same as 2.

I like cats.

Thumbs up

2019-08-07 07:34:30

same as 2 and 3

blindness is an ability. not a disability.

2019-08-07 12:06:33

sounds good, I last year did pick up the go hand book, and I quite liked the way the language worked.

Have a lovely day.

2019-08-07 15:18:15

I found Beep when looking around for an audio lib lol. I might try to set it up and see if I can get it working.

Pain is life and life is pain.

Thumbs up

2019-08-07 17:44:31 (edited by pauliyobo 2019-08-07 17:44:52)

I was actually surprised by the amount of gaming libraries are present on
Awesome GO
Not just gaming libraries, but libraries in general. I mean probably I shouldn't be surprised but still.

if you wish,  you could give a look at my github profile.
If you want to get in touch with me you can follow me on Twitter
have a nice day.
Paul

2019-08-07 18:40:30 (edited by Ethin 2019-08-07 18:42:49)

Streaming an audio file from Beep isn't hard at all. Something like this should do (it plays all supported formats, but you can easily figure out how it works):

package main

import (
    // Actual audio library
    "github.com/faiface/beep"
    // Audio codecs
    "github.com/faiface/beep/flac"
    "github.com/faiface/beep/mp3"
    "github.com/faiface/beep/vorbis"
    "github.com/faiface/beep/wav"
    // Required for actually playing the audio (makes it much easier at least)
    "github.com/faiface/beep/speaker"
    // Mime-type detection (I do this so we don't need to check audio extensions)
    "github.com/zRedShift/mimemagic"
    // Formatted output
    "fmt"
    // Required to open files
    "os"
    // Parse command-line arguments
    "flag"
    // Figure out buffer speed
    "time"
)

func main() {
    // Parse command-line arguments (files)
    flag.Parse()
    // Figure out our mime type
    mime, err := mimemagic.MatchFilePath(flag.Arg(0), -1)
    if err != nil {
        fmt.Printf("Can't identify mime type for file %s: %s\n", flag.Arg(0), err)
        os.Exit(1)
    }
    switch mime.MediaType() {
    // Is this MP3?
    case "audio/mpeg":
    case "audio/MPA":
    case "audio/mpa-robust":
        PlayMP3(flag.Arg(0))
    // Is this flac?
    case "audio/flac":
        PlayFLAC(flag.Arg(0))
    // Is this vorbis?
    case "application/ogg":
    case "audio/ogg":
    case "audio/vorbis":
    case "audio/vorbis-config":
    case "audio/x-vorbis+ogg":
        PlayVorbis(flag.Arg(0))
    // Is this wav?
    case "audio/vnd.wave":
    case "audio/wave":
    case "audio/x-wav":
        PlayWAV(flag.Arg(0))
    default:
        // We don't know!
        fmt.Printf("Unknown mime type %s (media %s, subtype %s, comment %s, acronym %s, expanded acronym %s, icon %s, gen. icon %s)\n", mime.MediaType(), mime.Media, mime.Subtype, mime.Comment, mime.Acronym, mime.ExpandedAcronym, mime.Icon, mime.GenericIcon)
        os.Exit(1)
    }
}

// Below is a lot of repetitive code

// Plays MP3 files
func PlayMP3(file string) {
    // Open file
    f, err := os.Open(file)
    if err != nil {
        fmt.Printf("Can't open file %s: %s\n", file, err)
        os.Exit(1)
    }
    // Parse file codec data
    streamer, format, err := mp3.Decode(f)
    if err != nil {
        fmt.Printf("Can't decode MP3 file %s: %s\n", err)
        os.Exit(1)
    }
    defer streamer.Close()
    fmt.Printf("Decoded MP3 file with sr %d, %d channels, %d precision\n", format.SampleRate, format.NumChannels, format.Precision)
    // Initialize speaker
    speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
    // Wait until we're done playing (speaker.Play is asynchronous)
    done := make(chan bool)
    speaker.Play(beep.Seq(streamer, beep.Callback(func() {
        done <- true
    })))
    <-done
}

// Pretty much the same as above
func PlayFLAC(file string) {
    f, err := os.Open(file)
    if err != nil {
        fmt.Printf("Can't open file %s: %s\n", file, err)
        os.Exit(1)
    }
    streamer, format, err := flac.Decode(f)
    if err != nil {
        fmt.Printf("Can't decode FLAC file %s: %s\n", err)
        os.Exit(1)
    }
    defer streamer.Close()
    fmt.Printf("Decoded FLAC file with sr %d, %d channels, %d precision\n", format.SampleRate, format.NumChannels, format.Precision)
    speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
    done := make(chan bool)
    speaker.Play(beep.Seq(streamer, beep.Callback(func() {
        done <- true
    })))
    <-done
}

func PlayVorbis(file string) {
    f, err := os.Open(file)
    if err != nil {
        fmt.Printf("Can't open file %s: %s\n", file, err)
        os.Exit(1)
    }
    streamer, format, err := vorbis.Decode(f)
    if err != nil {
        fmt.Printf("Can't decode Vorbis file %s: %s\n", err)
        os.Exit(1)
    }
    defer streamer.Close()
    fmt.Printf("Decoded Vorbis file with sr %d, %d channels, %d precision\n", format.SampleRate, format.NumChannels, format.Precision)
    speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
    done := make(chan bool)
    speaker.Play(beep.Seq(streamer, beep.Callback(func() {
        done <- true
    })))
    <-done
}

func PlayWAV(file string) {
    f, err := os.Open(file)
    if err != nil {
        fmt.Printf("Can't open file %s: %s\n", file, err)
        os.Exit(1)
    }
    streamer, format, err := wav.Decode(f)
    if err != nil {
        fmt.Printf("Can't decode WAV file %s: %s\n", err)
        os.Exit(1)
    }
    defer streamer.Close()
    fmt.Printf("Decoded WAV file with sr %d, %d channels, %d precision\n", format.SampleRate, format.NumChannels, format.Precision)
    speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/10))
    done := make(chan bool)
    speaker.Play(beep.Seq(streamer, beep.Callback(func() {
        done <- true
    })))
    <-done
}

You can see what this code does in the beep tutorial, its where I figured it out. (heh, this code could definitely be drastically simplified.)

"On two occasions I have been asked [by members of Parliament!]: 'Pray, Mr. Babbage, if you put into the machine wrong figures, will the right answers come out ?' I am not able rightly to apprehend the kind of confusion of ideas that could provoke such a question."    — Charles Babbage.

Thumbs up