Add indicator showing where to drag when bearing off

This commit is contained in:
Trevor Slocum 2023-10-30 21:15:44 -07:00
parent 272cf442df
commit c888fbff06
6 changed files with 119 additions and 87 deletions

View file

@ -1,4 +1,5 @@
1.0.6:
- Add indicator showing where to drag when bearing off
- Optimize drawing board
1.0.5:

View file

@ -76,6 +76,8 @@ type board struct {
uiGrid *etk.Grid
frame *etk.Frame
bearOffOverlay *etk.Button
leaveGameGrid *etk.Grid
confirmLeaveGameFrame *etk.Frame
@ -111,6 +113,11 @@ func NewBoard() *board {
}
b.fontUpdated()
b.bearOffOverlay = etk.NewButton(fmt.Sprintf("%s", gotext.Get("Drag here to bear off")), func() error {
return nil
})
b.bearOffOverlay.SetVisible(false)
{
leaveGameLabel := etk.NewText(gotext.Get("Leave match?"))
leaveGameLabel.SetHorizontal(messeji.AlignCenter)
@ -133,6 +140,7 @@ func NewBoard() *board {
b.uiGrid.AddChildAt(b.inputGrid, 0, 4, 1, 1)
b.frame.AddChild(b.uiGrid)
b.frame.AddChild(b.bearOffOverlay)
b.frame.AddChild(b.leaveGameGrid)
b.buttons = []*boardButton{
@ -458,6 +466,76 @@ func (b *board) drawButtons(screen *ebiten.Image) {
}
}
func (b *board) drawSprite(target *ebiten.Image, sprite *Sprite) {
x, y := float64(sprite.x), float64(sprite.y)
if !sprite.toStart.IsZero() {
progress := float64(time.Since(sprite.toStart)) / float64(sprite.toTime)
if x == float64(sprite.toX) && y == float64(sprite.toY) {
sprite.toStart = time.Time{}
sprite.x = sprite.toX
sprite.y = sprite.toY
} else {
if x < float64(sprite.toX) {
x += (float64(sprite.toX) - x) * progress
if x > float64(sprite.toX) {
x = float64(sprite.toX)
}
} else if x > float64(sprite.toX) {
x -= (x - float64(sprite.toX)) * progress
if x < float64(sprite.toX) {
x = float64(sprite.toX)
}
}
if y < float64(sprite.toY) {
y += (float64(sprite.toY) - y) * progress
if y > float64(sprite.toY) {
y = float64(sprite.toY)
}
} else if y > float64(sprite.toY) {
y -= (y - float64(sprite.toY)) * progress
if y < float64(sprite.toY) {
y = float64(sprite.toY)
}
}
}
// Schedule another frame
scheduleFrame()
}
// Draw shadow.
{
op := &ebiten.DrawImageOptions{}
op.Filter = ebiten.FilterLinear
op.GeoM.Translate(x, y)
op.ColorScale.Scale(0, 0, 0, 1)
target.DrawImage(imgCheckerLight, op)
}
// Draw checker.
checkerScale := 0.94
op := &ebiten.DrawImageOptions{}
op.Filter = ebiten.FilterLinear
op.GeoM.Translate(-b.spaceWidth/2, -b.spaceWidth/2)
op.GeoM.Scale(checkerScale, checkerScale)
op.GeoM.Translate((b.spaceWidth/2)+x, (b.spaceWidth/2)+y)
c := lightCheckerColor
if !sprite.colorWhite {
c = darkCheckerColor
}
op.ColorScale.Scale(0, 0, 0, 1)
r := float32(c.R) / 0xff
g := float32(c.G) / 0xff
bl := float32(c.B) / 0xff
op.ColorScale.SetR(r)
op.ColorScale.SetG(g)
op.ColorScale.SetB(bl)
target.DrawImage(imgCheckerLight, op)
}
func (b *board) Draw(screen *ebiten.Image) {
{
op := &ebiten.DrawImageOptions{}
@ -465,77 +543,6 @@ func (b *board) Draw(screen *ebiten.Image) {
screen.DrawImage(b.backgroundImage, op)
}
drawSprite := func(sprite *Sprite) {
x, y := float64(sprite.x), float64(sprite.y)
if !sprite.toStart.IsZero() {
progress := float64(time.Since(sprite.toStart)) / float64(sprite.toTime)
if x == float64(sprite.toX) && y == float64(sprite.toY) {
sprite.toStart = time.Time{}
sprite.x = sprite.toX
sprite.y = sprite.toY
} else {
if x < float64(sprite.toX) {
x += (float64(sprite.toX) - x) * progress
if x > float64(sprite.toX) {
x = float64(sprite.toX)
}
} else if x > float64(sprite.toX) {
x -= (x - float64(sprite.toX)) * progress
if x < float64(sprite.toX) {
x = float64(sprite.toX)
}
}
if y < float64(sprite.toY) {
y += (float64(sprite.toY) - y) * progress
if y > float64(sprite.toY) {
y = float64(sprite.toY)
}
} else if y > float64(sprite.toY) {
y -= (y - float64(sprite.toY)) * progress
if y < float64(sprite.toY) {
y = float64(sprite.toY)
}
}
}
// Schedule another frame
scheduleFrame()
}
// Draw shadow.
{
op := &ebiten.DrawImageOptions{}
op.Filter = ebiten.FilterLinear
op.GeoM.Translate(x, y)
op.ColorScale.Scale(0, 0, 0, 1)
screen.DrawImage(imgCheckerLight, op)
}
// Draw checker.
checkerScale := 0.94
op := &ebiten.DrawImageOptions{}
op.Filter = ebiten.FilterLinear
op.GeoM.Translate(-b.spaceWidth/2, -b.spaceWidth/2)
op.GeoM.Scale(checkerScale, checkerScale)
op.GeoM.Translate((b.spaceWidth/2)+x, (b.spaceWidth/2)+y)
c := lightCheckerColor
if !sprite.colorWhite {
c = darkCheckerColor
}
op.ColorScale.Scale(0, 0, 0, 1)
r := float32(c.R) / 0xff
g := float32(c.G) / 0xff
bl := float32(c.B) / 0xff
op.ColorScale.SetR(r)
op.ColorScale.SetG(g)
op.ColorScale.SetB(bl)
screen.DrawImage(imgCheckerLight, op)
}
for space := 0; space < bgammon.BoardSpaces; space++ {
var numPieces int
for i, sprite := range b.spaceSprites[space] {
@ -544,7 +551,7 @@ func (b *board) Draw(screen *ebiten.Image) {
}
numPieces++
drawSprite(sprite)
b.drawSprite(screen, sprite)
var overlayText string
if i > 5 {
@ -729,19 +736,16 @@ func (b *board) Draw(screen *ebiten.Image) {
}
}
// Draw moving sprite
if b.moving != nil {
drawSprite(b.moving)
}
// Draw dragged sprite
if b.dragging != nil {
drawSprite(b.dragging)
}
b.drawButtons(screen)
}
func (b *board) drawDraggedChecker(screen *ebiten.Image) {
if b.dragging == nil {
return
}
b.drawSprite(screen, b.dragging)
}
func (b *board) updateButtonRects() {
btnRoll := b.buttons[0]
btnReset := b.buttons[1]
@ -1172,6 +1176,13 @@ func (b *board) handleClick(x int, y int) bool {
return false
}
func (b *board) startDrag(s *Sprite) {
b.dragging = s
if bgammon.CanBearOff(b.gameState.Board, b.gameState.PlayerNumber, true) && b.gameState.Board[bgammon.SpaceHomePlayer] == 0 {
b.bearOffOverlay.SetVisible(true)
}
}
func (b *board) Update() {
if b.Client == nil {
return
@ -1196,7 +1207,7 @@ func (b *board) Update() {
if b.playerTurn() && inpututil.IsMouseButtonJustPressed(ebiten.MouseButtonLeft) && !handled && len(b.gameState.Available) > 0 {
s := b.spriteAt(cx, cy)
if s != nil && s.colorWhite == (b.gameState.PlayerNumber == 2) {
b.dragging = s
b.startDrag(s)
}
}
@ -1210,7 +1221,7 @@ func (b *board) Update() {
s := b.spriteAt(x, y)
if s != nil && s.colorWhite == (b.gameState.PlayerNumber == 2) {
b.dragging = s
b.startDrag(s)
b.dragTouchId = id
}
}
@ -1233,10 +1244,12 @@ func (b *board) Update() {
if inpututil.IsMouseButtonJustReleased(ebiten.MouseButtonLeft) {
dropped = b.dragging
b.dragging = nil
b.bearOffOverlay.SetVisible(false)
}
} else if inpututil.IsTouchJustReleased(b.dragTouchId) {
dropped = b.dragging
b.dragging = nil
b.bearOffOverlay.SetVisible(false)
}
if dropped != nil {
index := b.spaceAt(x, y)

View file

@ -451,6 +451,7 @@ func setViewBoard(view bool) {
etk.SetFocus(inputBuffer)
game.Board.uiGrid.SetRect(game.Board.uiGrid.Rect())
game.Board.bearOffOverlay.SetRect(game.Board.bearOffOverlay.Rect())
} else {
if !game.loggedIn {
game.setRoot(connectGrid)
@ -1244,6 +1245,8 @@ func (g *Game) Draw(screen *ebiten.Image) {
log.Fatal(err)
}
g.Board.drawDraggedChecker(screen)
game.keyboard.Draw(screen)
if Debug > 0 {
@ -1337,6 +1340,12 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
bufferPaddingX := int(g.Board.horizontalBorderSize / 2)
g.Board.uiGrid.SetRect(image.Rect(bufferPaddingX, g.Board.h+bufferPaddingX, g.screenW-bufferPaddingX, g.screenH-bufferPaddingX))
w := g.screenW / 2
h := (g.screenH - g.Board.h) / 2
x := w / 2
y := g.Board.h + h/2
g.Board.bearOffOverlay.SetRect(image.Rect(x, y, x+w, y+h))
g.lobby.fullscreen = true
g.lobby.setRect(0, 0, g.screenW, g.screenH-lobbyStatusBufferHeight)
} else { // Landscape view.
@ -1361,6 +1370,12 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
bufferPaddingX := int(g.Board.horizontalBorderSize / 2)
g.Board.uiGrid.SetRect(image.Rect(g.Board.w+bufferPaddingX, bufferPaddingX, g.screenW-bufferPaddingX, g.screenH-bufferPaddingX))
w := (g.screenW - bufferPaddingX - g.Board.w) / 2
h := (g.screenH) / 4
x := g.Board.w + bufferPaddingX + w/2
y := g.screenH/2 - h/2
g.Board.bearOffOverlay.SetRect(image.Rect(x, y, x+w, y+h))
g.lobby.fullscreen = true
g.lobby.setRect(0, 0, g.screenW, g.screenH-lobbyStatusBufferHeight)
}

View file

@ -37,6 +37,9 @@ msgstr ""
msgid "Double"
msgstr ""
msgid "Drag here to bear off"
msgstr ""
msgid "Failed to join match: %s"
msgstr ""

2
go.mod
View file

@ -3,7 +3,7 @@ module code.rocket9labs.com/tslocum/boxcars
go 1.17
require (
code.rocket9labs.com/tslocum/bgammon v0.0.0-20231027191341-991fd6d481ca
code.rocket9labs.com/tslocum/bgammon v0.0.0-20231031041258-b89776c323ab
code.rocket9labs.com/tslocum/etk v0.0.0-20231029060740-36965d0b795c
code.rocketnine.space/tslocum/kibodo v1.0.2-0.20231024233002-77bb43ba6fe8
code.rocketnine.space/tslocum/messeji v1.0.5-0.20231028192343-ebfed687fb71

4
go.sum
View file

@ -1,5 +1,5 @@
code.rocket9labs.com/tslocum/bgammon v0.0.0-20231027191341-991fd6d481ca h1:JClRU4ONLpMiyW/BoI3O8Sb9yiYcySTZjcUfQ48GWvw=
code.rocket9labs.com/tslocum/bgammon v0.0.0-20231027191341-991fd6d481ca/go.mod h1:U8qo60VHGzKFUHLZZJcvT0yDzwWybJBabsCw3Lyqx4s=
code.rocket9labs.com/tslocum/bgammon v0.0.0-20231031041258-b89776c323ab h1:FH0ZI82dOOFv34Ywwxy2TDN34/MIs1dDEu4VI1tokTQ=
code.rocket9labs.com/tslocum/bgammon v0.0.0-20231031041258-b89776c323ab/go.mod h1:U8qo60VHGzKFUHLZZJcvT0yDzwWybJBabsCw3Lyqx4s=
code.rocket9labs.com/tslocum/etk v0.0.0-20231029060740-36965d0b795c h1:tupDtvsfZAGs9aruB5z4d+PesDFAZ7W2Q9+HQc/s3kk=
code.rocket9labs.com/tslocum/etk v0.0.0-20231029060740-36965d0b795c/go.mod h1:C+pdWMPmOOPGk6adunX6PxE40F8CSg0h8LLwWIO2qeM=
code.rocketnine.space/tslocum/kibodo v1.0.2-0.20231024233002-77bb43ba6fe8 h1:i1NzTMQA1DAAUIpFh2bnHVnH5j9hUkG6F3tqzsdD16Y=