initial go implementation
This commit is contained in:
parent
3c0128b9b9
commit
d777a978ab
39
game.go
Normal file
39
game.go
Normal file
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
30
main.go
Normal file
30
main.go
Normal file
@ -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")
|
||||
}
|
||||
}
|
83
player.go
Normal file
83
player.go
Normal file
@ -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)
|
||||
}
|
Loading…
Reference in New Issue
Block a user