client/spectator.go

167 lines
4.3 KiB
Go
Raw Normal View History

package client
import (
"log"
2014-05-12 22:11:44 -07:00
"math"
2014-05-04 00:33:46 -07:00
"github.com/nsf/termbox-go"
"bitbucket.org/hackerbots/server"
)
2014-05-04 00:33:46 -07:00
var bots = []rune{
'。', 'ヲ', 'ァ', 'ィ', 'ゥ', 'ェ', 'ォ', 'ャ', 'ュ', 'ョ', 'ッ', 'ー', 'ア', 'イ', 'ウ',
'エ', 'オ', 'カ', 'キ', 'ク', 'ケ', 'コ', 'サ', 'シ', 'ス', 'セ', 'ソ', 'タ', 'チ', 'ツ',
'テ', 'ト', 'ナ', 'ニ', 'ヌ', 'ネ', 'ノ', 'ハ', 'ヒ', 'フ', 'ヘ', 'ホ', 'マ', 'ミ', 'ム',
'メ', 'モ', 'ヤ', 'ユ', 'ヨ', 'ラ', 'リ', 'ル', 'レ', 'ロ', 'ワ', 'ン', '゙', '゚',
}
type size struct {
width, height int
}
type SimpleSpectator struct {
width, height float64
2014-05-04 00:33:46 -07:00
viewX, viewY int
update chan *server.Boardstate
}
// NewSimpleSpectator simply returns a populated, usable *SimplePlayer
func NewSimpleSpectator(width, height float64) *SimpleSpectator {
return &SimpleSpectator{
width: width,
height: height,
2014-05-04 00:33:46 -07:00
update: make(chan *server.Boardstate),
}
}
// Recv is our implementation of receiving a server.Boardstate from the server
2014-05-04 00:33:46 -07:00
func (s *SimpleSpectator) Update(bs *server.Boardstate) map[string]server.Instruction {
s.update <- bs
return nil
}
2014-05-04 00:33:46 -07:00
func (s *SimpleSpectator) Run() {
err := termbox.Init()
if err != nil {
log.Fatal(err)
}
s.viewX, s.viewY = termbox.Size()
events := make(chan termbox.Event)
go func() {
for {
events <- termbox.PollEvent()
}
}()
termbox.HideCursor()
termbox.Clear(termbox.ColorBlack, termbox.ColorBlack)
func() {
for {
select {
case event := <-events:
switch event.Type {
case termbox.EventKey:
switch event.Key {
case termbox.KeyCtrlZ, termbox.KeyCtrlC:
log.Printf("exiting ...")
return
}
switch event.Ch {
case 'q':
return
case 'c':
termbox.Clear(termbox.ColorBlack, termbox.ColorBlack)
}
case termbox.EventResize:
s.viewX, s.viewY = event.Width, event.Height
case termbox.EventError:
log.Fatalf("Quitting because of termbox error: \n%s\n", event.Err)
}
case u := <-s.update:
termbox.Clear(termbox.ColorBlack, termbox.ColorBlack)
for _, obstacle := range u.Obstacles {
startX := int((obstacle.Bounds.A.X / s.width) * float64(s.viewX))
stopX := int((obstacle.Bounds.B.X / s.width) * float64(s.viewX))
startY := int((obstacle.Bounds.A.Y / s.height) * float64(s.viewY))
stopY := int((obstacle.Bounds.B.Y / s.height) * float64(s.viewY))
for x := startX; x < stopX; x++ {
for y := startY; y < stopY; y++ {
termbox.SetCell(
x,
s.viewY-y,
' ',
termbox.ColorBlack, termbox.ColorBlue,
)
}
}
}
for i, bot := range u.OtherRobots {
x := int((bot.Position.X / s.width) * float64(s.viewX))
y := int((bot.Position.Y / s.height) * float64(s.viewY))
b := bots[i%len(bots)]
c := termbox.ColorWhite
if bot.Health < 0 {
c = termbox.ColorBlack
}
termbox.SetCell(
x,
s.viewY-y,
b,
c|termbox.AttrBold, termbox.ColorBlack,
)
}
for _, p := range u.Projectiles {
x := int((p.Position.X / s.width) * float64(s.viewX))
y := int((p.Position.Y / s.height) * float64(s.viewY))
termbox.SetCell(
x,
s.viewY-y,
'·',
termbox.ColorWhite|termbox.AttrBold, termbox.ColorBlack,
)
}
for _, splosion := range u.Splosions {
2014-05-12 22:11:44 -07:00
startX := int(((splosion.Position.X - float64(splosion.Radius)) / s.width) * float64(s.viewX))
startY := int(((splosion.Position.Y - float64(splosion.Radius)) / s.height) * float64(s.viewY))
stopX := int(((splosion.Position.X+float64(splosion.Radius))/s.width)*float64(s.viewX)) + 1
stopY := int(((splosion.Position.Y+float64(splosion.Radius))/s.height)*float64(s.viewY)) + 1
for x := startX; x < stopX; x++ {
for y := startY; y < stopY; y++ {
realX := float64(x) * s.width / float64(s.viewX)
realY := float64(y) * s.height / float64(s.viewY)
dX := realX - splosion.Position.X
dY := realY - splosion.Position.Y
curRad := math.Sqrt(dX*dX + dY*dY)
if curRad < float64(splosion.Radius) {
termbox.SetCell(
x,
s.viewY-y,
'·',
termbox.ColorYellow|termbox.AttrBold, termbox.ColorRed,
)
}
}
}
2014-05-04 00:33:46 -07:00
}
err := termbox.Flush()
if err != nil {
log.Fatal(err)
}
}
}
}()
termbox.Close()
}