Golang示例:使用Ebitengine实现六边形棋盘游戏

Golang示例:使用Ebitengine实现六边形棋盘游戏 你好,Go社区,

我写了一个使用Ebitengine的简单六边形棋盘示例。我将六角星寻路算法放在了一个本地库astarhexlib中,因为我没有找到其他Ebitengine的六边形示例。

https://github.com/ConValance/ebitengine-hexboard

1 回复

更多关于Golang示例:使用Ebitengine实现六边形棋盘游戏的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


// 这是一个使用Ebitengine实现六边形棋盘游戏的示例
// 展示了如何集成astarhexlib库进行六边形网格寻路

package main

import (
    "github.com/hajimehoshi/ebiten/v2"
    "github.com/ConValance/ebitengine-hexboard/astarhexlib"
    "image/color"
    "math"
)

// 六边形棋盘配置
const (
    hexSize   = 30  // 六边形外接圆半径
    hexWidth  = hexSize * 2
    hexHeight = math.Sqrt(3) * hexSize
)

type HexBoard struct {
    grid      [][]*HexTile
    path      []astarhexlib.HexCoord
    pathfinder *astarhexlib.PathFinder
}

type HexTile struct {
    q, r      int           // 立方体坐标
    x, y      float64       // 屏幕坐标
    color     color.Color
    isBlocked bool
}

func (h *HexBoard) Layout(outsideWidth, outsideHeight int) (screenWidth, screenHeight int) {
    return 800, 600
}

func (h *HexBoard) Update() error {
    // 处理鼠标点击进行寻路
    if ebiten.IsMouseButtonPressed(ebiten.MouseButtonLeft) {
        x, y := ebiten.CursorPosition()
        hexCoord := h.pixelToHex(float64(x), float64(y))
        
        // 使用astarhexlib进行寻路
        if h.pathfinder != nil {
            start := astarhexlib.HexCoord{Q: 0, R: 0}
            end := astarhexlib.HexCoord{Q: hexCoord.q, R: hexCoord.r}
            h.path = h.pathfinder.FindPath(start, end)
        }
    }
    return nil
}

func (h *HexBoard) Draw(screen *ebiten.Image) {
    // 绘制所有六边形
    for _, row := range h.grid {
        for _, hex := range row {
            h.drawHex(screen, hex)
        }
    }
    
    // 绘制路径
    for _, coord := range h.path {
        hex := h.getHexAt(coord.Q, coord.R)
        if hex != nil {
            h.drawHexHighlight(screen, hex, color.RGBA{255, 0, 0, 128})
        }
    }
}

// 像素坐标转换为六边形坐标
func (h *HexBoard) pixelToHex(x, y float64) HexTile {
    q := (x * math.Sqrt(3)/3 - y/3) / hexSize
    r := y * 2/3 / hexSize
    return h.cubeToHex(h.cubeRound(q, -q-r, r))
}

// 立方体坐标取整
func (h *HexBoard) cubeRound(x, y, z float64) (int, int, int) {
    rx := math.Round(x)
    ry := math.Round(y)
    rz := math.Round(z)
    
    xDiff := math.Abs(rx - x)
    yDiff := math.Abs(ry - y)
    zDiff := math.Abs(rz - z)
    
    if xDiff > yDiff && xDiff > zDiff {
        rx = -ry - rz
    } else if yDiff > zDiff {
        ry = -rx - rz
    } else {
        rz = -rx - ry
    }
    
    return int(rx), int(ry), int(rz)
}

// 立方体坐标转轴向坐标
func (h *HexBoard) cubeToHex(x, y, z int) HexTile {
    q := x
    r := z
    return HexTile{q: q, r: r}
}

// 绘制单个六边形
func (h *HexBoard) drawHex(screen *ebiten.Image, hex *HexTile) {
    points := make([]ebiten.Vertex, 6)
    for i := 0; i < 6; i++ {
        angle := 2 * math.Pi / 6 * float64(i)
        x := hex.x + hexSize*math.Cos(angle)
        y := hex.y + hexSize*math.Sin(angle)
        
        points[i] = ebiten.Vertex{
            DstX:   float32(x),
            DstY:   float32(y),
            SrcX:   0,
            SrcY:   0,
            ColorR: 1,
            ColorG: 1,
            ColorB: 1,
            ColorA: 1,
        }
    }
    
    // 绘制六边形边框
    indices := []uint16{0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 0}
    screen.DrawTriangles(points, indices, nil, &ebiten.DrawTrianglesOptions{
        FillRule: ebiten.EvenOdd,
    })
}

// 绘制高亮六边形
func (h *HexBoard) drawHexHighlight(screen *ebiten.Image, hex *HexTile, clr color.Color) {
    r, g, b, a := clr.RGBA()
    points := make([]ebiten.Vertex, 6)
    
    for i := 0; i < 6; i++ {
        angle := 2 * math.Pi / 6 * float64(i)
        x := hex.x + (hexSize-2)*math.Cos(angle)
        y := hex.y + (hexSize-2)*math.Sin(angle)
        
        points[i] = ebiten.Vertex{
            DstX:   float32(x),
            DstY:   float32(y),
            SrcX:   0,
            SrcY:   0,
            ColorR: float32(r) / 0xFFFF,
            ColorG: float32(g) / 0xFFFF,
            ColorB: float32(b) / 0xFFFF,
            ColorA: float32(a) / 0xFFFF,
        }
    }
    
    indices := []uint16{0, 1, 2, 2, 3, 4, 4, 5, 0}
    screen.DrawTriangles(points, indices, nil, &ebiten.DrawTrianglesOptions{
        FillRule: ebiten.NonZero,
    })
}

func main() {
    board := &HexBoard{}
    board.pathfinder = astarhexlib.NewPathFinder()
    
    // 初始化网格
    gridSize := 10
    board.grid = make([][]*HexTile, gridSize)
    for q := 0; q < gridSize; q++ {
        board.grid[q] = make([]*HexTile, gridSize)
        for r := 0; r < gridSize; r++ {
            x := hexSize * (3.0/2 * float64(q))
            y := hexSize * (math.Sqrt(3)/2*float64(q) + math.Sqrt(3)*float64(r))
            
            board.grid[q][r] = &HexTile{
                q: q,
                r: r,
                x: x + 100, // 偏移量
                y: y + 100,
                color: color.White,
            }
        }
    }
    
    ebiten.SetWindowSize(800, 600)
    ebiten.SetWindowTitle("Ebitengine Hex Board")
    if err := ebiten.RunGame(board); err != nil {
        panic(err)
    }
}

这个示例展示了如何使用Ebitengine创建六边形棋盘,并集成astarhexlib库进行六边形网格寻路。主要功能包括:

  1. 六边形网格渲染:使用立方体坐标系统绘制六边形网格
  2. 坐标转换:实现像素坐标到六边形坐标的转换算法
  3. 路径查找:集成astarhexlib库进行A*寻路
  4. 交互功能:通过鼠标点击选择目标位置并显示路径

代码中包含了完整的六边形几何计算、坐标系统转换和图形渲染逻辑。astarhexlib库负责处理六边形网格特有的寻路算法,而Ebitengine负责图形渲染和用户交互。

回到顶部