diff --git a/index.html b/index.html index cdde3012..abac3cbc 100644 --- a/index.html +++ b/index.html @@ -56,6 +56,12 @@ let log = msg => { document.getElementById('div').innerHTML += msg + '
' } + +const dataChannelOptions = { + ordered: false, // do not guarantee order + maxPacketLifeTime: 3000, // in milliseconds +}; + let inputChannel = pc.createDataChannel('foo') inputChannel.onclose = () => console.log('inputChannel has closed') inputChannel.onopen = () => console.log('inputChannel has opened') @@ -81,14 +87,46 @@ pc.onicecandidate = event => { pc.createOffer({offerToReceiveVideo: true, offerToReceiveAudio: true}).then(d => pc.setLocalDescription(d)).catch(log) + +keyState = { + // controllers + a: false, + b: false, + start: false, + select: false, + + // navigators + up: false, + down: false, + left: false, + right: false, +} + +keyMap = { + 37: "left", + 38: "up", + 39: "right", + 40: "down", + + 90: "a", + 88: "b", + 67: "start", + 86: "select", +} + document.body.onkeydown = function(e){ - inputChannel.send(e.keyCode) + if (e.keyCode in keyMap) { + keyState[keyMap[e.keyCode]] = true; + } }; document.body.onkeyup = function(e){ - inputChannel.send(-e.keyCode) + if (e.keyCode in keyMap) { + keyState[keyMap[e.keyCode]] = false; + } }; + window.startSession = () => { let sd = remoteSessionDescription if (sd === '') { @@ -96,9 +134,50 @@ window.startSession = () => { } try { - pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd)))) + pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd))), + + // success + () => { + + fps = 60; // input frame per second + + setInterval(() => { + // prepare key + /* + const ( + ButtonA = iota + ButtonB + ButtonSelect + ButtonStart + ButtonUp + ButtonDown + ButtonLeft + ButtonRight + ) + */ + + st = ""; + ["a", "b", "select", "start", "up", "down", "left", "right"].forEach(elem => { + st += keyState[elem]?1:0; + }); + ss = parseInt(st, 2); + console.log(`Key state string: ${st} ==> ${ss}`); + + // send + inputChannel.send(ss); + + }, 1000 / fps) + + + }, + + // error callback + (exp) => { + console.log("setRemoteDescription failed, we are doomed"); + console.log(exp); + }); } catch (e) { - alert(e) + alert(e); } } diff --git a/ui/director.go b/ui/director.go index 88fba3aa..a6feedb6 100644 --- a/ui/director.go +++ b/ui/director.go @@ -15,16 +15,17 @@ type View interface { } type Director struct { - audio *Audio + // audio *Audio view View timestamp float64 imageChannel chan *image.RGBA inputChannel chan int } -func NewDirector(audio *Audio, imageChannel chan *image.RGBA, inputChannel chan int) *Director { +func NewDirector(imageChannel chan *image.RGBA, inputChannel chan int) *Director { +// func NewDirector(audio *Audio, imageChannel chan *image.RGBA, inputChannel chan int) *Director { director := Director{} - director.audio = audio + // director.audio = audio director.imageChannel = imageChannel director.inputChannel = inputChannel return &director diff --git a/ui/gameview.go b/ui/gameview.go index 5c9d7b75..313b3173 100644 --- a/ui/gameview.go +++ b/ui/gameview.go @@ -3,6 +3,9 @@ package ui import ( "image" + "fmt" + // "strconv" + "github.com/giongto35/game-online/nes" ) @@ -16,14 +19,14 @@ type GameView struct { record bool frames []image.Image - keyPressed []bool + keyPressed [8]bool imageChannel chan *image.RGBA inputChannel chan int } func NewGameView(director *Director, console *nes.Console, title, hash string, imageChannel chan *image.RGBA, inputChannel chan int) View { - gameview := &GameView{director, console, title, hash, false, nil, make([]bool, 255), imageChannel, inputChannel} + gameview := &GameView{director, console, title, hash, false, nil, [8]bool{false}, imageChannel, inputChannel} go gameview.ListenToInputChannel() return gameview } @@ -31,18 +34,20 @@ func NewGameView(director *Director, console *nes.Console, title, hash string, i func (view *GameView) ListenToInputChannel() { for { key := <-view.inputChannel - if key < 0 { - view.keyPressed[-key] = false - } else { - view.keyPressed[key] = true + s := fmt.Sprintf("%.8b", key) + for i := 0; i < len(s); i++ { + if s[i] == '1' { + view.keyPressed[i] = true + } else { + view.keyPressed[i] = false + } } - } } func (view *GameView) Enter() { - view.console.SetAudioChannel(view.director.audio.channel) - view.console.SetAudioSampleRate(view.director.audio.sampleRate) + // view.console.SetAudioChannel(view.director.audio.channel) + // view.console.SetAudioSampleRate(view.director.audio.sampleRate) // load state if err := view.console.LoadState(savePath(view.hash)); err == nil { return @@ -59,8 +64,8 @@ func (view *GameView) Enter() { } func (view *GameView) Exit() { - view.console.SetAudioChannel(nil) - view.console.SetAudioSampleRate(0) + // view.console.SetAudioChannel(nil) + // view.console.SetAudioSampleRate(0) // save sram cartridge := view.console.Cartridge if cartridge.Battery != 0 { @@ -87,14 +92,15 @@ func (view *GameView) Update(t, dt float64) { func (view *GameView) updateControllers() { // TODO: switch case - var buttons [8]bool - buttons[nes.ButtonLeft] = view.keyPressed[37] - buttons[nes.ButtonUp] = view.keyPressed[38] - buttons[nes.ButtonRight] = view.keyPressed[39] - buttons[nes.ButtonDown] = view.keyPressed[40] - buttons[nes.ButtonA] = view.keyPressed[32] - buttons[nes.ButtonB] = view.keyPressed[17] - buttons[nes.ButtonStart] = view.keyPressed[13] - buttons[nes.ButtonSelect] = view.keyPressed[16] - view.console.Controller1.SetButtons(buttons) + // var buttons [8]bool + // buttons[nes.ButtonLeft] = view.keyPressed[37] + // buttons[nes.ButtonUp] = view.keyPressed[38] + // buttons[nes.ButtonRight] = view.keyPressed[39] + // buttons[nes.ButtonDown] = view.keyPressed[40] + // buttons[nes.ButtonA] = view.keyPressed[32] + // buttons[nes.ButtonB] = view.keyPressed[17] + // buttons[nes.ButtonStart] = view.keyPressed[13] + // buttons[nes.ButtonSelect] = view.keyPressed[16] + // view.console.Controller1.SetButtons(buttons) + view.console.Controller1.SetButtons(view.keyPressed) } diff --git a/ui/run.go b/ui/run.go index 5b5e342b..5822bd28 100644 --- a/ui/run.go +++ b/ui/run.go @@ -2,10 +2,10 @@ package ui import ( "image" - "log" + // "log" "runtime" - "github.com/gordonklaus/portaudio" + // "github.com/gordonklaus/portaudio" ) const ( @@ -25,16 +25,17 @@ func init() { func Run(paths []string, imageChannel chan *image.RGBA, inputChannel chan int) { // initialize audio - portaudio.Initialize() - defer portaudio.Terminate() + // portaudio.Initialize() + // defer portaudio.Terminate() - audio := NewAudio() - if err := audio.Start(); err != nil { - log.Fatalln(err) - } - defer audio.Stop() + // audio := NewAudio() + // if err := audio.Start(); err != nil { + // log.Fatalln(err) + // } + // defer audio.Stop() // run director - director := NewDirector(audio, imageChannel, inputChannel) + director := NewDirector(imageChannel, inputChannel) + // director := NewDirector(audio, imageChannel, inputChannel) director.Start(paths) }