sound system refactored
This commit is contained in:
parent
18d4d7f843
commit
a9399f2d17
BIN
chip8/beep.wav
Normal file
BIN
chip8/beep.wav
Normal file
Binary file not shown.
|
@ -4,10 +4,11 @@ import (
|
||||||
_ "embed"
|
_ "embed"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"image"
|
"image"
|
||||||
|
"math"
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:embed sound.wav
|
//go:embed beep.wav
|
||||||
var Sound []byte
|
var Beep []byte
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MemorySize = 4096 // 4KB of memory
|
MemorySize = 4096 // 4KB of memory
|
||||||
|
@ -19,13 +20,14 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
Width = 64
|
Width = 64
|
||||||
Height = 32
|
Height = 32
|
||||||
FPS = 60
|
FPS = 60
|
||||||
|
SampleRate = 44100
|
||||||
)
|
)
|
||||||
|
|
||||||
type KeyPressed func(key uint8) bool
|
type KeyPressed func(key uint8) bool
|
||||||
type PlaySound func(sound []byte) func()
|
type SoundPlayer func(sound []byte) (func(), func())
|
||||||
|
|
||||||
type ROM struct {
|
type ROM struct {
|
||||||
Name string
|
Name string
|
||||||
|
@ -43,14 +45,14 @@ type Emulator struct {
|
||||||
ROM ROM // game rom
|
ROM ROM // game rom
|
||||||
Display *image.RGBA // display buffer
|
Display *image.RGBA // display buffer
|
||||||
KeyPressed KeyPressed // input function
|
KeyPressed KeyPressed // input function
|
||||||
PlaySound PlaySound
|
PlaySound func() // play sound effect
|
||||||
StopSound func()
|
StopSound func() // stop sound effect
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewEmulator(keyPressed KeyPressed, playSound PlaySound) *Emulator {
|
func NewEmulator(keyPressed KeyPressed, soundPlayer SoundPlayer) *Emulator {
|
||||||
emulator := new(Emulator)
|
emulator := new(Emulator)
|
||||||
emulator.KeyPressed = keyPressed
|
emulator.KeyPressed = keyPressed
|
||||||
emulator.PlaySound = playSound
|
emulator.PlaySound, emulator.StopSound = soundPlayer(Beep)
|
||||||
emulator.Stack = NewStack()
|
emulator.Stack = NewStack()
|
||||||
emulator.Display = image.NewRGBA(image.Rect(0, 0, Width, Height))
|
emulator.Display = image.NewRGBA(image.Rect(0, 0, Width, Height))
|
||||||
emulator.Reset()
|
emulator.Reset()
|
||||||
|
@ -97,20 +99,13 @@ func (emulator *Emulator) LoadFont() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emulator *Emulator) UpdateTimers() {
|
func (emulator *Emulator) UpdateTimers() {
|
||||||
if emulator.DT > 0 {
|
if emulator.ST != 0 {
|
||||||
emulator.DT -= 1
|
emulator.PlaySound()
|
||||||
}
|
|
||||||
if emulator.ST > 0 {
|
|
||||||
emulator.ST -= 1
|
|
||||||
if emulator.StopSound == nil {
|
|
||||||
emulator.StopSound = emulator.PlaySound(Sound)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if emulator.StopSound != nil {
|
emulator.StopSound()
|
||||||
emulator.StopSound()
|
|
||||||
emulator.StopSound = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
emulator.ST = uint8(math.Max(0, float64(emulator.ST)-1))
|
||||||
|
emulator.DT = uint8(math.Max(0, float64(emulator.DT)-1))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (emulator *Emulator) Cycle() {
|
func (emulator *Emulator) Cycle() {
|
||||||
|
|
|
@ -8,7 +8,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestEmulator_Reset(t *testing.T) {
|
func TestEmulator_Reset(t *testing.T) {
|
||||||
emulator := chip8.NewEmulator(nil, nil)
|
soundPlayer := func(sound []byte) (func(), func()) { return nil, nil }
|
||||||
|
|
||||||
|
emulator := chip8.NewEmulator(nil, soundPlayer)
|
||||||
emulator.V[0x03] = 0xFF
|
emulator.V[0x03] = 0xFF
|
||||||
emulator.V[0x0F] = 0xBB
|
emulator.V[0x0F] = 0xBB
|
||||||
|
|
||||||
|
|
BIN
chip8/sound.wav
BIN
chip8/sound.wav
Binary file not shown.
68
main.go
68
main.go
|
@ -50,71 +50,81 @@ var KeyMapping = []ebiten.Key{
|
||||||
ebiten.KeyV,
|
ebiten.KeyV,
|
||||||
}
|
}
|
||||||
|
|
||||||
type UI struct {
|
type GUI struct {
|
||||||
Emulator *chip8.Emulator
|
State State
|
||||||
State State
|
Emulator *chip8.Emulator
|
||||||
AudioContext *audio.Context
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ui *UI) Run() {
|
func (gui *GUI) Run() {
|
||||||
for {
|
for {
|
||||||
ui.Emulator.Cycle()
|
gui.Emulator.Cycle()
|
||||||
time.Sleep(time.Millisecond * 2)
|
time.Sleep(time.Millisecond * 2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ui *UI) Update() error {
|
func (gui *GUI) Update() error {
|
||||||
if ebiten.IsKeyPressed(ebiten.KeyEscape) {
|
if ebiten.IsKeyPressed(ebiten.KeyEscape) {
|
||||||
ui.Emulator.Reset()
|
gui.Emulator.Reset()
|
||||||
}
|
}
|
||||||
|
switch gui.State {
|
||||||
switch ui.State {
|
|
||||||
case LoadingState:
|
case LoadingState:
|
||||||
go ui.Run()
|
go gui.Run()
|
||||||
ui.State = RunningState
|
gui.State = RunningState
|
||||||
case RunningState:
|
case RunningState:
|
||||||
ui.Emulator.UpdateTimers()
|
gui.Emulator.UpdateTimers()
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ui *UI) Draw(screen *ebiten.Image) {
|
func (gui *GUI) Draw(screen *ebiten.Image) {
|
||||||
frame := ebiten.NewImageFromImage(ui.Emulator.Display)
|
frame := ebiten.NewImageFromImage(gui.Emulator.Display)
|
||||||
|
|
||||||
operation := new(ebiten.DrawImageOptions)
|
operation := new(ebiten.DrawImageOptions)
|
||||||
operation.GeoM.Scale(ScreenScale, ScreenScale)
|
operation.GeoM.Scale(ScreenScale, ScreenScale)
|
||||||
|
|
||||||
screen.DrawImage(frame, operation)
|
screen.DrawImage(frame, operation)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ui *UI) Layout(int, int) (int, int) {
|
func (gui *GUI) Layout(int, int) (int, int) {
|
||||||
return Width, Height
|
return Width, Height
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ui *UI) KeyPressed(key uint8) bool {
|
func KeyPressed(key uint8) bool {
|
||||||
return ebiten.IsKeyPressed(KeyMapping[key])
|
return ebiten.IsKeyPressed(KeyMapping[key])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ui *UI) PlaySound(sound []byte) func() {
|
func SoundPlayer(sound []byte) (func(), func()) {
|
||||||
player := ui.AudioContext.NewPlayerFromBytes(sound)
|
player := audio.NewContext(chip8.SampleRate).NewPlayerFromBytes(sound)
|
||||||
player.SetVolume(0.3)
|
player.SetVolume(0.3)
|
||||||
player.Play()
|
return PlaySound(player), StopSound(player)
|
||||||
return func() { _ = player.Close() }
|
}
|
||||||
|
|
||||||
|
func PlaySound(player *audio.Player) func() {
|
||||||
|
return func() {
|
||||||
|
if player.IsPlaying() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
player.Play()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func StopSound(player *audio.Player) func() {
|
||||||
|
return func() {
|
||||||
|
player.Pause()
|
||||||
|
player.Seek(0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
rom := LoadROM()
|
rom := LoadROM()
|
||||||
|
|
||||||
ui := UI{}
|
gui := GUI{}
|
||||||
ui.Emulator = chip8.NewEmulator(ui.KeyPressed, ui.PlaySound)
|
gui.State = LoadingState
|
||||||
ui.State = LoadingState
|
gui.Emulator = chip8.NewEmulator(KeyPressed, SoundPlayer)
|
||||||
ui.AudioContext = audio.NewContext(44100)
|
gui.Emulator.LoadROM(rom)
|
||||||
ui.Emulator.LoadROM(rom)
|
|
||||||
|
|
||||||
ebiten.SetWindowSize(Width, Height)
|
ebiten.SetWindowSize(Width, Height)
|
||||||
ebiten.SetWindowTitle("CHIP-8 : " + rom.Name)
|
ebiten.SetWindowTitle("CHIP-8 : " + rom.Name)
|
||||||
|
|
||||||
if err := ebiten.RunGame(&ui); err != nil {
|
if err := ebiten.RunGame(&gui); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user