diff --git a/game.go b/game.go new file mode 100644 index 0000000..62362b4 --- /dev/null +++ b/game.go @@ -0,0 +1,39 @@ +package main + +type game struct { + players map[*player]bool + broadcast chan *player + register chan *player + unregister chan *player +} + +var g = game{ + broadcast: make(chan *player), + register: make(chan *player), + unregister: make(chan *player), + players: make(map[*player]bool), +} + +func (g *game) run() { + for { + select { + case c := <-g.register: + g.players[c] = true + case c := <-g.unregister: + delete(g.players, c) + close(c.send) + case p := <-g.broadcast: + for c := range g.players { + if p != c { + select { + case c.send <- p: + default: + delete(g.players, c) + close(c.send) + go c.ws.Close() + } + } + } + } + } +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..9de0ce1 --- /dev/null +++ b/main.go @@ -0,0 +1,30 @@ +package main + +import ( + "code.google.com/p/go.net/websocket" + "flag" + "fmt" + "log" + "net/http" +) + +var addr = flag.String("addr", ":8666", "http service address") +var static_files = flag.String("static", "./static", "location of static files") + +func main() { + flag.Parse() + + http.Handle("/", http.FileServer(http.Dir( + fmt.Sprintf("%s/html", *static_files)))) + http.Handle("/static/", http.StripPrefix("/static/", + http.FileServer(http.Dir(*static_files)))) + + http.Handle("/ws/game/", websocket.Handler(addPlayer)) + + go g.run() + + err := http.ListenAndServe(*addr, nil) + if err != nil { + log.Fatal("unable to start server") + } +} diff --git a/player.go b/player.go new file mode 100644 index 0000000..1dfb5cb --- /dev/null +++ b/player.go @@ -0,0 +1,83 @@ +package main + +import ( + "code.google.com/p/go.net/websocket" + "encoding/json" + "fmt" + "log" + "math" +) + +type Position struct { + X, Y int +} + +type player struct { + Position Position `json:"position"` + Name string `json:"name"` + ws *websocket.Conn + send chan *player +} + +func (p *player) validMove(next Position) (r bool) { + r = true + if math.Abs(float64(p.Position.X - next.X)) > 1 { + r = false + } + if math.Abs(float64(p.Position.Y - next.Y)) > 1 { + r = false + } + return +} + +func (p *player) sender() { + for pinfo := range p.send { + err := websocket.JSON.Send(p.ws, pinfo) + if err != nil { + break + } + } + p.ws.Close() +} + +func (p *player) recv() { + for { + var msg string + err := websocket.Message.Receive(p.ws, &msg) + if err != nil { + break + } + // XXX: the danger! + var pos Position + err = json.Unmarshal([]byte(msg), &pos) + if err != nil { + break + } + if !p.validMove(pos) { + break + } + p.Position = pos + g.broadcast <- p + } + p.ws.Close() +} + +func addPlayer(ws *websocket.Conn) { + var name string + err := websocket.Message.Receive(ws, &name) + if err != nil { + log.Fatal("trouble parsing username") + } + p := &player{ + Name: name, + send: make(chan *player, 256), + ws: ws, + } + g.register <- p + defer func() { + g.unregister <- p + }() + go p.sender() + p.recv() + fmt.Printf("%v has been disconnect from this game\n", p) +}