Update chat and game status color scheme

This commit is contained in:
Trevor Slocum 2021-11-12 13:31:34 -08:00
parent 22a97cdbfe
commit 67cb241e1e
7 changed files with 140 additions and 78 deletions

View File

@ -20,6 +20,8 @@ type board struct {
x, y int
w, h int
fullHeight bool
innerW, innerH int
op *ebiten.DrawImageOptions
@ -215,18 +217,14 @@ func (b *board) updateBackgroundImage() {
borderImage := image.NewRGBA(image.Rect(0, 0, b.w, b.h))
gc = draw2dimg.NewGraphicContext(borderImage)
gc.SetStrokeColor(borderColor)
// - Outside left
gc.SetLineWidth(2)
gc.MoveTo(float64(1), float64(0))
gc.LineTo(float64(1), float64(b.h))
// - Center
gc.SetLineWidth(2)
gc.MoveTo(float64(frameW/2), float64(0))
gc.LineTo(float64(frameW/2), float64(b.h))
gc.Stroke()
// - Outside right
gc.MoveTo(float64(frameW), float64(0))
gc.LineTo(float64(frameW), float64(b.h))
gc.Close()
gc.Stroke()
// - Inside left
gc.SetLineWidth(1)
@ -248,6 +246,19 @@ func (b *board) updateBackgroundImage() {
gc.LineTo(float64(edgeStart), float64(b.verticalBorderSize))
gc.Close()
gc.Stroke()
if !b.fullHeight {
// - Outside left
gc.SetLineWidth(1)
gc.MoveTo(float64(0), float64(0))
gc.LineTo(float64(0), float64(b.h))
// Top
gc.MoveTo(0, float64(0))
gc.LineTo(float64(b.w), float64(0))
// Bottom
gc.MoveTo(0, float64(b.h))
gc.LineTo(float64(b.w), float64(b.h))
gc.Stroke()
}
img = ebiten.NewImageFromImage(borderImage)
b.op.GeoM.Reset()
b.op.GeoM.Translate(b.horizontalBorderSize-borderSize, 0)
@ -918,12 +929,26 @@ func (b *board) movePiece(from int, to int) {
}
}
// WatchingGame returns whether the active game is being watched.
func (b *board) watchingGame() bool {
return !b.playingGame() && b.s[fibs.StatePlayerName] != "" && b.s[fibs.StateOpponentName] != ""
}
// PlayingGame returns whether the active game is being played.
func (b *board) playingGame() bool {
return b.s[fibs.StatePlayerName] == "You" || b.s[fibs.StateOpponentName] == "You"
}
func (b *board) playerTurn() bool {
return b.playingGame() && b.v[fibs.StateTurn] == b.v[fibs.StatePlayerColor]
}
func (b *board) update() {
if b.Client == nil {
return
}
if b.dragging == nil {
if b.dragging == nil && b.playerTurn() {
// TODO allow grabbing multiple pieces by grabbing further down the stack
handleReset := func(x, y int) bool {

View File

@ -3,8 +3,8 @@ package game
import "image/color"
var (
tableColor = color.RGBA{0, 0, 0, 255}
//tableColor = color.RGBA{0, 102, 51, 255}
//tableColor = color.RGBA{0, 102, 51, 255}
tableColor = color.RGBA{65, 40, 14, 255}
frameColor = color.RGBA{65, 40, 14, 255}
borderColor = color.RGBA{0, 0, 0, 255}
faceColor = color.RGBA{120, 63, 25, 255}

View File

@ -45,7 +45,7 @@ var (
var (
lightCheckerColor = color.RGBA{232, 211, 162, 255}
darkCheckerColor = color.RGBA{51, 0, 111, 255}
darkCheckerColor = color.RGBA{0, 0, 0, 255}
)
const defaultServerAddress = "fibs.com:4321"
@ -54,6 +54,15 @@ const maxStatusWidthRatio = 0.5
const bufferCharacterWidth = 54
const lobbyCharacterWidth = 48
const showGameBufferLines = 4
const (
minWidth = 320
minHeight = 240
)
func init() {
loadAssets(0)
@ -461,13 +470,13 @@ http://www.fibs.com/help.html#register`
return
}
g.gameBuffer.draw(screen)
g.statusBuffer.draw(screen)
if !viewBoard {
// Lobby screen
g.lobby.draw(screen)
} else {
// Game board screen
g.gameBuffer.draw(screen)
g.statusBuffer.draw(screen)
g.Board.draw(screen)
}
@ -506,6 +515,12 @@ http://www.fibs.com/help.html#register`
func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
s := ebiten.DeviceScaleFactor()
outsideWidth, outsideHeight = int(float64(outsideWidth)*s), int(float64(outsideHeight)*s)
if outsideWidth < minWidth {
outsideWidth = minWidth
}
if outsideHeight < minHeight {
outsideHeight = minHeight
}
if g.screenW == outsideWidth && g.screenH == outsideHeight {
return outsideWidth, outsideHeight
}
@ -517,12 +532,7 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
statusBufferWidth = int(float64(g.screenW) * maxStatusWidthRatio)
}
showGameBufferLines := 8
gameBufferHeight := g.statusBuffer.chatFontSize * showGameBufferLines * 2
statusBufferHeight := g.screenH - gameBufferHeight
g.lobby.setRect(0, 0, g.screenW, g.screenH)
g.Board.fullHeight = true
g.Board.setRect(0, 0, g.screenW-statusBufferWidth, g.screenH)
availableWidth := g.screenW - (g.Board.innerW + int(g.Board.horizontalBorderSize*2))
@ -532,15 +542,43 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) {
}
if g.Board.h > g.Board.w {
g.Board.fullHeight = false
g.Board.setRect(0, 0, g.Board.w, g.Board.w)
}
if g.screenW > 200 {
g.statusBuffer.padding = 2
g.gameBuffer.padding = 2
} else if g.screenW > 100 {
g.statusBuffer.padding = 1
g.gameBuffer.padding = 1
} else {
g.statusBuffer.padding = 0
g.gameBuffer.padding = 0
}
bufferPadding := int(g.Board.horizontalBorderSize / 2)
gameBufferHeight := (g.gameBuffer.chatLineHeight * showGameBufferLines) + (g.gameBuffer.padding * 4)
g.lobby.buttonBarHeight = gameBufferHeight + int(float64(bufferPadding)*1.5)
minLobbyWidth := text.BoundString(mediumFont, strings.Repeat("A", lobbyCharacterWidth)).Dx()
if g.Board.w >= minLobbyWidth {
g.lobby.fullscreen = false
g.lobby.setRect(0, 0, g.Board.w, g.screenH)
} else {
g.lobby.fullscreen = true
g.lobby.setRect(0, 0, g.screenW, g.screenH)
}
if true || availableWidth >= 150 { // TODO allow chat window to be repositioned
statusBufferHeight := g.screenH - gameBufferHeight - bufferPadding*3
g.statusBuffer.docked = true
g.statusBuffer.setRect(g.screenW-statusBufferWidth, g.screenH-(statusBufferHeight), statusBufferWidth, statusBufferHeight)
g.statusBuffer.setRect((g.screenW-statusBufferWidth)+bufferPadding, bufferPadding, statusBufferWidth-(bufferPadding*2), statusBufferHeight)
g.gameBuffer.docked = true
g.gameBuffer.setRect(g.screenW-statusBufferWidth, 0, statusBufferWidth, statusBufferHeight)
g.gameBuffer.setRect((g.screenW-statusBufferWidth)+bufferPadding, (g.screenH-(gameBufferHeight))-bufferPadding, statusBufferWidth-(bufferPadding*2), gameBufferHeight)
} else {
// Clamp buffer position.
bx, by := g.statusBuffer.x, g.statusBuffer.y

View File

@ -2,6 +2,7 @@ package game
import (
"fmt"
"image"
"image/color"
"math"
"sort"
@ -36,6 +37,8 @@ type lobby struct {
x, y int
w, h int
fullscreen bool
padding float64
entryH float64
buttonBarHeight int
@ -102,9 +105,9 @@ func (l *lobby) _drawBufferButtons() {
l.bufferButtons.Fill(frameColor)
// Draw border
for ly := 0; ly < 2; ly++ {
for ly := 0; ly < 1; ly++ {
for lx := 0; lx < l.w; lx++ {
l.bufferButtons.Set(lx, ly, triangleA)
l.bufferButtons.Set(lx, ly, borderColor)
}
}
@ -115,20 +118,20 @@ func (l *lobby) _drawBufferButtons() {
// Draw border
if i > 0 {
for ly := 0; ly < l.buttonBarHeight; ly++ {
for lx := buttonWidth * i; lx < (buttonWidth*i)+2; lx++ {
l.bufferButtons.Set(lx, ly, triangleA)
for lx := buttonWidth * i; lx < (buttonWidth*i)+1; lx++ {
l.bufferButtons.Set(lx, ly, borderColor)
}
}
}
bounds := text.BoundString(mediumFont, button.label)
labelColor := triangleA
labelColor := lightCheckerColor
img := ebiten.NewImage(bounds.Dx()*2, bounds.Dy()*2)
text.Draw(img, button.label, mediumFont, 0, bounds.Dy(), labelColor)
text.Draw(img, button.label, mediumFont, 0, standardLineHeight, labelColor)
l.op.GeoM.Reset()
l.op.GeoM.Translate(float64(buttonWidth*i)+float64((buttonWidth-bounds.Dx())/2), float64(l.buttonBarHeight-bounds.Dy())/2-float64(bounds.Dy()/2))
l.op.GeoM.Translate(float64(buttonWidth*i)+float64((buttonWidth-bounds.Dx())/2), float64(l.buttonBarHeight-standardLineHeight*1.5)/2)
l.bufferButtons.DrawImage(img, l.op)
}
}
@ -159,53 +162,55 @@ func (l *lobby) drawBuffer() {
}
} else {
var img *ebiten.Image
drawEntry := func(cx float64, cy float64, colA string, colB string, colC string, highlight bool) {
boundsA := text.BoundString(mediumFont, colA)
boundsB := text.BoundString(mediumFont, colB)
boundsC := text.BoundString(mediumFont, colC)
y := (boundsA.Dy() + boundsB.Dy() + boundsC.Dy()) / 3 // TODO this isn't correct
drawEntry := func(cx float64, cy float64, colA string, colB string, colC string, highlight bool, title bool) {
labelColor := triangleA
if highlight {
labelColor = color.RGBA{200, 200, 60, 255}
labelColor = lightCheckerColor
} else if title {
labelColor = lightCheckerColor
}
selectedBorderColor := triangleB
img = ebiten.NewImage(l.w-int(l.padding*2), int(l.entryH))
if highlight {
highlightColor := color.RGBA{triangleA.R, triangleA.G, triangleA.B, 15}
img.SubImage(image.Rect(0, 0, l.w, int(l.entryH))).(*ebiten.Image).Fill(highlightColor)
div := 1.75
highlightBorderColor := color.RGBA{uint8(float64(frameColor.R) / div), uint8(float64(frameColor.G) / div), uint8(float64(frameColor.B) / div), 200}
for x := 0; x < l.w; x++ {
img.Set(x, 0, selectedBorderColor)
img.Set(x, int(l.entryH)-1, selectedBorderColor)
img.Set(x, 0, highlightBorderColor)
img.Set(x, int(l.entryH)-1, highlightBorderColor)
}
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)
img.Set(0, by, highlightBorderColor)
img.Set(l.w-(int(l.padding)*2)-1, by, highlightBorderColor)
}
}
text.Draw(img, colA, mediumFont, 4, y+2, labelColor)
text.Draw(img, colB, mediumFont, int(250*ebiten.DeviceScaleFactor()), y+2, labelColor)
text.Draw(img, colC, mediumFont, int(500*ebiten.DeviceScaleFactor()), y+2, labelColor)
text.Draw(img, colA, mediumFont, 4, standardLineHeight, labelColor)
text.Draw(img, colB, mediumFont, int(250*ebiten.DeviceScaleFactor()), standardLineHeight, labelColor)
text.Draw(img, colC, mediumFont, int(500*ebiten.DeviceScaleFactor()), standardLineHeight, labelColor)
l.op.GeoM.Reset()
l.op.GeoM.Translate(cx, cy)
l.buffer.DrawImage(img, l.op)
}
titleOffset := 2.0
if len(l.who) == 0 {
drawEntry(l.padding, l.padding, "Loading...", "Please wait...", "Loading...", false)
drawEntry(l.padding, l.padding-titleOffset, "Loading...", "Please wait...", "Loading...", false, true)
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)
for ly := -2; ly < -1; ly++ {
for lx := 0; lx < l.w; lx++ {
l.buffer.Set(lx, int(l.padding)+int(l.entryH)+ly, borderColor)
}
}
cx, cy := 0.0, 0.0 // Cursor
drawEntry(cx+l.padding, cy+l.padding, "Username", "Rating (Experience)", "Status", false)
drawEntry(cx+l.padding, cy+l.padding-titleOffset, "Username", "Rating (Experience)", "Status", false, true)
cy += l.entryH
i := 0
for _, who := range l.who {
@ -219,7 +224,7 @@ func (l *lobby) drawBuffer() {
status = "Ready to play"
}
drawEntry(cx+l.padding, cy+l.padding, who.Username, details, status, i == l.selected)
drawEntry(cx+l.padding, cy+l.padding, who.Username, details, status, i == l.selected, false)
cy += l.entryH
}
@ -274,7 +279,6 @@ func (l *lobby) setRect(x, y, w, h int) {
s := ebiten.DeviceScaleFactor()
l.padding = 4 * s
l.entryH = 32 * s
l.buttonBarHeight = int(200 * s)
if l.w != w || l.h != h {
l.buffer = ebiten.NewImage(w, h)

View File

@ -28,7 +28,7 @@ const (
const (
monoLineHeight = 14
standardLineHeight = 22
standardLineHeight = 24
)
type tabbedBuffers struct {
@ -105,14 +105,6 @@ func (t *tabbedBuffers) setRect(x, y, w, h int) {
}
if t.w != w {
if w > 200 {
t.padding = 2
} else if w > 100 {
t.padding = 1
} else {
t.padding = 0
}
t.wrapWidth = (w - (t.padding * 4)) / t.chatFontSize
for _, b := range t.buffers {
b.wrapDirty = true
@ -122,40 +114,43 @@ func (t *tabbedBuffers) setRect(x, y, w, h int) {
t.x, t.y, t.w, t.h = x, y, w, h
}
func (t *tabbedBuffers) linesVisible() int {
lines := (t.h - (t.padding * 2)) / t.chatLineHeight
// Leave space for the input buffer.
if t.acceptInput {
if lines > 1 {
lines--
}
}
return lines
}
func (t *tabbedBuffers) drawBuffer() {
t.buffer.Fill(color.Black)
// Draw background.
t.buffer.Fill(color.RGBA{0, 0, 0, 100})
// Draw content.
textColor := triangleALight
/*sub := t.buffer.SubImage(image.Rect(1, 1, t.w-1, t.h-1)).(*ebiten.Image)
sub.Fill(frameColor)*/
b := t.buffers[0]
l := len(b.contentWrapped)
showLines := t.h / t.chatLineHeight
if showLines > 1 {
showLines--
}
if t.acceptInput {
// Leave space for the input buffer.
if showLines > 1 {
showLines--
}
}
showLines := t.linesVisible()
if l < showLines {
showLines = l
}
for i := 0; i < showLines; i++ {
line := b.contentWrapped[l-showLines+i]
text.Draw(t.buffer, line, t.chatFont, t.padding*2, t.padding+(t.chatLineHeight*(i+1)), textColor)
text.Draw(t.buffer, line, t.chatFont, t.padding*2, t.chatLineHeight*(i+1), textColor)
}
// Draw input buffer.
if t.acceptInput {
text.Draw(t.buffer, "> "+string(t.inputBuffer), t.chatFont, t.padding*2, t.h-(t.padding*2), textColor)
text.Draw(t.buffer, "> "+string(t.inputBuffer), t.chatFont, t.padding*2, t.h-(t.padding*4), textColor)
}
}

2
go.mod
View File

@ -23,7 +23,7 @@ require (
golang.org/x/exp v0.0.0-20211111183329-cb5df436b1a8 // indirect
golang.org/x/mobile v0.0.0-20211109191125-d61a72f26a1a // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
golang.org/x/sys v0.0.0-20211111213525-f221eed1c01e // indirect
golang.org/x/sys v0.0.0-20211112193437-faf0a1b62c6b // indirect
golang.org/x/text v0.3.7 // indirect
nhooyr.io/websocket v1.8.7 // indirect
)

4
go.sum
View File

@ -441,8 +441,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/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-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211111213525-f221eed1c01e h1:zeJt6jBtVDK23XK9QXcmG0FvO0elikp0dYZQZOeL1y0=
golang.org/x/sys v0.0.0-20211111213525-f221eed1c01e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211112193437-faf0a1b62c6b h1:uo+9AuR+gDt/gdj+1BaLhdOHsaGI6YU6585IiDcLrFE=
golang.org/x/sys v0.0.0-20211112193437-faf0a1b62c6b/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=