diff --git a/example/piano/main.go b/example/piano/main.go index 89117d5d7..9868b1b11 100644 --- a/example/piano/main.go +++ b/example/piano/main.go @@ -103,6 +103,36 @@ func updateInput() { } } +var pianoImage *ebiten.Image + +func init() { + var err error + pianoImage, err = ebiten.NewImage(screenWidth, screenHeight, ebiten.FilterNearest) + if err != nil { + panic(err) + } + whiteKeys := []string{"A", "S", "D", "F", "G", "H", "J", "K", "L"} + width := 24 + y := 48 + for i, k := range whiteKeys { + x := i*width + 36 + height := 112 + pianoImage.DrawFilledRect(x, y, width-1, height, color.White) + common.ArcadeFont.DrawText(pianoImage, k, x+8, y+height-16, 1, color.Black) + } + + blackKeys := []string{"Q", "W", "", "R", "T", "", "U", "I", "O"} + for i, k := range blackKeys { + if k == "" { + continue + } + x := i*width + 24 + height := 64 + pianoImage.DrawFilledRect(x, y, width-1, height, color.Black) + common.ArcadeFont.DrawText(pianoImage, k, x+8, y+height-16, 1, color.White) + } +} + func update(screen *ebiten.Image) error { updateInput() for i, key := range keys { @@ -113,27 +143,7 @@ func update(screen *ebiten.Image) error { } screen.Fill(color.RGBA{0x80, 0x80, 0xc0, 0xff}) - - whiteKeys := []string{"A", "S", "D", "F", "G", "H", "J", "K", "L"} - width := 24 - y := 48 - for i, k := range whiteKeys { - x := i*width + 36 - height := 112 - screen.DrawFilledRect(x, y, width-1, height, color.White) - common.ArcadeFont.DrawText(screen, k, x+8, y+height-16, 1, color.Black) - } - - blackKeys := []string{"Q", "W", "", "R", "T", "", "U", "I", "O"} - for i, k := range blackKeys { - if k == "" { - continue - } - x := i*width + 24 - height := 64 - screen.DrawFilledRect(x, y, width-1, height, color.Black) - common.ArcadeFont.DrawText(screen, k, x+8, y+height-16, 1, color.White) - } + screen.DrawImage(pianoImage, nil) ebitenutil.DebugPrint(screen, fmt.Sprintf("FPS: %0.2f", ebiten.CurrentFPS())) return nil diff --git a/exp/audio/internal/audio.go b/exp/audio/internal/audio.go index 0cff16ecf..1942493d2 100644 --- a/exp/audio/internal/audio.go +++ b/exp/audio/internal/audio.go @@ -18,8 +18,6 @@ var audioEnabled = false const SampleRate = 44100 -var currentPosition = 0 - type channel struct { l []int16 r []int16 @@ -143,10 +141,8 @@ func loadChannelBuffer(channel int, bufferSize int) (l, r []int16) { ch := channels[channel] length := min(len(ch.l), bufferSize) - inputL := make([]int16, length) - inputR := make([]int16, length) - copy(inputL, ch.l[:length]) - copy(inputR, ch.r[:length]) + inputL := ch.l[:length] + inputR := ch.r[:length] ch.l = ch.l[length:] ch.r = ch.r[length:] ch.nextInsertionPosition -= min(bufferSize, ch.nextInsertionPosition) diff --git a/exp/audio/internal/audio_js.go b/exp/audio/internal/audio_js.go index 4e7fdbd16..7be097c66 100644 --- a/exp/audio/internal/audio_js.go +++ b/exp/audio/internal/audio_js.go @@ -33,28 +33,21 @@ var ( const bufferSize = 1024 -func audioProcess(channel int) func(e js.Object) { - return func(e js.Object) { - // Can't use 'go' here. Probably it may cause race conditions. - defer func() { - currentPosition += bufferSize - }() +type audioProcessor struct { + channel int +} - b := e.Get("outputBuffer") - l := b.Call("getChannelData", 0) - r := b.Call("getChannelData", 1) - inputL, inputR := loadChannelBuffer(channel, bufferSize) - const max = 1 << 15 - for i := 0; i < bufferSize; i++ { - // TODO: Use copyToChannel? - if len(inputL) <= i { - l.SetIndex(i, 0) - r.SetIndex(i, 0) - continue - } - l.SetIndex(i, float64(inputL[i])/max) - r.SetIndex(i, float64(inputR[i])/max) - } +func (a *audioProcessor) Process(e js.Object) { + // Can't use 'go' here. Probably it may cause race conditions. + b := e.Get("outputBuffer") + l := b.Call("getChannelData", 0) + r := b.Call("getChannelData", 1) + inputL, inputR := loadChannelBuffer(a.channel, bufferSize) + const max = 1 << 15 + for i := 0; i < len(inputL); i++ { + // TODO: Use copyToChannel? + l.SetIndex(i, float64(inputL[i])/max) + r.SetIndex(i, float64(inputR[i])/max) } } @@ -69,7 +62,8 @@ func initialize() { // https://developer.mozilla.org/ja/docs/Web/API/ScriptProcessorNode for i := 0; i < MaxChannel; i++ { node := context.Call("createScriptProcessor", bufferSize, 0, 2) - node.Call("addEventListener", "audioprocess", audioProcess(i)) + processor := &audioProcessor{i} + node.Call("addEventListener", "audioprocess", processor.Process) nodes = append(nodes, node) dummy := context.Call("createBufferSource") diff --git a/internal/graphics/framebuffer.go b/internal/graphics/framebuffer.go index e08066d62..f1de5fb3a 100644 --- a/internal/graphics/framebuffer.go +++ b/internal/graphics/framebuffer.go @@ -53,10 +53,11 @@ func orthoProjectionMatrix(left, right, bottom, top int) *[4][4]float64 { } type Framebuffer struct { - native opengl.Framebuffer - width int - height int - flipY bool + native opengl.Framebuffer + width int + height int + flipY bool + proMatrix *[4][4]float64 } func NewZeroFramebuffer(c *opengl.Context, width, height int) (*Framebuffer, error) { @@ -100,6 +101,9 @@ func (f *Framebuffer) setAsViewport(c *opengl.Context) error { } func (f *Framebuffer) projectionMatrix() *[4][4]float64 { + if f.proMatrix != nil { + return f.proMatrix + } width := NextPowerOf2Int(f.width) height := NextPowerOf2Int(f.height) m := orthoProjectionMatrix(0, width, 0, height) @@ -107,7 +111,8 @@ func (f *Framebuffer) projectionMatrix() *[4][4]float64 { m[1][1] *= -1 m[1][3] += float64(f.height) / float64(NextPowerOf2Int(f.height)) * 2 } - return m + f.proMatrix = m + return f.proMatrix } func (f *Framebuffer) Fill(c *opengl.Context, clr color.Color) error {