diff --git a/flags.go b/flags.go index b9c08e2..f4055e5 100644 --- a/flags.go +++ b/flags.go @@ -21,14 +21,12 @@ func parseFlags() *game.Game { locale string tv bool debug int - touch bool ) flag.StringVar(&username, "username", "", "Username") flag.StringVar(&password, "password", "", "Password") flag.StringVar(&serverAddress, "address", game.DefaultServerAddress, "Server address") flag.StringVar(&locale, "locale", "", "Use specified locale for translations") flag.BoolVar(&tv, "tv", false, "Watch random games continuously") - flag.BoolVar(&touch, "touch", false, "Force touch input related interface elements to be displayed") flag.IntVar(&debug, "debug", 0, "Print debug information and serve pprof on specified port") flag.Parse() @@ -51,10 +49,6 @@ func parseFlags() *game.Game { g.ServerAddress = serverAddress g.TV = tv - if touch { - g.EnableTouchInput() - } - if debug > 0 { game.Debug = 1 go func() { diff --git a/game/board.go b/game/board.go index 1f2a4b5..21cb58f 100644 --- a/game/board.go +++ b/game/board.go @@ -172,11 +172,15 @@ var ( ) func NewBoard() *board { + var extraBorder float64 + if AutoEnableTouchInput { + extraBorder = float64(etk.Scale(5)) + } b := &board{ barWidth: 100, triangleOffset: float64(50), - horizontalBorderSize: 20, - verticalBorderSize: float64(baseBoardVerticalSize), + horizontalBorderSize: 20 + extraBorder, + verticalBorderSize: float64(baseBoardVerticalSize) + extraBorder, overlapSize: 97, Sprites: &Sprites{ sprites: make([]*Sprite, 30), @@ -333,7 +337,7 @@ func NewBoard() *board { b.changePasswordGrid.SetBackground(color.RGBA{40, 24, 9, 255}) b.changePasswordGrid.SetColumnSizes(20, -1, -1, 20) - b.changePasswordGrid.SetRowSizes(72, fieldHeight+20+fieldHeight, -1, game.scale(baseButtonHeight)) + b.changePasswordGrid.SetRowSizes(72, fieldHeight+20+fieldHeight, -1, etk.Scale(baseButtonHeight)) b.changePasswordGrid.AddChildAt(headerLabel, 1, 0, 2, 1) b.changePasswordGrid.AddChildAt(fieldGrid, 1, 1, 2, 1) b.changePasswordGrid.AddChildAt(etk.NewBox(), 1, 2, 1, 1) @@ -493,7 +497,7 @@ func NewBoard() *board { } b.settingsGrid.SetBackground(color.RGBA{40, 24, 9, 255}) b.settingsGrid.SetColumnSizes(20, -1, -1, 20) - b.settingsGrid.SetRowSizes(72, -1, 20, game.scale(baseButtonHeight)) + b.settingsGrid.SetRowSizes(72, -1, 20, etk.Scale(baseButtonHeight)) b.settingsGrid.AddChildAt(settingsLabel, 1, 0, 2, 1) b.settingsGrid.AddChildAt(checkboxGrid, 1, 1, 2, 1) b.settingsGrid.AddChildAt(etk.NewBox(), 1, 2, 1, 1) @@ -626,20 +630,12 @@ func (b *board) fontUpdated() { b.lineOffset = m.Ascent.Round() fontMutex.Unlock() - bufferFont := b.fontFace - if game.scaleFactor <= 1 { - switch b.fontFace { - case largeFont: - bufferFont = mediumFont - case mediumFont: - bufferFont = smallFont - } - } + bufferFont := smallFont statusBuffer.SetFont(bufferFont, fontMutex) gameBuffer.SetFont(bufferFont, fontMutex) inputBuffer.Field.SetFont(bufferFont, fontMutex) - if game.TouchInput { + if AutoEnableTouchInput { b.showMenuButton.Label.SetFont(largeFont, fontMutex) } else { b.showMenuButton.Label.SetFont(smallFont, fontMutex) @@ -648,7 +644,7 @@ func (b *board) fontUpdated() { b.timerLabel.SetFont(b.fontFace, fontMutex) b.clockLabel.SetFont(b.fontFace, fontMutex) - if game.TouchInput { + if AutoEnableTouchInput { b.opponentForcedLabel.SetFont(largeFont, fontMutex) b.playerForcedLabel.SetFont(largeFont, fontMutex) } else { @@ -659,8 +655,13 @@ func (b *board) fontUpdated() { b.opponentMovesLabel.SetFont(bufferFont, fontMutex) b.playerMovesLabel.SetFont(bufferFont, fontMutex) - b.opponentPipCount.SetFont(bufferFont, fontMutex) - b.playerPipCount.SetFont(bufferFont, fontMutex) + if AutoEnableTouchInput { + b.opponentPipCount.SetFont(extraSmallFont, fontMutex) + b.playerPipCount.SetFont(extraSmallFont, fontMutex) + } else { + b.opponentPipCount.SetFont(bufferFont, fontMutex) + b.playerPipCount.SetFont(bufferFont, fontMutex) + } } func (b *board) recreateUIGrid() { @@ -675,15 +676,11 @@ func (b *board) recreateUIGrid() { gridY += 2 } if game.replay { - f := smallFont - if defaultFontSize == extraLargeFontSize { - f = mediumFont - } summary1 := etk.NewText("") - summary1.SetFont(f, fontMutex) + summary1.SetFont(smallFont, fontMutex) summary1.Write(game.replaySummary1) summary2 := etk.NewText("") - summary2.SetFont(f, fontMutex) + summary2.SetFont(smallFont, fontMutex) summary2.Write(game.replaySummary2) subGrid := etk.NewGrid() subGrid.SetBackground(bufferBackgroundColor) @@ -691,7 +688,7 @@ func (b *board) recreateUIGrid() { subGrid.AddChildAt(summary1, 1, 0, 1, 1) g := etk.NewGrid() - g.SetRowSizes(game.scale(baseButtonHeight), int(b.verticalBorderSize/2), -1, int(b.verticalBorderSize/2), lobbyStatusBufferHeight*2) + g.SetRowSizes(etk.Scale(baseButtonHeight), int(b.verticalBorderSize/2), -1, int(b.verticalBorderSize/2), lobbyStatusBufferHeight*2) g.AddChildAt(b.replayGrid, 0, 0, 1, 1) g.AddChildAt(subGrid, 0, 2, 1, 1) g.AddChildAt(statusBuffer, 0, 4, 1, 1) @@ -733,14 +730,14 @@ func (b *board) showButtonGrid(buttonGrid *etk.Grid) { func (b *board) recreateButtonGrid() { buttonGrid := func(grid *etk.Grid, reverse bool, widgets ...etk.Widget) *etk.Grid { - w := game.scale(250) + w := etk.Scale(250) if w > b.innerW/4 { w = b.innerW / 4 } if w > b.innerH/4 { w = b.innerH / 4 } - h := game.scale(125) + h := etk.Scale(125) if h > b.innerW/8 { h = b.innerW / 8 } @@ -1791,10 +1788,7 @@ func (b *board) setRect(x, y, w, h int) { b.updateBackgroundImage() b.processState() - matchStatus := 36 - if game.scaleFactor >= 1.25 || AutoEnableTouchInput { - matchStatus *= 2 - } + matchStatus := etk.Scale(36) if AutoEnableTouchInput { b.uiGrid.SetRowSizes(int(b.verticalBorderSize/2), matchStatus, int(b.verticalBorderSize/2), fieldHeight, int(b.verticalBorderSize/2), -1, int(b.verticalBorderSize/2), -1) } else { @@ -1802,11 +1796,11 @@ func (b *board) setRect(x, y, w, h int) { } { - dialogWidth := game.scale(620) + dialogWidth := etk.Scale(620) if dialogWidth > game.screenW { dialogWidth = game.screenW } - dialogHeight := game.scale(100) + dialogHeight := etk.Scale(100) if dialogHeight > game.screenH { dialogHeight = game.screenH } @@ -1816,11 +1810,11 @@ func (b *board) setRect(x, y, w, h int) { } { - dialogWidth := game.scale(620) + dialogWidth := etk.Scale(620) if dialogWidth > game.screenW { dialogWidth = game.screenW } - dialogHeight := 72 + 72 + 20 + 72 + 20 + 72 + 20 + 72 + 20 + 72 + 20 + 72 + 20 + 72 + 20 + game.scale(baseButtonHeight) + dialogHeight := 72 + 72 + 20 + 72 + 20 + 72 + 20 + 72 + 20 + 72 + 20 + 72 + 20 + 72 + 20 + etk.Scale(baseButtonHeight) if dialogHeight > game.screenH { dialogHeight = game.screenH } @@ -1832,11 +1826,11 @@ func (b *board) setRect(x, y, w, h int) { } { - dialogWidth := game.scale(400) + dialogWidth := etk.Scale(400) if dialogWidth > game.screenW { dialogWidth = game.screenW } - dialogHeight := game.scale(100) + dialogHeight := etk.Scale(100) if dialogHeight > game.screenH { dialogHeight = game.screenH } @@ -1850,7 +1844,7 @@ func (b *board) setRect(x, y, w, h int) { b.recreateButtonGrid() - b.menuGrid.SetColumnSizes(-1, game.scale(10), -1, game.scale(10), -1) + b.menuGrid.SetColumnSizes(-1, etk.Scale(10), -1, etk.Scale(10), -1) var padding int if b.w >= 600 { @@ -2619,7 +2613,7 @@ func (b *board) finishDrag(x int, y int, click bool) { if !b.draggingClick && index == b.draggingSpace && !b.lastDragClick.IsZero() && time.Since(b.lastDragClick) < 500*time.Millisecond { b.startDrag(dropped, index, true) - if game.TouchInput { + if AutoEnableTouchInput { r := b.spaceRects[index] offset := int(b.spaceWidth) + int(b.overlapSize)*4 if !b.bottomRow(index) { diff --git a/game/game.go b/game/game.go index 279e80d..12a4dde 100644 --- a/game/game.go +++ b/game/game.go @@ -67,10 +67,11 @@ var ( imgDice5 *ebiten.Image imgDice6 *ebiten.Image - smallFont font.Face - mediumFont font.Face - largeFont font.Face - extraLargeFont font.Face + extraSmallFont font.Face + smallFont font.Face + mediumFont font.Face + mediumLargeFont font.Face + largeFont font.Face fontMutex = &sync.Mutex{} ) @@ -90,10 +91,11 @@ const ( ) const ( - smallFontSize = 20 - mediumFontSize = 24 - largeFontSize = 36 - extraLargeFontSize = 52 + extraSmallFontSize = 14 + smallFontSize = 20 + mediumFontSize = 24 + mediumLargeFontSize = 32 + largeFontSize = 36 ) var ( @@ -128,8 +130,6 @@ var ( historyContainer *etk.Grid listGamesContainer *etk.Grid - tutorialFrame *etk.Frame - connectFrame *etk.Frame createGameFrame *etk.Frame joinGameFrame *etk.Frame @@ -173,46 +173,6 @@ func lg(s string) { scheduleFrame() } -func init() { - gotext.SetDomain("boxcars") - - initializeFonts() - - loadAudioAssets() - - if AutoEnableTouchInput { - etk.Bindings.ConfirmRune = 199 - etk.Bindings.BackRune = 231 - } - - if defaultFontSize == extraLargeFontSize { - etk.Style.TextFont = extraLargeFont - } else { - etk.Style.TextFont = largeFont - } - etk.Style.TextFontMutex = fontMutex - - etk.Style.TextColorLight = triangleA - etk.Style.TextColorDark = triangleA - etk.Style.InputBgColor = color.RGBA{40, 24, 9, 255} - - etk.Style.ScrollAreaColor = color.RGBA{26, 15, 6, 255} - etk.Style.ScrollHandleColor = color.RGBA{180, 154, 108, 255} - - etk.Style.ButtonTextColor = color.RGBA{0, 0, 0, 255} - etk.Style.ButtonBgColor = color.RGBA{225, 188, 125, 255} - - statusBuffer.SetForegroundColor(bufferTextColor) - statusBuffer.SetBackgroundColor(bufferBackgroundColor) - - gameBuffer.SetForegroundColor(bufferTextColor) - gameBuffer.SetBackgroundColor(bufferBackgroundColor) - - inputBuffer.Field.SetForegroundColor(bufferTextColor) - inputBuffer.Field.SetBackgroundColor(bufferBackgroundColor) - inputBuffer.Field.SetSuffix("") -} - var loadedCheckerWidth = -1 func loadImageAssets(width int) { @@ -229,7 +189,7 @@ func loadImageAssets(width int) { panic("nil game") } - maxSize := game.scale(100) + maxSize := etk.Scale(100) if maxSize > game.screenW/10 { maxSize = game.screenW / 10 } @@ -237,7 +197,7 @@ func loadImageAssets(width int) { maxSize = game.screenH / 10 } - diceSize = game.scale(width) + diceSize = etk.Scale(width) if diceSize > maxSize { diceSize = maxSize } @@ -387,8 +347,21 @@ func initializeFonts() { } const dpi = 72 + s := etk.ScaleFactor() + if AutoEnableTouchInput { + s /= 2 + } + + extraSmallFont, err = opentype.NewFace(tt, &opentype.FaceOptions{ + Size: extraSmallFontSize * s, + DPI: dpi, + Hinting: font.HintingFull, + }) + if err != nil { + log.Fatal(err) + } smallFont, err = opentype.NewFace(tt, &opentype.FaceOptions{ - Size: smallFontSize, + Size: smallFontSize * s, DPI: dpi, Hinting: font.HintingFull, }) @@ -396,7 +369,15 @@ func initializeFonts() { log.Fatal(err) } mediumFont, err = opentype.NewFace(tt, &opentype.FaceOptions{ - Size: mediumFontSize, + Size: mediumFontSize * s, + DPI: dpi, + Hinting: font.HintingFull, + }) + if err != nil { + log.Fatal(err) + } + mediumLargeFont, err = opentype.NewFace(tt, &opentype.FaceOptions{ + Size: mediumLargeFontSize * s, DPI: dpi, Hinting: font.HintingFull, }) @@ -404,15 +385,7 @@ func initializeFonts() { log.Fatal(err) } largeFont, err = opentype.NewFace(tt, &opentype.FaceOptions{ - Size: largeFontSize, - DPI: dpi, - Hinting: font.HintingFull, - }) - if err != nil { - log.Fatal(err) - } - extraLargeFont, err = opentype.NewFace(tt, &opentype.FaceOptions{ - Size: extraLargeFontSize, + Size: largeFontSize * s, DPI: dpi, Hinting: font.HintingFull, }) @@ -597,7 +570,6 @@ type Game struct { pressedRunes []rune cursorX, cursorY int - TouchInput bool rootWidget etk.Widget @@ -607,8 +579,6 @@ type Game struct { forceLayout bool - scaleFactor float64 - bufferWidth int connectGridY int @@ -618,13 +588,10 @@ type Game struct { needLayoutLobby bool needLayoutBoard bool - loadedConnect bool - loadedLobby bool - loadedBoard bool - LoadReplay []byte - loaded bool + initialized bool + loaded bool showRegister bool showReset bool @@ -651,31 +618,62 @@ func NewGame() *Game { g := &Game{ runeBuffer: make([]rune, 24), - TouchInput: AutoEnableTouchInput, - tutorialFrame: etk.NewFrame(), - debugImg: ebiten.NewImage(200, 200), - volume: 1, - scaleFactor: 1, + debugImg: ebiten.NewImage(200, 200), + volume: 1, Mutex: &sync.Mutex{}, } g.tutorialFrame.SetPositionChildren(true) game = g + return g +} + +func (g *Game) initialize() { + gotext.SetDomain("boxcars") + + initializeFonts() + loadAudioAssets() loadImageAssets(0) + if AutoEnableTouchInput { + etk.Bindings.ConfirmRune = 199 + etk.Bindings.BackRune = 231 + } + + etk.Style.TextFont = largeFont + etk.Style.TextFontMutex = fontMutex + + etk.Style.TextColorLight = triangleA + etk.Style.TextColorDark = triangleA + etk.Style.InputBgColor = color.RGBA{40, 24, 9, 255} + + etk.Style.ScrollAreaColor = color.RGBA{26, 15, 6, 255} + etk.Style.ScrollHandleColor = color.RGBA{180, 154, 108, 255} + + etk.Style.ButtonTextColor = color.RGBA{0, 0, 0, 255} + etk.Style.ButtonBgColor = color.RGBA{225, 188, 125, 255} + + statusBuffer.SetForegroundColor(bufferTextColor) + statusBuffer.SetBackgroundColor(bufferBackgroundColor) + + gameBuffer.SetForegroundColor(bufferTextColor) + gameBuffer.SetBackgroundColor(bufferBackgroundColor) + + inputBuffer.Field.SetForegroundColor(bufferTextColor) + inputBuffer.Field.SetBackgroundColor(bufferBackgroundColor) + inputBuffer.Field.SetSuffix("") + g.Board = NewBoard() g.lobby = NewLobby() - xPadding := 10 - yPadding := 20 - labelWidth := 200 - if defaultFontSize == extraLargeFontSize { - xPadding = 15 - yPadding = 30 - labelWidth = 260 + xPadding := etk.Scale(10) + yPadding := etk.Scale(20) + labelWidth := etk.Scale(200) + if AutoEnableTouchInput { + labelWidth /= 2 } connectAddress := game.ServerAddress @@ -818,6 +816,10 @@ func NewGame() *Game { nameLabel := newCenteredText(gotext.Get("Username")) passwordLabel := newCenteredText(gotext.Get("Password")) serverLabel := newCenteredText(gotext.Get("Server")) + if AutoEnableTouchInput { + headerLabel.SetFont(mediumLargeFont, fontMutex) + headerLabel.SetHorizontal(messeji.AlignCenter) + } infoLabel := etk.NewText(gotext.Get("To log in as a guest, enter a username (if you want) and do not enter a password.")) @@ -1048,10 +1050,10 @@ func NewGame() *Game { opponentLabel := newCenteredText(gotext.Get("Opponent")) opponentLabel.SetFollow(false) opponentLabel.SetScrollBarVisible(false) - - indentA, indentB := lobbyIndentA, lobbyIndentB - if defaultFontSize == extraLargeFontSize { - indentA, indentB = int(float64(indentA)*1.3), int(float64(indentB)*1.3) + if AutoEnableTouchInput { + dateLabel.SetFont(mediumFont, fontMutex) + resultLabel.SetFont(mediumFont, fontMutex) + opponentLabel.SetFont(mediumFont, fontMutex) } g.lobby.historyUsername = etk.NewInput("", "", func(text string) (handled bool) { @@ -1063,7 +1065,13 @@ func NewGame() *Game { searchButton := etk.NewButton(gotext.Get("Search"), g.selectHistorySearch) - g.lobby.historyList = etk.NewList(game.itemHeight(), g.lobby.selectHistory) + indentA, indentB := etk.Scale(lobbyIndentA), etk.Scale(lobbyIndentB) + + historyItemHeight := game.itemHeight() + if AutoEnableTouchInput { + historyItemHeight /= 2 + } + g.lobby.historyList = etk.NewList(historyItemHeight, g.lobby.selectHistory) g.lobby.historyList.SetColumnSizes(int(float64(indentA)*1.25), int(float64(indentB)*1.25)-int(float64(indentA)*1.25), -1) g.lobby.historyList.SetHighlightColor(color.RGBA{79, 55, 30, 255}) @@ -1090,10 +1098,7 @@ func NewGame() *Game { g.lobby.historyRatingCasualTabulaMulti = newLabel("...", messeji.AlignStart) ratingGrid := func(singleLabel *etk.Text, multiLabel *etk.Text) *etk.Grid { - dividerSize := 10 - if defaultFontSize == extraLargeFontSize { - dividerSize = 20 - } + const dividerSize = 10 g := etk.NewGrid() g.SetColumnSizes(-1, dividerSize, -1) g.AddChildAt(newLabel(gotext.Get("Single"), messeji.AlignEnd), 0, 0, 1, 1) @@ -1106,12 +1111,6 @@ func NewGame() *Game { historyDividerLine := etk.NewBox() historyDividerLine.SetBackground(bufferTextColor) - headerLabel := func(text string) *etk.Text { - t := newLabel(text, messeji.AlignCenter) - t.SetFont(extraLargeFont, fontMutex) - return t - } - g.lobby.historyPageLabel = newLabel("...", messeji.AlignCenter) pageControlGrid := etk.NewGrid() @@ -1122,11 +1121,11 @@ func NewGame() *Game { historyRatingGrid := etk.NewGrid() historyRatingGrid.SetRowSizes(2, -1, -1, -1) historyRatingGrid.AddChildAt(historyDividerLine, 0, 0, 3, 1) - historyRatingGrid.AddChildAt(headerLabel(gotext.Get("Backgammon")), 0, 1, 1, 1) + historyRatingGrid.AddChildAt(newLabel(gotext.Get("Backgammon"), messeji.AlignCenter), 0, 1, 1, 1) historyRatingGrid.AddChildAt(ratingGrid(g.lobby.historyRatingCasualBackgammonSingle, g.lobby.historyRatingCasualBackgammonMulti), 0, 2, 1, 2) - historyRatingGrid.AddChildAt(headerLabel(gotext.Get("Acey-deucey")), 1, 1, 1, 1) + historyRatingGrid.AddChildAt(newLabel(gotext.Get("Acey-deucey"), messeji.AlignCenter), 1, 1, 1, 1) historyRatingGrid.AddChildAt(ratingGrid(g.lobby.historyRatingCasualAceySingle, g.lobby.historyRatingCasualAceyMulti), 1, 2, 1, 2) - historyRatingGrid.AddChildAt(headerLabel(gotext.Get("Tabula")), 2, 1, 1, 1) + historyRatingGrid.AddChildAt(newLabel(gotext.Get("Tabula"), messeji.AlignCenter), 2, 1, 1, 1) historyRatingGrid.AddChildAt(ratingGrid(g.lobby.historyRatingCasualTabulaSingle, g.lobby.historyRatingCasualTabulaMulti), 2, 2, 1, 2) historyContainer = etk.NewGrid() @@ -1162,15 +1161,18 @@ func NewGame() *Game { nameLabel := newCenteredText(gotext.Get("Match Name")) nameLabel.SetFollow(false) nameLabel.SetScrollBarVisible(false) - - indentA, indentB := lobbyIndentA, lobbyIndentB - if defaultFontSize == extraLargeFontSize { - indentA, indentB = int(float64(indentA)*1.3), int(float64(indentB)*1.3) + if AutoEnableTouchInput { + statusLabel.SetFont(mediumFont, fontMutex) + ratingLabel.SetFont(mediumFont, fontMutex) + pointsLabel.SetFont(mediumFont, fontMutex) + nameLabel.SetFont(mediumFont, fontMutex) } g.lobby.historyButton = etk.NewButton(gotext.Get("History"), game.selectHistory) g.lobby.historyButton.SetVisible(false) + indentA, indentB := etk.Scale(lobbyIndentA), etk.Scale(lobbyIndentB) + headerGrid := etk.NewGrid() headerGrid.SetColumnSizes(indentA, indentB-indentA, indentB-indentA, -1, 300) headerGrid.AddChildAt(statusLabel, 0, 0, 1, 1) @@ -1197,6 +1199,21 @@ func NewGame() *Game { g.keyboardHint.SetVertical(messeji.AlignCenter) } + statusBuffer.SetScrollBarColors(etk.Style.ScrollAreaColor, etk.Style.ScrollHandleColor) + gameBuffer.SetScrollBarColors(etk.Style.ScrollAreaColor, etk.Style.ScrollHandleColor) + inputBuffer.Field.SetScrollBarColors(etk.Style.ScrollAreaColor, etk.Style.ScrollHandleColor) + g.lobby.availableMatchesList.SetScrollBarColors(etk.Style.ScrollAreaColor, etk.Style.ScrollHandleColor) + g.lobby.historyList.SetScrollBarColors(etk.Style.ScrollAreaColor, etk.Style.ScrollHandleColor) + + { + scrollBarWidth := etk.Scale(32) + statusBuffer.SetScrollBarWidth(scrollBarWidth) + gameBuffer.SetScrollBarWidth(scrollBarWidth) + inputBuffer.Field.SetScrollBarWidth(scrollBarWidth) + g.lobby.availableMatchesList.SetScrollBarWidth(scrollBarWidth) + g.lobby.historyList.SetScrollBarWidth(scrollBarWidth) + } + g.needLayoutConnect = true g.needLayoutLobby = true g.needLayoutBoard = true @@ -1215,7 +1232,6 @@ func NewGame() *Game { go g.handleUpdateTimeLabels() scheduleFrame() - return g } func (g *Game) playOffline() { @@ -1292,17 +1308,17 @@ func (g *Game) setRoot(w etk.Widget) { } func (g *Game) setBufferRects() { - statusBufferHeight := g.scale(75) - - historyRatingHeight := 200 - if defaultFontSize == extraLargeFontSize { - historyRatingHeight = 250 - } + statusBufferHeight := etk.Scale(75) + historyRatingHeight := etk.Scale(200) createGameContainer.SetRowSizes(-1, statusBufferHeight, g.lobby.buttonBarHeight) joinGameContainer.SetRowSizes(-1, statusBufferHeight, g.lobby.buttonBarHeight) historyContainer.SetRowSizes(g.itemHeight(), 2, -1, g.lobby.buttonBarHeight, historyRatingHeight, statusBufferHeight, g.lobby.buttonBarHeight) - listGamesContainer.SetRowSizes(g.itemHeight(), 2, -1, statusBufferHeight, g.lobby.buttonBarHeight) + listHeaderHeight := g.itemHeight() + if AutoEnableTouchInput { + listHeaderHeight /= 2 + } + listGamesContainer.SetRowSizes(listHeaderHeight, 2, -1, statusBufferHeight, g.lobby.buttonBarHeight) } func (g *Game) handleAutoRefresh() { @@ -1592,9 +1608,17 @@ func (g *Game) handleEvent(e interface{}) { if match.Winner == 2 { result = "L" } - list.AddChildAt(newCenteredText(time.Unix(match.Timestamp, 0).Format("2006-01-02")), 0, y+i) - list.AddChildAt(newCenteredText(result), 1, y+i) - list.AddChildAt(newCenteredText(match.Opponent), 2, y+i) + dateLabel := newCenteredText(time.Unix(match.Timestamp, 0).Format("2006-01-02")) + resultLabel := newCenteredText(result) + opponentLabel := newCenteredText(match.Opponent) + if AutoEnableTouchInput { + dateLabel.SetFont(mediumFont, fontMutex) + resultLabel.SetFont(mediumFont, fontMutex) + opponentLabel.SetFont(mediumFont, fontMutex) + } + list.AddChildAt(dateLabel, 0, y+i) + list.AddChildAt(resultLabel, 1, y+i) + list.AddChildAt(opponentLabel, 2, y+i) } if ev.Page == 1 { list.SetSelectedItem(0, 0) @@ -2202,9 +2226,14 @@ func (g *Game) selectConnect() error { } func (g *Game) searchMatches(username string) { + loadingText := newCenteredText(gotext.Get("Loading...")) + if AutoEnableTouchInput { + loadingText.SetFont(mediumFont, fontMutex) + } + g.lobby.historyList.Clear() g.lobby.historyList.SetSelectionMode(etk.SelectNone) - g.lobby.historyList.AddChildAt(newCenteredText(gotext.Get("Loading...")), 0, 0) + g.lobby.historyList.AddChildAt(loadingText, 0, 0) g.Client.Out <- []byte(fmt.Sprintf("history %s", username)) } @@ -2248,7 +2277,6 @@ func (g *Game) handleInput(keys []ebiten.Key) error { return nil } else if AutoEnableTouchInput { scheduleFrame() - log.Println("SCHEDULE FRAME ON KEYS") } if !g.loggedIn { @@ -2439,7 +2467,6 @@ func (g *Game) Update() error { g.pressedKeys = inpututil.AppendPressedKeys(g.pressedKeys[:0]) if len(g.pressedKeys) > 0 { - log.Printf("PRESSED %+v", g.pressedKeys) scheduleFrame() } @@ -2472,7 +2499,6 @@ func (g *Game) Update() error { if cx == 0 && cy == 0 { g.touchIDs = inpututil.AppendJustPressedTouchIDs(g.touchIDs[:0]) for _, id := range g.touchIDs { - g.EnableTouchInput() cx, cy = ebiten.TouchPosition(id) if cx != 0 || cy != 0 { if g.handleTouch(image.Point{cx, cy}) { @@ -2493,18 +2519,10 @@ func (g *Game) Update() error { if AutoEnableTouchInput { g.pressedRunes = ebiten.AppendInputChars(g.pressedRunes[:0]) if len(g.pressedRunes) != 0 { - log.Printf("PRESSED RUNES %+v", g.pressedRunes) scheduleFrame() } } - if !g.TouchInput { - g.touchIDs = inpututil.AppendJustPressedTouchIDs(g.touchIDs[:0]) - if len(g.touchIDs) > 0 { - g.EnableTouchInput() - } - } - if len(ebiten.AppendTouchIDs(g.touchIDs[:0])) != 0 { scheduleFrame() } @@ -2622,8 +2640,9 @@ func (g *Game) Draw(screen *ebiten.Image) { g.spinnerIndex = 0 } - if g.scaleFactor != 1.0 { - g.drawBuffer.Write([]byte(fmt.Sprintf("SCA %0.1f\n", g.scaleFactor))) + scale := etk.ScaleFactor() + if scale != 1.0 { + g.drawBuffer.Write([]byte(fmt.Sprintf("SCA %0.1f\n", scale))) } g.drawBuffer.Write([]byte(fmt.Sprintf("FPS %c %0.0f", spinner[g.spinnerIndex], ebiten.ActualFPS()))) @@ -2648,44 +2667,32 @@ func (g *Game) portraitView() bool { return g.screenH-g.screenW >= 100 } -func (g *Game) scale(v int) int { - return int(float64(v) * g.scaleFactor) -} - func (g *Game) layoutConnect() { g.needLayoutConnect = false - infoHeight := 108 - if defaultFontSize == extraLargeFontSize { - infoHeight = 108 * 2 + headerHeight := etk.Scale(60) + infoHeight := etk.Scale(108) + if AutoEnableTouchInput { + headerHeight = etk.Scale(20) } if ShowServerSettings { - connectGrid.SetRowSizes(60, fieldHeight, fieldHeight, fieldHeight, g.scale(baseButtonHeight), g.scale(baseButtonHeight), infoHeight) - registerGrid.SetRowSizes(60, fieldHeight, fieldHeight, fieldHeight, fieldHeight, g.scale(baseButtonHeight), infoHeight) - resetGrid.SetRowSizes(60, fieldHeight, fieldHeight, g.scale(baseButtonHeight), infoHeight) + connectGrid.SetRowSizes(headerHeight, fieldHeight, fieldHeight, fieldHeight, etk.Scale(baseButtonHeight), etk.Scale(baseButtonHeight), infoHeight) + registerGrid.SetRowSizes(headerHeight, fieldHeight, fieldHeight, fieldHeight, fieldHeight, etk.Scale(baseButtonHeight), infoHeight) + resetGrid.SetRowSizes(headerHeight, fieldHeight, fieldHeight, etk.Scale(baseButtonHeight), infoHeight) } else { - connectGrid.SetRowSizes(60, fieldHeight, fieldHeight, g.scale(baseButtonHeight), g.scale(baseButtonHeight), infoHeight) - registerGrid.SetRowSizes(60, fieldHeight, fieldHeight, fieldHeight, g.scale(baseButtonHeight), infoHeight) - resetGrid.SetRowSizes(60, fieldHeight, g.scale(baseButtonHeight), infoHeight) - } - - if !g.loadedConnect { - updateAllButtons(connectGrid) - g.loadedConnect = true + connectGrid.SetRowSizes(headerHeight, fieldHeight, fieldHeight, etk.Scale(baseButtonHeight), etk.Scale(baseButtonHeight), infoHeight) + registerGrid.SetRowSizes(headerHeight, fieldHeight, fieldHeight, fieldHeight, etk.Scale(baseButtonHeight), infoHeight) + resetGrid.SetRowSizes(headerHeight, fieldHeight, etk.Scale(baseButtonHeight), infoHeight) } } func (g *Game) layoutLobby() { g.needLayoutLobby = false - g.lobby.buttonBarHeight = g.scale(baseButtonHeight) + g.lobby.buttonBarHeight = etk.Scale(baseButtonHeight) + g.lobby.rebuildButtonsGrid() g.setBufferRects() - - if !g.loadedLobby { - updateAllButtons(game.lobby.buttonsGrid) - g.loadedLobby = true - } } func (g *Game) layoutBoard() { @@ -2719,12 +2726,6 @@ func (g *Game) layoutBoard() { g.setBufferRects() g.Board.widget.SetRect(image.Rect(0, 0, g.screenW, g.screenH)) - - if !g.loadedBoard { - updateAllButtons(game.Board.menuGrid) - updateAllButtons(game.Board.leaveGameGrid) - g.loadedBoard = true - } } func (g *Game) bufferPadding() int { @@ -2741,8 +2742,14 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { g.Lock() defer g.Unlock() - s := ebiten.DeviceScaleFactor() - outsideWidth, outsideHeight = int(float64(outsideWidth)*s), int(float64(outsideHeight)*s) + if !g.initialized { + g.initialize() + g.initialized = true + } + + originalWidth, originalHeight := outsideWidth, outsideHeight + + outsideWidth, outsideHeight = etk.Scale(outsideWidth), etk.Scale(outsideHeight) if outsideWidth < minWidth { outsideWidth = minWidth } @@ -2755,37 +2762,8 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { g.forceLayout = false g.screenW, g.screenH = outsideWidth, outsideHeight - g.scaleFactor = s scheduleFrame() - b := g.Board - if s >= 1.25 { - lobbyStatusBufferHeight = int(50 * s) - g.Board.verticalBorderSize = baseBoardVerticalSize * 1.5 - if b.fontFace != largeFont { - b.fontFace = largeFont - b.fontUpdated() - } - } else { - if b.fontFace != mediumFont { - b.fontFace = mediumFont - b.fontUpdated() - } - } - - statusBuffer.SetScrollBarColors(etk.Style.ScrollAreaColor, etk.Style.ScrollHandleColor) - gameBuffer.SetScrollBarColors(etk.Style.ScrollAreaColor, etk.Style.ScrollHandleColor) - inputBuffer.Field.SetScrollBarColors(etk.Style.ScrollAreaColor, etk.Style.ScrollHandleColor) - g.lobby.availableMatchesList.SetScrollBarColors(etk.Style.ScrollAreaColor, etk.Style.ScrollHandleColor) - g.lobby.historyList.SetScrollBarColors(etk.Style.ScrollAreaColor, etk.Style.ScrollHandleColor) - - { - scrollBarWidth := g.scale(32) - statusBuffer.SetScrollBarWidth(scrollBarWidth) - gameBuffer.SetScrollBarWidth(scrollBarWidth) - inputBuffer.Field.SetScrollBarWidth(scrollBarWidth) - } - fontMutex.Lock() g.bufferWidth = etk.BoundString(g.Board.fontFace, strings.Repeat("A", bufferCharacterWidth)).Dx() fontMutex.Unlock() @@ -2793,7 +2771,7 @@ func (g *Game) Layout(outsideWidth, outsideHeight int) (int, int) { g.bufferWidth = int(float64(g.screenW) * maxStatusWidthRatio) } - etk.Layout(g.screenW, g.screenH) + etk.Layout(originalWidth, originalHeight) g.needLayoutConnect = true g.needLayoutLobby = true @@ -2859,27 +2837,7 @@ func acceptInput(text string) (handled bool) { } func (g *Game) itemHeight() int { - if defaultFontSize == extraLargeFontSize { - return 72 - } - return 48 -} - -func (g *Game) EnableTouchInput() { - if g.TouchInput { - return - } - g.TouchInput = true - - // Update layout. - g.forceLayout = true - - b := g.Board - b.matchStatusGrid.Clear() - b.matchStatusGrid.AddChildAt(b.timerLabel, 0, 0, 1, 1) - b.matchStatusGrid.AddChildAt(b.clockLabel, 1, 0, 1, 1) - - b.fontUpdated() + return etk.Scale(48) } func (g *Game) toggleProfiling() error { @@ -3071,27 +3029,7 @@ func newCenteredText(text string) *etk.Text { func centerInput(input *etk.Input) { input.Field.SetVertical(messeji.AlignCenter) - paddingSize := 5 - if defaultFontSize == extraLargeFontSize { - paddingSize = 20 - } - input.Field.SetPadding(paddingSize) -} - -func updateAllButtons(w etk.Widget) { - for _, c := range w.Children() { - updateAllButtons(c) - } - - f := largeFont - if defaultFontSize == extraLargeFontSize { - f = extraLargeFont - } - - btn, ok := w.(*etk.Button) - if ok && (defaultFontSize == extraLargeFontSize || btn != game.Board.showMenuButton) { - btn.Label.SetFont(f, fontMutex) - } + input.Field.SetPadding(etk.Scale(5)) } // Short description. diff --git a/game/game_android.go b/game/game_android.go index a2de218..c0b7d83 100644 --- a/game/game_android.go +++ b/game/game_android.go @@ -24,7 +24,6 @@ const ( ShowServerSettings = true APPNAME = "boxcars-android" fieldHeight = 100 - defaultFontSize = extraLargeFontSize ) func init() { diff --git a/game/game_standard.go b/game/game_standard.go index ce15469..fb6cb84 100644 --- a/game/game_standard.go +++ b/game/game_standard.go @@ -21,7 +21,6 @@ const ( ShowServerSettings = false APPNAME = "boxcars" fieldHeight = 50 - defaultFontSize = largeFontSize ) func DefaultLocale() string { diff --git a/game/game_web.go b/game/game_web.go index 4abbc28..a9a451b 100644 --- a/game/game_web.go +++ b/game/game_web.go @@ -17,7 +17,6 @@ const ( ShowServerSettings = false APPNAME = "boxcars" fieldHeight = 50 - defaultFontSize = largeFontSize ) func DefaultLocale() string { diff --git a/game/lobby.go b/game/lobby.go index 3908f60..95835b5 100644 --- a/game/lobby.go +++ b/game/lobby.go @@ -31,19 +31,22 @@ const ( lobbyButtonHistoryView ) -const ( +var ( lobbyIndentA = 200 lobbyIndentB = 350 ) -type lobbyButton struct { - label string +func init() { + if AutoEnableTouchInput { + lobbyIndentA, lobbyIndentB = lobbyIndentA/3, lobbyIndentB/3 + } } -var mainButtons []*lobbyButton -var createButtons []*lobbyButton -var cancelJoinButtons []*lobbyButton -var historyButtons []*lobbyButton +var mainButtons []string +var mainShortButtons []string +var createButtons []string +var cancelJoinButtons []string +var historyButtons []string type lobby struct { buttonBarHeight int @@ -94,26 +97,32 @@ type lobby struct { } func NewLobby() *lobby { - mainButtons = []*lobbyButton{ - {gotext.Get("Refresh matches")}, - {gotext.Get("Create match")}, - {gotext.Get("Join match")}, + mainButtons = []string{ + gotext.Get("Refresh matches"), + gotext.Get("Create match"), + gotext.Get("Join match"), } - createButtons = []*lobbyButton{ - {gotext.Get("Cancel")}, - {gotext.Get("Create match")}, + mainShortButtons = []string{ + gotext.Get("Refresh"), + gotext.Get("Create"), + gotext.Get("Join"), } - cancelJoinButtons = []*lobbyButton{ - {gotext.Get("Cancel")}, - {gotext.Get("Join match")}, + createButtons = []string{ + gotext.Get("Cancel"), + gotext.Get("Create match"), } - historyButtons = []*lobbyButton{ - {gotext.Get("Return")}, - {gotext.Get("Download replay")}, - {gotext.Get("View replay")}, + cancelJoinButtons = []string{ + gotext.Get("Cancel"), + gotext.Get("Join match"), + } + + historyButtons = []string{ + gotext.Get("Return"), + gotext.Get("Download replay"), + gotext.Get("View replay"), } l := &lobby{ @@ -121,16 +130,18 @@ func NewLobby() *lobby { buttonsGrid: etk.NewGrid(), } - indentA, indentB := lobbyIndentA, lobbyIndentB - if defaultFontSize == extraLargeFontSize { - indentA, indentB = int(float64(indentA)*1.3), int(float64(indentB)*1.3) + loadingText := newCenteredText(gotext.Get("Loading...")) + if AutoEnableTouchInput { + loadingText.SetFont(mediumFont, fontMutex) } + indentA, indentB := etk.Scale(lobbyIndentA), etk.Scale(lobbyIndentB) + matchList := etk.NewList(game.itemHeight(), l.selectMatch) matchList.SetSelectionMode(etk.SelectRow) matchList.SetColumnSizes(indentA, indentB-indentA, indentB-indentA, -1) matchList.SetHighlightColor(color.RGBA{79, 55, 30, 255}) - matchList.AddChildAt(newCenteredText(gotext.Get("Loading...")), 0, 0) + matchList.AddChildAt(loadingText, 0, 0) l.availableMatchesList = matchList return l } @@ -178,6 +189,9 @@ func (l *lobby) setGameList(games []bgammon.GameListing) { txt.SetScrollBarVisible(false) txt.SetWordWrap(false) txt.SetVertical(messeji.AlignCenter) + if AutoEnableTouchInput { + txt.SetFont(mediumFont, fontMutex) + } return txt } @@ -198,10 +212,14 @@ func (l *lobby) setGameList(games []bgammon.GameListing) { } else { rating = fmt.Sprintf("%d", entry.Rating) } + nameLabel := newLabel(entry.Name) + if AutoEnableTouchInput { + nameLabel.SetWordWrap(true) + } l.availableMatchesList.AddChildAt(newLabel(status), 0, i) l.availableMatchesList.AddChildAt(newLabel(rating), 1, i) l.availableMatchesList.AddChildAt(newLabel(fmt.Sprintf("%d", entry.Points)), 2, i) - l.availableMatchesList.AddChildAt(newLabel(entry.Name), 3, i) + l.availableMatchesList.AddChildAt(nameLabel, 3, i) } if lastSelection >= 0 && lastSelection < len(l.games) { @@ -214,13 +232,15 @@ func (l *lobby) setGameList(games []bgammon.GameListing) { } } -func (l *lobby) getButtons() []*lobbyButton { +func (l *lobby) getButtons() []string { if l.showCreateGame { return createButtons } else if l.showJoinGame { return cancelJoinButtons } else if l.showHistory { return historyButtons + } else if AutoEnableTouchInput && game.portraitView() { + return mainShortButtons } return mainButtons } @@ -350,8 +370,8 @@ func (l *lobby) rebuildButtonsGrid() { r := l.buttonsGrid.Rect() l.buttonsGrid.Clear() - for i, btn := range l.getButtons() { - l.buttonsGrid.AddChildAt(etk.NewButton(btn.label, l.selectButton(i)), i, 0, 1, 1) + for i, label := range l.getButtons() { + l.buttonsGrid.AddChildAt(etk.NewButton(label, l.selectButton(i)), i, 0, 1, 1) } l.buttonsGrid.SetRect(r) diff --git a/game/locales/boxcars.pot b/game/locales/boxcars.pot index 0fa6795..6c75ab4 100644 --- a/game/locales/boxcars.pot +++ b/game/locales/boxcars.pot @@ -70,6 +70,9 @@ msgstr "" msgid "Connecting..." msgstr "" +msgid "Create" +msgstr "" + msgid "Create Match" msgstr "" @@ -142,6 +145,9 @@ msgstr "" msgid "Instant" msgstr "" +msgid "Join" +msgstr "" + msgid "Join match" msgstr "" @@ -232,6 +238,9 @@ msgstr "" msgid "Reconnecting" msgstr "" +msgid "Refresh" +msgstr "" + msgid "Refresh matches" msgstr "" diff --git a/game/tutorial.go b/game/tutorial.go index 5386f6f..9213418 100644 --- a/game/tutorial.go +++ b/game/tutorial.go @@ -102,13 +102,13 @@ func (w *tutorialWidget) setPage(page int) { } message = title + "\n\n" + message - w.grid.SetColumnSizes(-1, -1, -1, -1) + w.grid.SetColumnSizes(-1, -1, -1, -1, -1, -1) w.grid.SetRowSizes(-1, -1, -1, -1) - w.grid.AddChildAt(w.newTutorialBox(), 0, 0, 4, 1) + w.grid.AddChildAt(w.newTutorialBox(), 0, 0, 6, 1) w.grid.AddChildAt(w.newTutorialBox(), 0, 1, 1, 2) - w.grid.AddChildAt(w.dialogText(message), 1, 1, 2, 2) - w.grid.AddChildAt(w.newTutorialBox(), 3, 1, 1, 2) - w.grid.AddChildAt(w.newTutorialBox(), 0, 3, 4, 1) + w.grid.AddChildAt(w.dialogText(message), 1, 1, 4, 2) + w.grid.AddChildAt(w.newTutorialBox(), 5, 1, 1, 2) + w.grid.AddChildAt(w.newTutorialBox(), 0, 3, 6, 1) } type tutorialDialog struct { diff --git a/go.mod b/go.mod index 1ad572b..8bbfb01 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.17 require ( code.rocket9labs.com/tslocum/bgammon v0.0.0-20240117214045-3607efee4129 code.rocket9labs.com/tslocum/bgammon-tabula-bot v0.0.0-20240120074310-6968c426a4e1 - code.rocket9labs.com/tslocum/etk v0.0.0-20240122001849-b8e1658b3f49 + code.rocket9labs.com/tslocum/etk v0.0.0-20240122050631-9e17ce631967 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 diff --git a/go.sum b/go.sum index 34a0b63..e2ae33c 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ code.rocket9labs.com/tslocum/bgammon v0.0.0-20240117214045-3607efee4129 h1:wguf0 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-20240120074310-6968c426a4e1 h1:FsUNZJjzoYixG36Hxf0eYov0no6GGWjEVdmvGWjol7Y= code.rocket9labs.com/tslocum/bgammon-tabula-bot v0.0.0-20240120074310-6968c426a4e1/go.mod h1:w6xR2lWW3xUo7KlCOaJ+Jbs29AfQVRQEJ2W1vb0IuOo= -code.rocket9labs.com/tslocum/etk v0.0.0-20240122001849-b8e1658b3f49 h1:OcdDIzebupJx2uj6lKw6uip537C+RTa39RBpsvOErPc= -code.rocket9labs.com/tslocum/etk v0.0.0-20240122001849-b8e1658b3f49/go.mod h1:2IXUt2b3de6r0IX5W5uR1vvTw1Z+JcX/ATC1woaaW2E= +code.rocket9labs.com/tslocum/etk v0.0.0-20240122050631-9e17ce631967 h1:1utGdjqNQg+7hrduWOfqQpiBeRpbinCrY7mZZi+y7oI= +code.rocket9labs.com/tslocum/etk v0.0.0-20240122050631-9e17ce631967/go.mod h1:2IXUt2b3de6r0IX5W5uR1vvTw1Z+JcX/ATC1woaaW2E= 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=