iT邦幫忙

2025 iThome 鐵人賽

DAY 8
2

🎯 主題

根據格內數字畫出不同顏色與文字大小

📖 說明

在 2048 遊戲中,棋盤為 4x4 的格子。每個格子可能包含數字(如 2、4、8 ... 2048),需要根據不同數字顯示對應的背景顏色與文字樣式,以提供玩家清晰的視覺提示:

  • 數字越大,顏色越深
  • 數字越大,文字大小越小(避免超出格子邊界)

範例對應規則(可擴充):

數字 背景色 字體大小 字體顏色
2 淺灰色 黑色
4 米黃色 黑色
8 橘色 白色
16 紅色 白色
32 深紅色 白色
64 金色 白色
128+ 漸層 / 更深顏色 白色

程式

type GameLayout struct {
	gameInstance *game.Game
}

// drawCell - 透過目前值來畫出目前 cell 的格子顏色
func (g *GameLayout) drawCell(screen *ebiten.Image, value, row, col int) {
	cellXPos := padding + col*(tileSize+padding)
	cellYPos := padding + row*(tileSize+padding)
	cellColor := getTileColor(value)
	cell := ebiten.NewImage(tileSize, tileSize)
	cell.Fill(cellColor)
	op := &ebiten.DrawImageOptions{}
	op.GeoM.Translate(float64(cellXPos), float64(cellYPos))
	op.ColorScale.ScaleWithColor(g.tileBackgroundColor(value))
	screen.DrawImage(cell, op)
}

// drawTileText -  透過目前值來畫出目前 cell 的文字顏色
func (g *GameLayout) drawTileText(screen *ebiten.Image, value, row, col int) {
	if value > 0 {
		// 繪製數字 (置中)
		textValue := fmt.Sprintf("%d", value)
		textXPos := (col+1)*padding + col*tileSize + (tileSize)/2
		textYPos := (row+1)*padding + row*tileSize + (tileSize)/2
		textOpts := &text.DrawOptions{}
		textOpts.ColorScale.ScaleWithColor(getTileColor(value))
		textOpts.PrimaryAlign = text.AlignCenter
		textOpts.SecondaryAlign = text.AlignCenter
		textOpts.GeoM.Translate(float64(textXPos), float64(textYPos))
		text.Draw(screen, textValue, &text.GoTextFace{
			Source: mplusFaceSource,
			Size:   getFontSize(value),
		}, textOpts)
	}
}

func (g *GameLayout) Draw(screen *ebiten.Image) {
	// 背景色
	screen.Fill(color.RGBA{250, 248, 239, 255})
	// 畫 4x4 格子
	for row := 0; row < gridSize; row++ {
		for col := 0; col < gridSize; col++ {
			// 取出值
			value := g.gameInstance.Data(row, col)
			// 畫格子背景
			g.drawCell(screen, value, row, col)
			// 畫文字
			g.drawTileText(screen, value, row, col)
		}
	}
}

main function 執行

func main() {
	ebiten.SetWindowSize(layout.WinWidth, layout.WinHeight)
	ebiten.SetWindowTitle("2048 - Day 8 測試")
	gameInstance := game.NewGame()
	gameInstance.Init([][]int{
		{2, 4, 8, 16},
		{32, 64, 128, 256},
		{512, 1024, 2048, 4096},
		{0, 0, 0, 8192},
	}, nil, nil)
	gameLayout := layout.NameGameLayout(gameInstance)
	if err := ebiten.RunGame(gameLayout); err != nil {
		log.Fatal(err)
	}
}

畫面

https://ithelp.ithome.com.tw/upload/images/20250822/20111580gIyUU4h34m.png

✅ 驗收條件

  • 棋盤每個格子皆能正確顯示數字與對應顏色。
  • 當數字增加時,背景顏色變化符合規則。
  • 不同數字文字大小能自動調整,避免超出格子。
  • 空格(數字 = 0 或無數字)顯示為空白背景。

📌 本日收穫

  • 學會在 Ebiten 中繪製數字格與背景顏色。
  • 理解如何載入 TTF 字體 並在遊戲中繪製文字。
  • 釐清 text.Draw 與字體大小的關係,知道要用 truetype.NewFace 來控制字體大小。

📌 明日預計(Day 9)

  • 將字型繪製整合到 2048 遊戲格子,並根據數字動態調整字體大小(例如 2 → 大字,2048 → 小字)。
  • 嘗試加入 顏色與動畫效果(如數字合併時的閃爍或放大動畫)。

上一篇
2048遊戲: Ebiten 畫面初始渲染
下一篇
2048 遊戲: 鍵盤控制滑動 + 整合更新邏輯
系列文
在 ai 時代 gopher 遊戲開發者的 30 天自我養成20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言