ebiten learning-infinite loop player

Posted by johnnyblotter on Sun, 10 Oct 2021 18:09:07 +0200

2021SC@SDUSC

Catalog

1. Preface

1. Description

2.ebiten package directory

3. Summary

2. Infinite Loop Audio

1. Package

2. Introducing packages

3. Start with main()

4.Layout method

5.Update logic

6.Draw drawing interface

7. Running results

8. Summary

3. Ending

1. Difficulties

2. Next time

1. Preface

1. Description

audio description document address

audio package - github.com/hajimehoshi/ebiten/v2/audio - pkg.go.dev

All screenshots and code in this article are from Description Documentation Or ebiten source file

The author is responsible for audio Audio-related code analysis

2.ebiten package directory

3. Summary

Analysis audioinfiniteloop An implementation of an infinite audio loop (example in ebiten source)

file location

 

Code Appearance

This "game" inherits run.go Game Structures and Methods in

// game's Update function is called every tick to update the game logic.

Update method is invoked for each frame, default 60 frames TPS = 60

// game's Draw function is called every frame to draw the screen.

The Draw method draws interface elements, and ebiten sees everything as a picture

// game's Layout function is called when necessary, and you can specify the logical screen size by the function.

A proportional relationship between the size of a program box and the size of an internal screen

* From run.go File Method Comments

2. Infinite Loop Audio

1. Package

package main

Represents that this file belongs to the main package, the main method can only be in the main package

2. Introducing packages

The next few rows use the relative path of the package because the go mod package management is used

The compiler looks for packages in GOPATH and GOROOT

The last line is renamed raudio

Similar

import (
     _ "      "
)

Introduce no-use methods only (go must be used by default)

import (
     . "      "
)

Method full copy introduction (less common, risk of duplication)

 

3. Start with main()

func main() {
    ebiten.SetWindowSize(screenWidth, screenHeight)
    ebiten.SetWindowTitle("Audio Infinite Loop (Ebiten Demo)")
    if err := ebiten.RunGame(&Game{}); err != nil {
        log.Fatal(err)
    }
}

The first is to call the SetWindowSize(,) method in ebiten to set the window size

The parameter passed in is a global constant

 

Then the SetWindowTitle() method sets the title of the window

The effect is shown in the diagram

Last run this game". RunGame() method has only one process

If an error occurs, it terminates and logs

(Methods such as RunGame() will be specifically analyzed later)

4.Layout method

func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
    return screenWidth, screenHeight
}

Layout method to set the window size, specific operations not found, next week and analysis of ui students to exchange

5.Update logic

func (g *Game) Update() error {

//This program only needs one player, which is a restriction statement and passes only once at the beginning

    if g.player != nil {
        return nil
    }

//Create an audio environment (audioContext) at the sampling frequency (constant sampleRate = 22050)

//Audio environment to create a Player

    if g.audioContext == nil {
        g.audioContext = audio.NewContext(sampleRate)
    }

//Decode the Ogg file (raudio.Ragtime_ogg) according to the sampling frequency of the audio environment

//oggs is both a decoded stream reader and a stream shutdown as well as a stream locator

    // Decode an Ogg file.
    // oggS is a decoded io.ReadCloser and io.Seeker.
    oggS, err := vorbis.Decode(g.audioContext, bytes.NewReader(raudio.Ragtime_ogg))
    if err != nil {
        return err
    }

//Create an infinite loop with decoded oggs

//Incoming Parameter Introduction Length and Loop Length, Seconds is Constant, *4 Cause: 16 bits Dual Channel /> 2 bytes * 2 Channels

    // Create an infinite loop stream from the decoded bytes.
    // s is still an io.ReadCloser and io.Seeker.
    s := audio.NewInfiniteLoopWithIntro(oggS, introLengthInSecond*4*sampleRate, loopLengthInSecond*4*sampleRate)

//New Player

//Start the player

    g.player, err = g.audioContext.NewPlayer(s)
    if err != nil {
        return err
    }
​
    // Play the infinite-length stream. This never ends.
    g.player.Play()
    return nil
}

 

6.Draw drawing interface

Figure

//Get the effect after the Current decimal point in the figure above

func (g *Game) Draw(screen *ebiten.Image) {
    pos := g.player.Current()
    if pos > 5*time.Second {
        pos = (g.player.Current()-5*time.Second)%(4*time.Second) + 5*time.Second
    }

//Format String

    msg := fmt.Sprintf(`TPS: %0.2f
This is an example using
audio.NewInfiniteLoopWithIntro.
​
Intro:   0[s] - %[2]d[s]
Loop:    %[2]d[s] - %[3]d[s]
Current: %0.2[4]f[s]`, ebiten.CurrentTPS(), introLengthInSecond, introLengthInSecond+loopLengthInSecond, float64(pos)/float64(time.Second))
// DebugPrint draws the string str on the image on left top corner.
    ebitenutil.DebugPrint(screen, msg)
}

 

7. Running results

Audio for 9 seconds

Play first 5 seconds, then 4 seconds after infinite loop

Set lines 2 to 3 to the bottom of the figure below

Current from 0.00 //> 8.99

 

Current Loops Infinitely from 5.00 /> 8.99

 

 

8. Summary

  • The core method in this example is the overridden Update() method
  • Play Step 1: Generate an audio environment based on the sampling frequency
g.audioContext = audio.NewContext(sampleRate)
  • Step 2: Decode and name the audio file in the above audio environment
oggS, err := vorbis.Decode(g.audioContext, bytes.NewReader(raudio.Ragtime_ogg))
if err != nil {
	return err
}
  • Step 3: Create an infinite loop io.Reader with the decoded variables, the length of the introduction, and the length of the loop
s := audio.NewInfiniteLoopWithIntro(oggS, introLengthInSecond*4*sampleRate, loopLengthInSecond*4*sampleRate)
  • Step 4: Create a player with step 3 io.Reader in the above audio environment
g.player, err = g.audioContext.NewPlayer(s)
if err != nil {
	return err
}
  • Step 5: Play() method is called by the player
g.player.Play()

3. Ending

1. Difficulties

This is the initial understanding of audio and a simple process to get familiar with ebiten.

Some of them are not easy to analyze. The methods used in the example dig in one layer at a time, involving the structure, inheritance, overloading, etc. in the go language. Others are not clear, such as

What is &Game{}?

When is the Layout() method called?

What does bitDepthInBytes = 2 mean?

Audio environment, what is the logic behind the player?

 

2. Next time

Next week, learn the logic behind it, learn how go inherits, and write a few demo implementations.

Topics: Go