parent
539f35bf53
commit
626d1d088b
8 changed files with 128 additions and 93 deletions
|
@ -1,3 +1,6 @@
|
|||
1.2.7:
|
||||
- Draw checkers in home spaces sideways
|
||||
|
||||
1.2.6:
|
||||
- Add rating column to list of matches
|
||||
- Add rating information to history screen
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 8.2 KiB |
BIN
game/asset/image/checker_side.png
Normal file
BIN
game/asset/image/checker_side.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
191
game/board.go
191
game/board.go
|
@ -1269,7 +1269,7 @@ func (b *board) toggleAdvancedMovementCheckbox() error {
|
|||
func (b *board) newSprite(white bool) *Sprite {
|
||||
s := &Sprite{}
|
||||
s.colorWhite = white
|
||||
s.w, s.h = imgCheckerLight.Bounds().Dx(), imgCheckerLight.Bounds().Dy()
|
||||
s.w, s.h = imgCheckerTop.Bounds().Dx(), imgCheckerTop.Bounds().Dy()
|
||||
return s
|
||||
}
|
||||
|
||||
|
@ -1464,6 +1464,46 @@ func (b *board) updateBackgroundImage() {
|
|||
}
|
||||
}
|
||||
|
||||
func (b *board) drawChecker(target *ebiten.Image, checker *ebiten.Image, x float64, y float64, white bool, side bool) {
|
||||
// Draw shadow.
|
||||
if !side {
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.Filter = ebiten.FilterLinear
|
||||
op.GeoM.Translate(x, y)
|
||||
op.ColorScale.Scale(0, 0, 0, 1)
|
||||
target.DrawImage(checker, op)
|
||||
}
|
||||
|
||||
// Draw checker.
|
||||
|
||||
checkerScale := 0.94
|
||||
|
||||
height := b.spaceWidth
|
||||
if side {
|
||||
height = 80
|
||||
}
|
||||
|
||||
op := &ebiten.DrawImageOptions{}
|
||||
op.Filter = ebiten.FilterLinear
|
||||
op.GeoM.Translate(-b.spaceWidth/2, -height/2)
|
||||
op.GeoM.Scale(checkerScale, checkerScale)
|
||||
op.GeoM.Translate((b.spaceWidth/2)+x, (height/2)+y)
|
||||
|
||||
c := lightCheckerColor
|
||||
if !white {
|
||||
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(checker, op)
|
||||
}
|
||||
|
||||
func (b *board) drawSprite(target *ebiten.Image, sprite *Sprite) {
|
||||
x, y := float64(sprite.x), float64(sprite.y)
|
||||
if sprite == b.dragging {
|
||||
|
@ -1507,39 +1547,7 @@ func (b *board) drawSprite(target *ebiten.Image, sprite *Sprite) {
|
|||
// 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)
|
||||
b.drawChecker(target, imgCheckerTop, x, y, sprite.colorWhite, false)
|
||||
}
|
||||
|
||||
func (b *board) innerBoardCenter(right bool) int {
|
||||
|
@ -1557,6 +1565,9 @@ func (b *board) Draw(screen *ebiten.Image) {
|
|||
}
|
||||
|
||||
for space := int8(0); space < bgammon.BoardSpaces; space++ {
|
||||
if space == bgammon.SpaceHomePlayer || space == bgammon.SpaceHomeOpponent {
|
||||
continue
|
||||
}
|
||||
var numPieces int8
|
||||
for i, sprite := range b.spaceSprites[space] {
|
||||
if sprite == b.dragging || sprite == b.moving {
|
||||
|
@ -1602,6 +1613,21 @@ func (b *board) Draw(screen *ebiten.Image) {
|
|||
}
|
||||
}
|
||||
|
||||
r := b.spaceRects[bgammon.SpaceHomePlayer]
|
||||
checkerY := float64(b.y+int(b.verticalBorderSize)+r[1]+r[3]) + 3
|
||||
checkerHeight := (b.spaceWidth + b.overlapSize*4) / 15
|
||||
checkers := len(b.spaceSprites[bgammon.SpaceHomePlayer])
|
||||
for i := 0; i < checkers; i++ {
|
||||
b.drawChecker(screen, imgCheckerSide, float64(b.x+int(b.horizontalBorderSize)+r[0]), float64(checkerY-checkerHeight*float64(i+1)), b.flipBoard, true)
|
||||
}
|
||||
|
||||
r = b.spaceRects[bgammon.SpaceHomeOpponent]
|
||||
checkerY = float64(b.y+int(b.verticalBorderSize)+int(b.spaceWidth)+int(b.overlapSize*4)) + 1
|
||||
checkers = len(b.spaceSprites[bgammon.SpaceHomeOpponent])
|
||||
for i := 0; i < checkers; i++ {
|
||||
b.drawChecker(screen, imgCheckerSide, float64(b.x+int(b.horizontalBorderSize)+r[0]), float64(checkerY-checkerHeight*float64(i+1)), !b.flipBoard, true)
|
||||
}
|
||||
|
||||
b.stateLock.Lock()
|
||||
var highlightSpaces [][]int8
|
||||
dragging := b.dragging
|
||||
|
@ -1836,7 +1862,7 @@ func (b *board) setRect(x, y, w, h int) {
|
|||
|
||||
for i := 0; i < b.Sprites.num; i++ {
|
||||
s := b.Sprites.sprites[i]
|
||||
s.w, s.h = imgCheckerLight.Bounds().Dx(), imgCheckerLight.Bounds().Dy()
|
||||
s.w, s.h = imgCheckerTop.Bounds().Dx(), imgCheckerTop.Bounds().Dy()
|
||||
}
|
||||
|
||||
b.setSpaceRects()
|
||||
|
@ -2250,6 +2276,10 @@ func (b *board) processState() {
|
|||
b.stateLock.Lock()
|
||||
defer b.stateLock.Unlock()
|
||||
|
||||
if b.dragging != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if b.lastPlayerNumber != b.gameState.PlayerNumber || b.lastVariant != b.gameState.Variant {
|
||||
b.setSpaceRects()
|
||||
b.updateBackgroundImage()
|
||||
|
@ -2540,6 +2570,13 @@ func (b *board) _movePiece(sprite *Sprite, from int8, to int8, speed int8, pause
|
|||
|
||||
space := to // Immediately go to target space
|
||||
|
||||
for i, s := range b.spaceSprites[from] {
|
||||
if s == sprite {
|
||||
b.spaceSprites[from] = append(b.spaceSprites[from][:i], b.spaceSprites[from][i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
stack := len(b.spaceSprites[space])
|
||||
if stack == 1 && sprite.colorWhite != b.spaceSprites[space][0].colorWhite {
|
||||
stack = 0 // Hit
|
||||
|
@ -2566,12 +2603,6 @@ func (b *board) _movePiece(sprite *Sprite, from int8, to int8, speed int8, pause
|
|||
sprite.toStart = time.Time{}
|
||||
|
||||
b.spaceSprites[to] = append(b.spaceSprites[to], sprite)
|
||||
for i, s := range b.spaceSprites[from] {
|
||||
if s == sprite {
|
||||
b.spaceSprites[from] = append(b.spaceSprites[from][:i], b.spaceSprites[from][i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
b.moving = nil
|
||||
|
||||
if pauseTime == 0 {
|
||||
|
@ -2621,6 +2652,16 @@ func (b *board) playerTurn() bool {
|
|||
|
||||
func (b *board) startDrag(s *Sprite, space int8, click bool) {
|
||||
b.dragging = s
|
||||
|
||||
if space >= 0 && space < bgammon.BoardSpaces {
|
||||
for i, sprite := range b.spaceSprites[space] {
|
||||
if s == sprite {
|
||||
b.spaceSprites[space] = append(b.spaceSprites[space][:i], b.spaceSprites[space][i+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b.draggingSpace = space
|
||||
b.draggingClick = click
|
||||
b.lastDragClick = time.Now()
|
||||
|
@ -2679,45 +2720,37 @@ func (b *board) finishDrag(x int, y int, click bool) {
|
|||
|
||||
var processed bool
|
||||
if index >= 0 && b.Client != nil {
|
||||
ADDPREMOVE:
|
||||
for sp, pieces := range b.spaceSprites {
|
||||
space := int8(sp)
|
||||
for _, piece := range pieces {
|
||||
if piece == dropped {
|
||||
if space != index {
|
||||
playSoundEffect(effectMove)
|
||||
b.gameState.AddLocalMove([]int8{space, index})
|
||||
b.processState()
|
||||
scheduleFrame()
|
||||
processed = true
|
||||
b.Client.Out <- []byte(fmt.Sprintf("mv %d/%d", space, index))
|
||||
} else if time.Since(b.lastDragClick) < 500*time.Millisecond && b.gameState.MayBearOff(b.gameState.PlayerNumber, true) {
|
||||
homeStart, homeEnd := bgammon.HomeRange(b.gameState.PlayerNumber, b.gameState.Variant)
|
||||
if homeEnd < homeStart {
|
||||
homeStart, homeEnd = homeEnd, homeStart
|
||||
}
|
||||
if index >= homeStart && index <= homeEnd {
|
||||
b.Client.Out <- []byte(fmt.Sprintf("mv %d/off", index))
|
||||
}
|
||||
} else if time.Since(b.lastDragClick) < 500*time.Millisecond && space == bgammon.SpaceHomePlayer && !b.gameState.Player1.Entered {
|
||||
var found bool
|
||||
for _, m := range b.gameState.Available {
|
||||
if m[0] == bgammon.SpaceHomePlayer && bgammon.SpaceDiff(m[0], m[1], b.gameState.Variant) == b.gameState.Roll1 {
|
||||
b.Client.Out <- []byte(fmt.Sprintf("mv %d/%d", m[0], m[1]))
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
for _, m := range b.gameState.Available {
|
||||
if m[0] == bgammon.SpaceHomePlayer {
|
||||
b.Client.Out <- []byte(fmt.Sprintf("mv %d/%d", m[0], m[1]))
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
space := b.draggingSpace
|
||||
if space != index {
|
||||
playSoundEffect(effectMove)
|
||||
b.gameState.AddLocalMove([]int8{space, index})
|
||||
b.processState()
|
||||
scheduleFrame()
|
||||
processed = true
|
||||
b.Client.Out <- []byte(fmt.Sprintf("mv %d/%d", space, index))
|
||||
} else if time.Since(b.lastDragClick) < 500*time.Millisecond && b.gameState.MayBearOff(b.gameState.PlayerNumber, true) {
|
||||
homeStart, homeEnd := bgammon.HomeRange(b.gameState.PlayerNumber, b.gameState.Variant)
|
||||
if homeEnd < homeStart {
|
||||
homeStart, homeEnd = homeEnd, homeStart
|
||||
}
|
||||
if index >= homeStart && index <= homeEnd {
|
||||
b.Client.Out <- []byte(fmt.Sprintf("mv %d/off", index))
|
||||
}
|
||||
} else if time.Since(b.lastDragClick) < 500*time.Millisecond && space == bgammon.SpaceHomePlayer && !b.gameState.Player1.Entered {
|
||||
var found bool
|
||||
for _, m := range b.gameState.Available {
|
||||
if m[0] == bgammon.SpaceHomePlayer && bgammon.SpaceDiff(m[0], m[1], b.gameState.Variant) == b.gameState.Roll1 {
|
||||
b.Client.Out <- []byte(fmt.Sprintf("mv %d/%d", m[0], m[1]))
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
for _, m := range b.gameState.Available {
|
||||
if m[0] == bgammon.SpaceHomePlayer {
|
||||
b.Client.Out <- []byte(fmt.Sprintf("mv %d/%d", m[0], m[1]))
|
||||
break
|
||||
}
|
||||
break ADDPREMOVE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,8 +57,8 @@ var assetFS embed.FS
|
|||
var debugExtra []byte
|
||||
|
||||
var (
|
||||
imgCheckerLight *ebiten.Image
|
||||
//imgCheckerDark *ebiten.Image
|
||||
imgCheckerTop *ebiten.Image
|
||||
imgCheckerSide *ebiten.Image
|
||||
|
||||
imgDice *ebiten.Image
|
||||
imgDice1 *ebiten.Image
|
||||
|
@ -223,9 +223,8 @@ func loadImageAssets(width int) {
|
|||
}
|
||||
loadedCheckerWidth = width
|
||||
|
||||
imgCheckerLight = loadAsset("asset/image/checker_white.png", width)
|
||||
//imgCheckerDark = loadAsset("asset/image/checker_white.png", width)
|
||||
//imgCheckerDark = loadAsset("assets/checker_black.png", width)
|
||||
imgCheckerTop = loadAsset("asset/image/checker_top.png", width)
|
||||
imgCheckerSide = loadAsset("asset/image/checker_side.png", width)
|
||||
|
||||
resizeDice := func(img image.Image) *ebiten.Image {
|
||||
if game == nil {
|
||||
|
|
6
go.mod
6
go.mod
|
@ -4,8 +4,8 @@ go 1.17
|
|||
|
||||
require (
|
||||
code.rocket9labs.com/tslocum/bgammon v0.0.0-20240117214045-3607efee4129
|
||||
code.rocket9labs.com/tslocum/bgammon-tabula-bot v0.0.0-20240118194149-d51931e431f7
|
||||
code.rocket9labs.com/tslocum/etk v0.0.0-20240118083053-9eecc7a44b04
|
||||
code.rocket9labs.com/tslocum/bgammon-tabula-bot v0.0.0-20240120044556-60982417c592
|
||||
code.rocket9labs.com/tslocum/etk v0.0.0-20240119041154-d2c44cc232f6
|
||||
code.rocket9labs.com/tslocum/tabula v0.0.0-20240118055336-21a3dea3f702
|
||||
github.com/hajimehoshi/ebiten/v2 v2.6.3
|
||||
github.com/leonelquinteros/gotext v1.5.3-0.20231003122255-12a99145a351
|
||||
|
@ -54,7 +54,7 @@ require (
|
|||
github.com/vanng822/css v1.0.1 // indirect
|
||||
github.com/vanng822/go-premailer v1.20.2 // indirect
|
||||
golang.org/x/crypto v0.18.0 // indirect
|
||||
golang.org/x/exp/shiny v0.0.0-20240112132812-db7319d0e0e3 // indirect
|
||||
golang.org/x/exp/shiny v0.0.0-20240119083558-1b970713d09a // indirect
|
||||
golang.org/x/mobile v0.0.0-20240112133503-c713f31d574b // indirect
|
||||
golang.org/x/net v0.20.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
|
|
12
go.sum
12
go.sum
|
@ -2,10 +2,10 @@ code.rocket9labs.com/tslocum/bei v0.0.0-20240108012722-6db380cc190b h1:Y0a14Kf/h
|
|||
code.rocket9labs.com/tslocum/bei v0.0.0-20240108012722-6db380cc190b/go.mod h1:tS60/VNAJphKvDBkSLQhKALa15msIAuWWfEKNc4oFZc=
|
||||
code.rocket9labs.com/tslocum/bgammon v0.0.0-20240117214045-3607efee4129 h1:wguf0figCFqnSxAK8wAznDor28ZEkElA2ShoZmqLRHg=
|
||||
code.rocket9labs.com/tslocum/bgammon v0.0.0-20240117214045-3607efee4129/go.mod h1:LAki3jpHOsr4fwaK0xC9tkg+wgu/9ZNEqqx1zE3/HP4=
|
||||
code.rocket9labs.com/tslocum/bgammon-tabula-bot v0.0.0-20240118194149-d51931e431f7 h1:suit9TmttidcpYqMSLwcUeB2Ks0y5vw19xtH38Vw+4s=
|
||||
code.rocket9labs.com/tslocum/bgammon-tabula-bot v0.0.0-20240118194149-d51931e431f7/go.mod h1:w6xR2lWW3xUo7KlCOaJ+Jbs29AfQVRQEJ2W1vb0IuOo=
|
||||
code.rocket9labs.com/tslocum/etk v0.0.0-20240118083053-9eecc7a44b04 h1:RgEI91LXhZeeb4Hje+dXLeL/CMy0WLfNzyBEFXkiOOw=
|
||||
code.rocket9labs.com/tslocum/etk v0.0.0-20240118083053-9eecc7a44b04/go.mod h1:+mJqiyL/Ne30kcpnaQ1+XjYxI3PZA7HfWY0ReHeSMEA=
|
||||
code.rocket9labs.com/tslocum/bgammon-tabula-bot v0.0.0-20240120044556-60982417c592 h1:vLCTYMZfu6otPNNQG/vgFibct+p1fsKGxk1eCddRAi4=
|
||||
code.rocket9labs.com/tslocum/bgammon-tabula-bot v0.0.0-20240120044556-60982417c592/go.mod h1:w6xR2lWW3xUo7KlCOaJ+Jbs29AfQVRQEJ2W1vb0IuOo=
|
||||
code.rocket9labs.com/tslocum/etk v0.0.0-20240119041154-d2c44cc232f6 h1:uXG3IWWGkMG/mDjk1YsWJfQMbssYh3weoGuz1knFSuE=
|
||||
code.rocket9labs.com/tslocum/etk v0.0.0-20240119041154-d2c44cc232f6/go.mod h1:+mJqiyL/Ne30kcpnaQ1+XjYxI3PZA7HfWY0ReHeSMEA=
|
||||
code.rocket9labs.com/tslocum/tabula v0.0.0-20240118055336-21a3dea3f702 h1:NGZILSBynzLZF84WKZyAuoWsZFq37uvEcP2dFvPsY/8=
|
||||
code.rocket9labs.com/tslocum/tabula v0.0.0-20240118055336-21a3dea3f702/go.mod h1:WEJXESKXqrMFLAArikQ79lpRibNeeE1C0VruxXYMF5M=
|
||||
github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
|
||||
|
@ -136,8 +136,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
|
|||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/exp/shiny v0.0.0-20240112132812-db7319d0e0e3 h1:NezsOJwoBjJ5AXH5QQCdxe+WsqLw+f/t8eo1Tacfhqs=
|
||||
golang.org/x/exp/shiny v0.0.0-20240112132812-db7319d0e0e3/go.mod h1:3F+MieQB7dRYLTmnncoFbb1crS5lfQoTfDgQy6K4N0o=
|
||||
golang.org/x/exp/shiny v0.0.0-20240119083558-1b970713d09a h1:NZ9mAQhIcCceDZKqQX3JJVIz7nn3QLDuC+nXedsViBM=
|
||||
golang.org/x/exp/shiny v0.0.0-20240119083558-1b970713d09a/go.mod h1:3F+MieQB7dRYLTmnncoFbb1crS5lfQoTfDgQy6K4N0o=
|
||||
golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
|
||||
golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
||||
golang.org/x/mobile v0.0.0-20240112133503-c713f31d574b h1:kfWLZgb8iUBHdE9WydD5V5dHIS/F6HjlBZNyJfn2bs4=
|
||||
|
|
Loading…
Reference in a new issue