Merge branch 'chim2'

This commit is contained in:
giongto35 2019-04-06 00:23:57 +08:00
commit 1718af5ba4
5 changed files with 110 additions and 66 deletions

View file

@ -10,9 +10,10 @@ textarea {
<div id="remoteVideos" ></div> <br />
<div>
Use Up, Down, Left, Right to Move <br />
Space to jump <br />
Ctrl to sprint <br />
Enter to select in menu <br />
Z to jump (A) <br />
X to sprint (B) <br />
C is start button <br />
V is select button <br />
Fullscreen media for better gaming experience<br />
</div>
@ -76,7 +77,6 @@ pc.ontrack = function (event) {
document.getElementById('remoteVideos').appendChild(el)
}
pc.oniceconnectionstatechange = e => log(pc.iceConnectionState)
pc.onicecandidate = event => {
if (event.candidate === null) {
var session = btoa(JSON.stringify(pc.localDescription));
@ -115,7 +115,7 @@ keyMap = {
}
INPUT_FPS = 100;
INPUT_STATE_PACKET = 10;
INPUT_STATE_PACKET = 5;
stateUnchange = true;
unchangePacket = INPUT_STATE_PACKET;
@ -137,7 +137,6 @@ document.body.onkeyup = function(e){
};
window.startSession = () => {
let sd = remoteSessionDescription
if (sd === '') {
@ -145,55 +144,65 @@ window.startSession = () => {
}
try {
pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd))),
// success
() => {
setInterval(() => {
// prepare key
/*
const (
ButtonA = iota
ButtonB
ButtonSelect
ButtonStart
ButtonUp
ButtonDown
ButtonLeft
ButtonRight
)
*/
if (stateUnchange || unchangePacket > 0) {
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);
stateUnchange = false;
unchangePacket--;
}
}, 1000 / INPUT_FPS)
},
// error callback
(exp) => {
console.log("setRemoteDescription failed, we are doomed");
console.log(exp);
});
pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(atob(sd))));
} catch (e) {
alert(e);
}
}
var timer = null;
function sendInput() {
// prepare key
/*
const (
ButtonA = iota
ButtonB
ButtonSelect
ButtonStart
ButtonUp
ButtonDown
ButtonLeft
ButtonRight
)
*/
if (stateUnchange || unchangePacket > 0) {
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);
stateUnchange = false;
unchangePacket--;
}
}
function startInput() {
if (timer == null) {
timer = setInterval(sendInput, 1000 / INPUT_FPS)
}
}
function endInput() {
clearInterval(timer);
timer = null;
}
pc.oniceconnectionstatechange = e => {
log(pc.iceConnectionState);
if (pc.iceConnectionState === "connected") {
startInput();
}
else if (pc.iceConnectionState === "disconnected") {
endInput();
}
}
</script>
</html>

43
main.go
View file

@ -6,7 +6,8 @@ import (
"io/ioutil"
"log"
"net/http"
"time"
// "time"
"github.com/giongto35/game-online/ui"
"github.com/giongto35/game-online/util"
@ -14,33 +15,37 @@ import (
"github.com/gorilla/mux"
)
var webRTC *webrtc.WebRTC
// var webRTC *webrtc.WebRTC
var width = 256
var height = 240
var gameName = "Legend of Pokemon.nes"
// var FPS = 60
func init() {
}
func startGame(path string, imageChannel chan *image.RGBA, inputChannel chan int) {
ui.Run([]string{path}, imageChannel, inputChannel)
func startGame(path string, imageChannel chan *image.RGBA, inputChannel chan int, webRTC *webrtc.WebRTC) {
ui.Run([]string{path}, imageChannel, inputChannel, webRTC)
}
func main() {
imageChannel := make(chan *image.RGBA, 100)
// imageChannel := make(chan *image.RGBA, 100)
fmt.Println("http://localhost:8000")
webRTC = webrtc.NewWebRTC()
// webRTC = webrtc.NewWebRTC()
router := mux.NewRouter()
router.HandleFunc("/", getWeb).Methods("GET")
router.HandleFunc("/session", postSession).Methods("POST")
go http.ListenAndServe(":8000", router)
// go http.ListenAndServe(":8000", router)
http.ListenAndServe(":8000", router)
// start screenshot loop, wait for connection
go screenshotLoop(imageChannel)
startGame("games/"+gameName, imageChannel, webRTC.InputChannel)
time.Sleep(time.Minute)
// go screenshotLoop(imageChannel)
// startGame("games/"+gameName, imageChannel, webRTC.InputChannel)
// time.Sleep(time.Minute)
}
func getWeb(w http.ResponseWriter, r *http.Request) {
@ -58,20 +63,34 @@ func postSession(w http.ResponseWriter, r *http.Request) {
}
r.Body.Close()
webRTC := webrtc.NewWebRTC()
localSession, err := webRTC.StartClient(string(bs), width, height)
if err != nil {
log.Fatalln(err)
}
imageChannel := make(chan *image.RGBA, 100)
go screenshotLoop(imageChannel, webRTC)
go startGame("games/"+gameName, imageChannel, webRTC.InputChannel, webRTC)
w.Write([]byte(localSession))
}
func screenshotLoop(imageChannel chan *image.RGBA) {
// func screenshotLoop(imageChannel chan *image.RGBA) {
func screenshotLoop(imageChannel chan *image.RGBA, webRTC *webrtc.WebRTC) {
for image := range imageChannel {
// Client stopped
if webRTC.IsClosed() {
break
}
// encode frame
if webRTC.IsConnected() {
yuv := util.RgbaToYuv(image)
webRTC.ImageChannel <- yuv
}
time.Sleep(10 * time.Millisecond)
// time.Sleep(10 * time.Millisecond)
// time.Sleep(time.Duration(1000 / FPS) * time.Millisecond)
}
}

View file

@ -6,6 +6,7 @@ import (
"time"
"github.com/giongto35/game-online/nes"
"github.com/giongto35/game-online/webrtc"
)
type View interface {
@ -20,14 +21,16 @@ type Director struct {
timestamp float64
imageChannel chan *image.RGBA
inputChannel chan int
webRTC *webrtc.WebRTC
}
func NewDirector(imageChannel chan *image.RGBA, inputChannel chan int) *Director {
func NewDirector(imageChannel chan *image.RGBA, inputChannel chan int, webRTC *webrtc.WebRTC) *Director {
// func NewDirector(audio *Audio, imageChannel chan *image.RGBA, inputChannel chan int) *Director {
director := Director{}
// director.audio = audio
director.imageChannel = imageChannel
director.inputChannel = inputChannel
director.webRTC = webRTC
return &director
}
@ -61,6 +64,11 @@ func (d *Director) Start(paths []string) {
func (d *Director) Run() {
for {
// quit game
if d.webRTC.IsClosed() {
break
}
d.Step()
}
d.SetView(nil)

View file

@ -6,6 +6,7 @@ import (
"runtime"
// "github.com/gordonklaus/portaudio"
"github.com/giongto35/game-online/webrtc"
)
const (
@ -23,7 +24,7 @@ func init() {
runtime.LockOSThread()
}
func Run(paths []string, imageChannel chan *image.RGBA, inputChannel chan int) {
func Run(paths []string, imageChannel chan *image.RGBA, inputChannel chan int, webRTC *webrtc.WebRTC) {
// initialize audio
// portaudio.Initialize()
// defer portaudio.Terminate()
@ -35,7 +36,7 @@ func Run(paths []string, imageChannel chan *image.RGBA, inputChannel chan int) {
// defer audio.Stop()
// run director
director := NewDirector(imageChannel, inputChannel)
director := NewDirector(imageChannel, inputChannel, webRTC)
// director := NewDirector(audio, imageChannel, inputChannel)
director.Start(paths)
}

View file

@ -108,6 +108,7 @@ type WebRTC struct {
connection *webrtc.PeerConnection
encoder *vpxEncoder.VpxEncoder
isConnected bool
isClosed bool
// for yuvI420 image
ImageChannel chan []byte
InputChannel chan int
@ -164,6 +165,7 @@ func (w *WebRTC) StartClient(remoteSession string, width, height int) (string, e
w.StopClient()
}
})
//w.listenInputChannel()
// Data channel
w.connection.OnDataChannel(func(d *webrtc.DataChannel) {
@ -210,6 +212,7 @@ func (w *WebRTC) StopClient() {
w.connection.Close()
}
w.connection = nil
w.isClosed = true
}
// IsConnected comment
@ -217,6 +220,10 @@ func (w *WebRTC) IsConnected() bool {
return w.isConnected
}
func (w *WebRTC) IsClosed() bool {
return w.isClosed
}
func (w *WebRTC) startStreaming(vp8Track *webrtc.Track) {
fmt.Println("Start streaming")
// send screenshot