Browse Source

Add lobby screen

wip
Trevor Slocum 9 months ago
parent
commit
475bae8664
  1. 33
      game/board.go
  2. 12
      game/colors.go
  3. 114
      game/game.go
  4. 357
      game/lobby.go
  5. 14
      go.mod
  6. 40
      go.sum
  7. 15
      main.go

33
game/board.go

@ -134,13 +134,6 @@ func (b *board) newSprite(white bool) *Sprite { @@ -134,13 +134,6 @@ func (b *board) newSprite(white bool) *Sprite {
}
func (b *board) updateBackgroundImage() {
tableColor := color.RGBA{0, 102, 51, 255}
frameColor := color.RGBA{65, 40, 14, 255}
borderColor := color.RGBA{0, 0, 0, 255}
faceColor := color.RGBA{120, 63, 25, 255}
triangleA := color.RGBA{225.0, 188, 125, 255}
triangleB := color.RGBA{120.0, 17.0, 0, 255}
borderSize := b.horizontalBorderSize
if borderSize > b.barWidth/2 {
borderSize = b.barWidth / 2
@ -812,24 +805,30 @@ func (b *board) _movePiece(sprite *Sprite, from int, to int, speed int, pause bo @@ -812,24 +805,30 @@ func (b *board) _movePiece(sprite *Sprite, from int, to int, speed int, pause bo
sprite.toTime = moveTime
sprite.toStart = time.Now()
ebiten.ScheduleFrame()
log.Println("SCHEDULED FRAME, SLEEP")
time.Sleep(sprite.toTime)
sprite.x = x
sprite.y = y
sprite.toStart = time.Time{}
ebiten.ScheduleFrame()
log.Println("SCHEDULED FRAME, UNSLEEP")
if pause {
log.Println("PAUSE ", pauseTime)
time.Sleep(pauseTime)
log.Println("UNPAUSE")
} else {
time.Sleep(50 * time.Millisecond)
}
homeSpace := b.Client.Board.PlayerHomeSpace()
/*homeSpace := b.Client.Board.PlayerHomeSpace()
if b.v[fibs.StateTurn] != b.v[fibs.StatePlayerColor] {
homeSpace = 25 - homeSpace
}
if to != homeSpace {
b.spaces[to] = append(b.spaces[to], sprite)
}
if to != homeSpace {*/
b.spaces[to] = append(b.spaces[to], sprite)
/*}*/
for i, s := range b.spaces[from] {
if s == sprite {
b.spaces[from] = append(b.spaces[from][:i], b.spaces[from][i+1:]...)
@ -860,14 +859,7 @@ func (b *board) movePiece(from int, to int) { @@ -860,14 +859,7 @@ func (b *board) movePiece(from int, to int) {
b._movePiece(sprite, from, to, 1, moveAfter == nil)
if moveAfter != nil {
toBar := 0
if b.v[fibs.StateDirection] == -1 {
toBar = 25
}
if b.v[fibs.StateTurn] != b.v[fibs.StatePlayerColor] {
toBar = 25 - toBar // TODO how is this determined?
}
b._movePiece(moveAfter, to, toBar, 1, true)
b._movePiece(moveAfter, to, b.Client.Board.PlayerBarSpace(), 1, true)
}
log.Println("FINISH MOVE PIECE", from, to)
}
@ -895,12 +887,12 @@ func (b *board) update() { @@ -895,12 +887,12 @@ func (b *board) update() {
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
if b.dragging == nil {
x, y := ebiten.CursorPosition()
handled := handleReset(x, y)
if !handled {
s := b.spriteAt(x, y)
if s != nil {
b.dragging = s
// TODO set dragFrom instead of calculating later
}
}
}
@ -909,7 +901,6 @@ func (b *board) update() { @@ -909,7 +901,6 @@ func (b *board) update() {
b.touchIDs = inpututil.AppendJustPressedTouchIDs(b.touchIDs[:0])
for _, id := range b.touchIDs {
x, y := ebiten.TouchPosition(id)
handled := handleReset(x, y)
if !handled {
b.dragX, b.dragY = x, y

12
game/colors.go

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
package game
import "image/color"
var (
tableColor = color.RGBA{0, 102, 51, 255}
frameColor = color.RGBA{65, 40, 14, 255}
borderColor = color.RGBA{0, 0, 0, 255}
faceColor = color.RGBA{120, 63, 25, 255}
triangleA = color.RGBA{225.0, 188, 125, 255}
triangleB = color.RGBA{120.0, 17.0, 0, 255}
)

114
game/game.go

@ -120,34 +120,16 @@ type Sprite struct { @@ -120,34 +120,16 @@ type Sprite struct {
premove bool
}
func (s *Sprite) Update() {
return // TODO
}
type Sprites struct {
sprites []*Sprite
num int
}
func (s *Sprites) Update() {
for i := 0; i < s.num; i++ {
s.sprites[i].Update()
}
}
const (
MinSprites = 0
MaxSprites = 50000
)
var spinner = []byte(`-\|/`)
type Game struct {
touchIDs []ebiten.TouchID
sprites Sprites
op *ebiten.DrawImageOptions
Board *board
var viewBoard bool // View board or lobby
type Game struct {
screenW, screenH int
drawBuffer bytes.Buffer
@ -166,6 +148,11 @@ type Game struct { @@ -166,6 +148,11 @@ type Game struct {
Client *fibs.Client
Board *board
lobby *lobby
pendingWho []*fibs.WhoInfo
runeBuffer []rune
inputBuffer string
@ -173,13 +160,11 @@ type Game struct { @@ -173,13 +160,11 @@ type Game struct {
keyboard *kibodo.Keyboard
shownKeyboard bool
op *ebiten.DrawImageOptions
}
func NewGame() *Game {
go func() {
// TODO fetch HTTP request, set debugExtra
}()
fibs.Debug = 1 // TODO
g := &Game{
@ -188,6 +173,8 @@ func NewGame() *Game { @@ -188,6 +173,8 @@ func NewGame() *Game {
},
Board: NewBoard(),
lobby: NewLobby(),
runeBuffer: make([]rune, 24),
keyboard: kibodo.NewKeyboard(),
@ -208,6 +195,17 @@ func NewGame() *Game { @@ -208,6 +195,17 @@ func NewGame() *Game {
func (g *Game) handleEvents() {
for e := range g.Client.Event {
switch event := e.(type) {
case *fibs.EventWho:
empty := len(g.lobby.who) == 0
if viewBoard || empty {
g.lobby.setWhoInfo(event.Who)
if empty {
ebiten.ScheduleFrame()
}
} else {
g.pendingWho = event.Who
}
case *fibs.EventBoardState:
g.Board.SetState(event.S, event.V)
case *fibs.EventMove:
@ -226,6 +224,7 @@ func (g *Game) Connect() { @@ -226,6 +224,7 @@ func (g *Game) Connect() {
address = defaultServerAddress
}
g.Client = fibs.NewClient(address, g.Username, g.Password)
g.lobby.c = g.Client
g.Board.Client = g.Client
go g.handleEvents()
@ -252,28 +251,6 @@ func (g *Game) Connect() { @@ -252,28 +251,6 @@ func (g *Game) Connect() {
}()
}
func (g *Game) leftTouched() bool {
for _, id := range g.touchIDs {
x, _ := ebiten.TouchPosition(id)
/*if x < screenWidth/2 {
return true
}*/
_ = x
}
return false
}
func (g *Game) rightTouched() bool {
for _, id := range g.touchIDs {
x, _ := ebiten.TouchPosition(id)
/*if x >= screenWidth/2 {
return true
}*/
_ = x
}
return false
}
// Separate update function for all normal update logic, as Update may only be
// called when there is user input when vsync is disabled.
func (g *Game) update() error {
@ -290,6 +267,10 @@ func (g *Game) Update() error { // Called by ebiten only when input occurs @@ -290,6 +267,10 @@ func (g *Game) Update() error { // Called by ebiten only when input occurs
g.Exit()
return nil
}
if g.pendingWho != nil && viewBoard {
g.lobby.setWhoInfo(g.pendingWho)
g.pendingWho = nil
}
err = g.keyboard.Update()
if err != nil {
@ -359,24 +340,6 @@ func (g *Game) Update() error { // Called by ebiten only when input occurs @@ -359,24 +340,6 @@ func (g *Game) Update() error { // Called by ebiten only when input occurs
f()
}
g.touchIDs = ebiten.AppendTouchIDs(g.touchIDs[:0])
// Decrease the number of the sprites.
if ebiten.IsKeyPressed(ebiten.KeyArrowLeft) || g.leftTouched() {
g.sprites.num -= 20
if g.sprites.num < MinSprites {
g.sprites.num = MinSprites
}
}
// Increase the number of the sprites.
if ebiten.IsKeyPressed(ebiten.KeyArrowRight) || g.rightTouched() {
g.sprites.num += 20
if MaxSprites < g.sprites.num {
g.sprites.num = MaxSprites
}
}
if inpututil.IsKeyJustPressed(ebiten.KeyD) {
g.Debug++
if g.Debug == 3 {
@ -385,9 +348,16 @@ func (g *Game) Update() error { // Called by ebiten only when input occurs @@ -385,9 +348,16 @@ func (g *Game) Update() error { // Called by ebiten only when input occurs
g.Board.debug = g.Debug
}
g.Board.update()
if inpututil.IsKeyJustPressed(ebiten.KeyEscape) {
viewBoard = !viewBoard
}
if !viewBoard {
g.lobby.update()
} else {
g.Board.update()
}
//g.sprites.Update()
return nil
}
@ -424,9 +394,13 @@ http://www.fibs.com/help.html#register` @@ -424,9 +394,13 @@ http://www.fibs.com/help.html#register`
return
}
// Game screen
g.Board.draw(screen)
if !viewBoard {
// Lobby screen
g.lobby.draw(screen)
} else {
// Game board screen
g.Board.draw(screen)
}
if g.Debug > 0 {
debugBox := image.NewRGBA(image.Rect(10, 20, 200, 200))
@ -469,6 +443,8 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { @@ -469,6 +443,8 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
}
g.screenW, g.screenH = outsideWidth, outsideHeight
g.lobby.setRect(0, 0, g.screenW, g.screenH)
g.Board.setRect(0, 0, g.screenW, g.screenH)
displayArea := 200

357
game/lobby.go

@ -0,0 +1,357 @@ @@ -0,0 +1,357 @@
package game
import (
"fmt"
"image/color"
"math"
"os"
"github.com/hajimehoshi/ebiten/v2/inpututil"
"code.rocketnine.space/tslocum/fibs"
"github.com/hajimehoshi/ebiten/v2"
"github.com/hajimehoshi/ebiten/v2/text"
)
type lobbyButton struct {
label string
f func()
}
var mainButtons = []*lobbyButton{
{"Invite...", func() {}},
{"Join", func() {}},
{"Watch", func() {}},
{"Quit", func() {}},
}
var inviteButtons = []*lobbyButton{
{"Send", func() {}},
{"- Point", func() {}},
{"+ Point", func() {}},
{"Cancel", func() {}},
}
type lobby struct {
x, y int
w, h int
padding float64
entryH float64
buttonBarHeight int
who []*fibs.WhoInfo
touchIDs []ebiten.TouchID
offset int
selected int
buffer *ebiten.Image
bufferDirty bool
op *ebiten.DrawImageOptions
c *fibs.Client
inviteUser *fibs.WhoInfo
invitePoints int
}
func NewLobby() *lobby {
l := &lobby{
op: &ebiten.DrawImageOptions{},
}
return l
}
func (l *lobby) setWhoInfo(who []*fibs.WhoInfo) {
l.who = who
l.bufferDirty = true
}
func (l *lobby) getButtons() []*lobbyButton {
if l.inviteUser != nil {
return inviteButtons
}
return mainButtons
}
// Draw to the off-screen buffer.
func (l *lobby) drawBuffer() {
l.buffer.Fill(frameColor)
// Draw invite user dialog
if l.inviteUser != nil {
labels := []string{
fmt.Sprintf("Invite %s to a %d point match.", l.inviteUser.Username, l.invitePoints),
"",
fmt.Sprintf(" Rating: %d", l.inviteUser.Rating),
fmt.Sprintf(" Experience: %d", l.inviteUser.Experience),
}
lineHeight := 30
padding := 24.0
for i, label := range labels {
bounds := text.BoundString(mplusNormalFont, label)
labelColor := triangleA
img := ebiten.NewImage(l.w-int(l.padding*2), int(l.entryH))
text.Draw(img, label, mplusNormalFont, 4, bounds.Dy(), labelColor)
l.op.GeoM.Reset()
l.op.GeoM.Translate(padding, padding+float64(i*lineHeight))
l.buffer.DrawImage(img, l.op)
}
} else {
var img *ebiten.Image
drawEntry := func(cx float64, cy float64, colA string, colB string, colC string, highlight bool) {
boundsA := text.BoundString(mplusNormalFont, colA)
boundsB := text.BoundString(mplusNormalFont, colB)
boundsC := text.BoundString(mplusNormalFont, colC)
y := (boundsA.Dy() + boundsB.Dy() + boundsC.Dy()) / 3 // TODO this isn't correct
labelColor := triangleA
if highlight {
labelColor = color.RGBA{200, 200, 60, 255}
}
selectedBorderColor := triangleB
img = ebiten.NewImage(l.w-int(l.padding*2), int(l.entryH))
if highlight {
for x := 0; x < l.w; x++ {
img.Set(x, 0, selectedBorderColor)
img.Set(x, int(l.entryH)-1, selectedBorderColor)
}
for by := 0; by < int(l.entryH)-1; by++ {
img.Set(0, by, selectedBorderColor)
img.Set(l.w-(int(l.padding)*2)-1, by, selectedBorderColor)
}
}
text.Draw(img, colA, mplusNormalFont, 4, y+2, labelColor)
text.Draw(img, colB, mplusNormalFont, int(250*ebiten.DeviceScaleFactor()), y+2, labelColor)
text.Draw(img, colC, mplusNormalFont, int(500*ebiten.DeviceScaleFactor()), y+2, labelColor)
l.op.GeoM.Reset()
l.op.GeoM.Translate(cx, cy)
l.buffer.DrawImage(img, l.op)
}
if len(l.who) == 0 {
drawEntry(l.padding, l.padding, "Loading...", "Please wait...", "Loading...", false)
return
}
for ly := -3; ly < -1; ly++ {
for lx := 0; lx < l.w-int(l.padding*2); lx++ {
l.buffer.Set(int(l.padding)+lx, int(l.padding)+int(l.entryH)+ly, triangleA)
}
}
cx, cy := 0.0, 0.0 // Cursor
drawEntry(cx+l.padding, cy+l.padding, "Username", "Rating (Experience)", "Status", false)
cy += l.entryH
i := 0
for _, who := range l.who {
if i >= l.offset {
details := fmt.Sprintf("%d (%d)", who.Rating, who.Experience)
status := "In the lobby"
if who.Opponent != "" {
status = fmt.Sprintf("Playing versus %s", who.Opponent)
}
drawEntry(cx+l.padding, cy+l.padding, who.Username, details, status, i == l.selected)
cy += l.entryH
}
i++
}
}
// Fill button bar
for ly := 0; ly < l.buttonBarHeight; ly++ {
for lx := 0; lx < l.w; lx++ {
l.buffer.Set(lx, l.h-ly, frameColor)
}
}
// Draw border
for ly := l.h - l.buttonBarHeight; ly < l.h-l.buttonBarHeight+2; ly++ {
for lx := 0; lx < l.w; lx++ {
l.buffer.Set(lx, ly, triangleA)
}
}
buttons := l.getButtons()
buttonWidth := l.w / len(buttons)
for i, button := range buttons {
// Draw border
if i > 0 {
for ly := l.h - l.buttonBarHeight; ly < l.h; ly++ {
for lx := buttonWidth * i; lx < (buttonWidth*i)+2; lx++ {
l.buffer.Set(lx, ly, triangleA)
}
}
}
bounds := text.BoundString(mplusNormalFont, button.label)
labelColor := triangleA
img := ebiten.NewImage(bounds.Dx()*2, bounds.Dy()*2)
text.Draw(img, button.label, mplusNormalFont, 0, bounds.Dy(), labelColor)
l.op.GeoM.Reset()
l.op.GeoM.Translate(float64(buttonWidth*i)+float64((buttonWidth-bounds.Dx())/2), float64(l.h-l.buttonBarHeight)+float64(l.buttonBarHeight-bounds.Dy())/2-float64(bounds.Dy()/2))
l.buffer.DrawImage(img, l.op)
}
}
// Draw to the screen.
func (l *lobby) draw(screen *ebiten.Image) {
if l.buffer == nil {
return
}
if l.bufferDirty {
l.drawBuffer()
l.bufferDirty = false
}
l.op.GeoM.Reset()
l.op.GeoM.Translate(float64(l.x), float64(l.y))
screen.DrawImage(l.buffer, l.op)
}
func (l *lobby) setRect(x, y, w, h int) {
if l.x == x && l.y == y && l.w == w && l.h == h {
return
}
if l.w != w || l.h != h {
l.buffer = ebiten.NewImage(w, h)
}
s := ebiten.DeviceScaleFactor()
l.padding = 4 * s
l.entryH = 32 * s
l.buttonBarHeight = int(200 * s)
l.x, l.y, l.w, l.h = x, y, w, h
l.bufferDirty = true
}
func (l *lobby) click(x, y int) {
inRect := l.x <= x && x <= l.x+l.w && l.y <= y && y <= l.y+l.h
if !inRect {
return
}
// Handle button click
if y >= l.h-l.buttonBarHeight {
if l.c == nil {
// Not yet connected
return
}
buttonWidth := l.w / len(l.getButtons())
buttonIndex := x / buttonWidth
if l.inviteUser != nil {
switch buttonIndex {
case 0:
l.c.Out <- []byte(fmt.Sprintf("invite %s %d", l.inviteUser.Username, l.invitePoints))
l.inviteUser = nil
l.bufferDirty = true
viewBoard = true
case 1:
l.invitePoints--
if l.invitePoints < 1 {
l.invitePoints = 1
}
l.bufferDirty = true
case 2:
l.invitePoints++
l.bufferDirty = true
case 3:
l.inviteUser = nil
l.bufferDirty = true
}
return
}
switch buttonIndex {
case 0:
l.inviteUser = l.who[l.selected]
l.invitePoints = 1
l.bufferDirty = true
case 1:
l.c.Out <- []byte(fmt.Sprintf("join %s", l.who[l.selected].Username))
viewBoard = true
case 2:
l.c.Out <- []byte(fmt.Sprintf("watch %s", l.who[l.selected].Username))
viewBoard = true
case 3:
os.Exit(0)
}
return
}
// Handle entry click
clickedEntry := (((y - int(l.padding)) - l.y) / int(l.entryH)) - 1
if clickedEntry >= 0 {
l.selected = l.offset + clickedEntry
l.bufferDirty = true
}
}
func (l *lobby) update() {
scrollLength := 2
if _, y := ebiten.Wheel(); y != 0 {
l.offset -= int(math.Ceil(y)) * scrollLength
l.bufferDirty = true
}
if inpututil.IsKeyJustPressed(ebiten.KeyDown) {
l.selected++
l.bufferDirty = true
}
if inpututil.IsKeyJustPressed(ebiten.KeyUp) {
l.selected--
l.bufferDirty = true
}
if inpututil.IsKeyJustPressed(ebiten.KeyPageDown) {
l.offset += scrollLength * 4
l.bufferDirty = true
}
if inpututil.IsKeyJustPressed(ebiten.KeyPageUp) {
l.offset -= scrollLength * 4
l.bufferDirty = true
}
if l.selected < 0 {
l.selected = 0
}
if l.offset < 0 {
l.offset = 0
}
if inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) {
x, y := ebiten.CursorPosition()
l.click(x, y)
}
l.touchIDs = inpututil.AppendJustPressedTouchIDs(l.touchIDs[:0])
for _, id := range l.touchIDs {
x, y := ebiten.TouchPosition(id)
l.click(x, y)
}
}

14
go.mod

@ -3,9 +3,9 @@ module code.rocketnine.space/tslocum/boxcars @@ -3,9 +3,9 @@ module code.rocketnine.space/tslocum/boxcars
go 1.17
require (
code.rocketnine.space/tslocum/fibs v0.0.0-20210914035810-391fe9721596
code.rocketnine.space/tslocum/kibodo v0.0.0-20210914054352-0aae5255ccec
github.com/hajimehoshi/ebiten/v2 v2.2.0-alpha.14.0.20210914160304-923c84a3d6ca
code.rocketnine.space/tslocum/fibs v0.0.0-20211001010223-882585bf240f
code.rocketnine.space/tslocum/kibodo v0.0.0-20210917002454-47a7751c7a48
github.com/hajimehoshi/ebiten/v2 v2.3.0-alpha.0.20210930150419-0b4bfd471fa9
github.com/llgcode/draw2d v0.0.0-20210904075650-80aa0a2a901d
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d
@ -15,15 +15,15 @@ require ( @@ -15,15 +15,15 @@ require (
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20210727001814-0db043d8d5be // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/jezek/xgb v0.0.0-20210312150743-0e0f116e1240 // indirect
github.com/klauspost/compress v1.13.5 // indirect
github.com/klauspost/compress v1.13.6 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/reiver/go-oi v1.0.0 // indirect
github.com/reiver/go-telnet v0.0.0-20180421082511-9ff0b2ab096e // indirect
golang.org/x/exp v0.0.0-20210910231120-3d0173ecaa1e // indirect
golang.org/x/mobile v0.0.0-20210902104108-5d9a33257ab5 // indirect
golang.org/x/exp v0.0.0-20210916165020-5cb4fee858ee // indirect
golang.org/x/mobile v0.0.0-20210924032853-1c027f395ef7 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 // indirect
golang.org/x/sys v0.0.0-20210930212924-f542c8878de8 // indirect
golang.org/x/text v0.3.7 // indirect
nhooyr.io/websocket v1.8.7 // indirect
)

40
go.sum

@ -1,9 +1,9 @@ @@ -1,9 +1,9 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
code.rocketnine.space/tslocum/fibs v0.0.0-20210914035810-391fe9721596 h1:phymPJwH4udif7tuvbric4zrdlZgRLV8Vrcd0GkDNZ4=
code.rocketnine.space/tslocum/fibs v0.0.0-20210914035810-391fe9721596/go.mod h1:f7Cz0zJWOnJ9DW7R/GTuE8z5XWQtkbXkKpksW9SDu2c=
code.rocketnine.space/tslocum/kibodo v0.0.0-20210914054352-0aae5255ccec h1:J+rI9MFq6A/b17ia27avsJkiYzFMKCWoNeqnW2j0O9A=
code.rocketnine.space/tslocum/kibodo v0.0.0-20210914054352-0aae5255ccec/go.mod h1:aj6xi25Ett7ECA5EdLm/0Ttr5WCk9vzrTPScURMJfq8=
code.rocketnine.space/tslocum/fibs v0.0.0-20211001010223-882585bf240f h1:EOB1YJ+7ormKLI/hLweoodN7vqTcEPaCkQfOSQV0ol4=
code.rocketnine.space/tslocum/fibs v0.0.0-20211001010223-882585bf240f/go.mod h1:f7Cz0zJWOnJ9DW7R/GTuE8z5XWQtkbXkKpksW9SDu2c=
code.rocketnine.space/tslocum/kibodo v0.0.0-20210917002454-47a7751c7a48 h1:iF8WUiUnqJ30k9RgReFSZL2tU+uFhr5Sgld1QqS0rnA=
code.rocketnine.space/tslocum/kibodo v0.0.0-20210917002454-47a7751c7a48/go.mod h1:Zd/62u2hSH/wmV//dOi8VhEj31a4IA3c62vGPw/8gZw=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20201218220906-28db891af037/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
@ -131,14 +131,15 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf @@ -131,14 +131,15 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
github.com/hajimehoshi/bitmapfont/v2 v2.1.3 h1:JefUkL0M4nrdVwVq7MMZxSTh6mSxOylm+C4Anoucbb0=
github.com/hajimehoshi/bitmapfont/v2 v2.1.3/go.mod h1:2BnYrkTQGThpr/CY6LorYtt/zEPNzvE/ND69CRTaHMs=
github.com/hajimehoshi/ebiten/v2 v2.2.0-alpha.13.0.20210909171729-37771717cc52/go.mod h1:44O6eBPGyRv8YctRbfzaqUH2sek5UdXh0aLWOP02ELI=
github.com/hajimehoshi/ebiten/v2 v2.2.0-alpha.14.0.20210914160304-923c84a3d6ca h1:O2pG5L34GaUq+aAc/QVvetVlRPGTX2UrMB7fI4wsqRc=
github.com/hajimehoshi/ebiten/v2 v2.2.0-alpha.14.0.20210914160304-923c84a3d6ca/go.mod h1:fS7PLZeV3mclX0J6qubENa9ms3NWmZdNJkCOeEHmF74=
github.com/hajimehoshi/ebiten/v2 v2.2.0-alpha.14.0.20210916141036-9c321d1fcf27/go.mod h1:2sY8DHIXNs0Lf/pyTZXltEQtqCKZ2HyXbeUWzrLTlg0=
github.com/hajimehoshi/ebiten/v2 v2.3.0-alpha.0.20210930150419-0b4bfd471fa9 h1:UP1Z1UozXrJeTSbMWzmcJ0jWK0PzNOhmrjFMbGg+980=
github.com/hajimehoshi/ebiten/v2 v2.3.0-alpha.0.20210930150419-0b4bfd471fa9/go.mod h1:olKl/qqhMBBAm2oI7Zy292nCtE+nitlmYKNF3UpbFn0=
github.com/hajimehoshi/file2byteslice v0.0.0-20200812174855-0e5e8a80490e/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE=
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE=
github.com/hajimehoshi/go-mp3 v0.3.2/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
github.com/hajimehoshi/oto/v2 v2.0.0-alpha.2/go.mod h1:rUKQmwMkqmRxe+IAof9+tuYA2ofm8cAWXFmSfzDN8vQ=
github.com/hajimehoshi/oto/v2 v2.1.0-alpha.0.20210912073017-18657977e3dc/go.mod h1:rUKQmwMkqmRxe+IAof9+tuYA2ofm8cAWXFmSfzDN8vQ=
github.com/hajimehoshi/oto/v2 v2.1.0-alpha.1/go.mod h1:rUKQmwMkqmRxe+IAof9+tuYA2ofm8cAWXFmSfzDN8vQ=
github.com/hajimehoshi/oto/v2 v2.1.0-alpha.2/go.mod h1:rUKQmwMkqmRxe+IAof9+tuYA2ofm8cAWXFmSfzDN8vQ=
github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
@ -181,8 +182,9 @@ github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+ @@ -181,8 +182,9 @@ github.com/jung-kurt/gofpdf v1.0.0/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+
github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.5 h1:9O69jUPDcsT9fEm74W92rZL9FQY7rCdaXVneq+yyzl4=
github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
@ -314,6 +316,7 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX @@ -314,6 +316,7 @@ github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtX
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
@ -346,8 +349,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh @@ -346,8 +349,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/exp v0.0.0-20210910231120-3d0173ecaa1e h1:W9ijN+u/MsYtKK8c9OVJM3Wc3GyrQO2hlRdbrwyzJMc=
golang.org/x/exp v0.0.0-20210910231120-3d0173ecaa1e/go.mod h1:a3o/VtDNHN+dCVLEpzjjUHOzR+Ln3DHX056ZPzoZGGA=
golang.org/x/exp v0.0.0-20210916165020-5cb4fee858ee h1:qlrAyYdKz4o7rWVUjiKqQJMa4PEpd55fqBU8jpsl4Iw=
golang.org/x/exp v0.0.0-20210916165020-5cb4fee858ee/go.mod h1:a3o/VtDNHN+dCVLEpzjjUHOzR+Ln3DHX056ZPzoZGGA=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@ -362,8 +365,9 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl @@ -362,8 +365,9 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20201217150744-e6ae53a27f4f/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
golang.org/x/mobile v0.0.0-20210902104108-5d9a33257ab5 h1:peBP2oZO/xVnGMaWMCyFEI0WENsGj71wx5K12mRELHQ=
golang.org/x/mobile v0.0.0-20210902104108-5d9a33257ab5/go.mod h1:c4YKU3ZylDmvbw+H/PSvm42vhdWbuxCzbonauEAP9B8=
golang.org/x/mobile v0.0.0-20210924032853-1c027f395ef7 h1:CyFUjc175y/mbMjxe+WdqI72jguLyjQChKCDe9mfTvg=
golang.org/x/mobile v0.0.0-20210924032853-1c027f395ef7/go.mod h1:c4YKU3ZylDmvbw+H/PSvm42vhdWbuxCzbonauEAP9B8=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
@ -389,6 +393,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL @@ -389,6 +393,7 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@ -423,10 +428,14 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w @@ -423,10 +428,14 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210820121016-41cdb8703e55/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0 h1:xrCZDmdtoloIiooiA9q0OQb9r8HejIHYoHGhGCe1pGg=
golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210930212924-f542c8878de8 h1:g54bVHzt/eKaj59LDwiDyLRXbOdJSfwRxA1WYEJx/Yo=
golang.org/x/sys v0.0.0-20210930212924-f542c8878de8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@ -454,6 +463,7 @@ golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapK @@ -454,6 +463,7 @@ golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

15
main.go

@ -7,7 +7,6 @@ import ( @@ -7,7 +7,6 @@ import (
"os"
"os/signal"
"syscall"
"time"
"code.rocketnine.space/tslocum/boxcars/game"
"github.com/hajimehoshi/ebiten/v2"
@ -25,8 +24,8 @@ func main() { @@ -25,8 +24,8 @@ func main() {
ebiten.SetWindowSize(screenWidth, screenHeight)
ebiten.SetWindowResizable(true)
ebiten.SetFPSMode(ebiten.FPSModeVsyncOffMinimum)
ebiten.SetMaxTPS(60) // TODO allow users to set custom value
ebiten.SetRunnableOnUnfocused(true) // Note - this currently does nothing in ebiten
ebiten.SetMaxTPS(60)
ebiten.SetRunnableOnUnfocused(true)
ebiten.SetWindowClosingHandled(true)
fullscreenWidth, fullscreenHeight := ebiten.ScreenSizeInFullscreen()
@ -55,16 +54,6 @@ func main() { @@ -55,16 +54,6 @@ func main() {
go func() {
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
// TODO temporary
if string(scanner.Bytes()) == "/board" {
g.Client.Out <- []byte("set boardstyle 2")
time.Sleep(time.Second / 2)
g.Client.Out <- []byte("board")
time.Sleep(time.Second / 2)
g.Client.Out <- []byte("set boardstyle 3")
continue
}
g.Client.Out <- append(scanner.Bytes())
}
}()

Loading…
Cancel
Save