Skip to content

Instantly share code, notes, and snippets.

@husio
Created October 2, 2012 16:44
Show Gist options
  • Select an option

  • Save husio/3820919 to your computer and use it in GitHub Desktop.

Select an option

Save husio/3820919 to your computer and use it in GitHub Desktop.
server.go
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<title>Index</title>
<script src="http://code.jquery.com/jquery-1.8.2.min.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
var players = {};
var myid = prompt("Nick:");
function Player(id) {
this.id = id;
this.el = $('<div>' + id + '</div>')
.addClass('player')
.appendTo('#content');
if (id === myid) {
this.el.addClass('me');
}
};
Player.prototype.position = function (x, y) {
this.el.css({top: y, left: x});
};
$(function () {
var log = function () {
//console.log(arguments);
}
var socket = new WebSocket("ws://" + document.location.host + "/ws");
var ping;
var onMouseMove = function (e) {
var data = JSON.stringify([myid, e.pageX - 25, e.pageY - 30]);
log("sending", data);
socket.send(data);
};
var heartbeat = function () {
socket.send(JSON.stringify([myid, Date.now()]));
ping = setTimeout(heartbeat, 1000);
};
socket.onopen = function () {
log('opened');
$('#content').bind('mousemove', onMouseMove);
heartbeat();
};
socket.onerror = function (error) {
log('error', error);
$('#content').unbind('mousemove', onMouseMove);
clearInterval(ping);
};
socket.onclose = function () {
log('close');
$('#content').unbind('mousemove', onMouseMove);
clearInterval(ping);
}
socket.onmessage = function (pack) {
var now = Date.now();
var msg = JSON.parse(pack.data)
if (msg.length === 2) {
if (msg[0] === myid) {
handlePing(now - parseInt(msg[1], 10));
}
} else {
handleMove(msg);
}
};
var handlePing = function (diff) {
$('#ping').text('PING: (ms) ' + diff);
$('#pingpulse').fadeIn(function () { $(this).fadeOut(); });
};
var handleMove = function (msg) {
var pid, posX, posY;
pid = msg[0];
posX = msg[1];
posY = msg[2];
if (players[pid] === undefined) {
players[pid] = new Player(pid);
}
players[pid].position(posX, posY);
};
});
</script>
<style type="text/css" media="screen">
#ping {
margin: 10px;
font-size: 2em;
}
#logs {
background: #000000;
line-height: 2em;
color: #57bd13;
}
#content {
background: #dedede;
border: 2px solid #c1c1c1;
margin: 20px auto;
width: 600px;
height: 400px;
}
.player {
width: 18px;
height: 18px;
padding: 4px;
background: #aacb77;
position: absolute;
border-radius: 50%;
border: 2px solid #93c349;
color: #3f3f3f;
font-size: 12px;
}
.player.me {
border: 2px solid #6d9d22;
}
#pingpulse {
width: 20px;
height: 20px;
background: #e06565;
border-radius: 50%;
display: none;
}
</style>
</head>
<body>
<div id="content"></div>
<div id="ping"></div>
<div id="pingpulse"></div>
<code><pre id="logs"></pre></code>
</body>
</html>
package main
import (
"code.google.com/p/go.net/websocket"
"flag"
"fmt"
"io"
"net/http"
)
var port *int = flag.Int("p", 23456, "Port to listen.")
var clients []*Client
func init() {
clients = make([]*Client, 0, 10)
}
type Client struct {
ws *websocket.Conn
tosend chan []byte
}
func ClientNew(ws *websocket.Conn) *Client {
tosend := make(chan []byte, 32)
go func() {
for {
data := <-tosend
ws.Write(data)
}
}()
return &Client{tosend: tosend}
}
func (c *Client) Write(data []byte) {
c.tosend <- data
}
func handleClient(ws *websocket.Conn) {
clients = append(clients, ClientNew(ws))
for {
buf := make([]byte, 1024)
n, err := ws.Read(buf)
if err != nil && err != io.EOF {
fmt.Println(err)
break
}
if n == 0 {
continue
}
for _, c := range clients {
c.Write(buf[:n])
}
}
}
func main() {
flag.Parse()
http.Handle("/ws", websocket.Handler(handleClient))
http.Handle("/", http.FileServer(http.Dir(".")))
fmt.Printf("http://localhost:%d/\n", *port)
err := http.ListenAndServe(fmt.Sprintf(":%d", *port), nil)
if err != nil {
panic("ListenANdServe: " + err.Error())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment