main.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. package main
  2. import (
  3. "embed"
  4. "fmt"
  5. "net/http"
  6. "f1-game/internal/algorithm/astar"
  7. "f1-game/internal/algorithm/astar6"
  8. "f1-game/internal/types"
  9. cherryTime "github.com/cherry-game/cherry/extend/time"
  10. "github.com/gin-gonic/gin"
  11. )
  12. //go:embed index.html
  13. var staticFiles embed.FS
  14. var (
  15. aStar *astar.AStar
  16. aStarV6 *astar6.AStar
  17. // mapSize represents the width and height of the grid
  18. mapSize int32 = 1000
  19. )
  20. // PathRequest represents the request body for finding a path
  21. // Contains start point, end point, and optional obstacle points
  22. type PathRequest struct {
  23. StartX int32 `json:"startX"`
  24. StartY int32 `json:"startY"`
  25. EndX int32 `json:"endX"`
  26. EndY int32 `json:"endY"`
  27. Obstacles []Point `json:"obstacles"` // 障碍点列表
  28. }
  29. type Point struct {
  30. X int32 `json:"x"`
  31. Y int32 `json:"y"`
  32. }
  33. func main() {
  34. // Initialize A*
  35. // Initializing with all 1 (walkable)
  36. mapData := make([][]int32, mapSize)
  37. for i := range mapData {
  38. mapData[i] = make([]int32, mapSize)
  39. for j := range mapData[i] {
  40. mapData[i][j] = 1 //可走
  41. }
  42. }
  43. config := astar.Config{
  44. Width: mapSize,
  45. Height: mapSize,
  46. MapData: mapData,
  47. IsWalkableFunc: nil,
  48. IsDebug: false,
  49. }
  50. aStar = astar.New(config)
  51. // 初始化 astar6 算法
  52. config6 := astar6.Config{
  53. Min: types.NewPoint(1, 1),
  54. Max: types.NewPoint(mapSize, mapSize),
  55. MapData: mapData,
  56. IsWalkableFunc: nil,
  57. IsDebug: false,
  58. }
  59. aStarV6 = astar6.New(config6)
  60. r := gin.Default()
  61. r.GET("/", func(c *gin.Context) {
  62. // Serve the embedded index.html
  63. content, err := staticFiles.ReadFile("index.html")
  64. if err != nil {
  65. c.String(http.StatusInternalServerError, "Could not read index.html")
  66. return
  67. }
  68. c.Data(http.StatusOK, "text/html; charset=utf-8", content)
  69. })
  70. // POST /find-path - 寻找路径接口
  71. // 功能:根据起点、终点和障碍点列表,使用A*算法计算最优路径
  72. r.POST("/find-path", func(c *gin.Context) {
  73. var req PathRequest
  74. if err := c.ShouldBindJSON(&req); err != nil {
  75. c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
  76. return
  77. }
  78. // 重置缓存
  79. aStar.ResetCache()
  80. // 设置障碍点(0表示不可行走)
  81. for _, obs := range req.Obstacles {
  82. aStar.SetObstacles(obs.X, obs.Y, false)
  83. }
  84. ct := cherryTime.Now()
  85. pathNodes, err := aStar.FindPath(req.StartX, req.StartY, req.EndX, req.EndY)
  86. costTime := ct.NowDiffMillisecond()
  87. if !err {
  88. c.JSON(http.StatusOK, gin.H{"path": []Point{}, "error": err}) // Return empty path on error (no path found)
  89. return
  90. }
  91. // Convert to simple Point struct for JSON
  92. path := make([]Point, len(pathNodes))
  93. for i, node := range pathNodes {
  94. path[i] = Point{
  95. X: node.X(),
  96. Y: node.Y(),
  97. }
  98. }
  99. c.JSON(http.StatusOK, gin.H{
  100. "path": path,
  101. "costTime": costTime,
  102. })
  103. })
  104. // POST /find-path-astar6 - 使用 astar6 寻找路径接口
  105. // 功能:根据起点、终点和障碍点列表,使用 astar6 算法计算最优路径
  106. r.POST("/find-path-astar6", func(c *gin.Context) {
  107. var req PathRequest
  108. if err := c.ShouldBindJSON(&req); err != nil {
  109. c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
  110. return
  111. }
  112. aStarV6.ResetCache()
  113. // 设置障碍点(0表示不可行走)
  114. for _, obs := range req.Obstacles {
  115. aStarV6.SetNode(obs.X, obs.Y, false)
  116. }
  117. ct := cherryTime.Now()
  118. pathNodes, found := aStarV6.FindPath(astar6.DefaultFindContext(req.StartX, req.StartY, req.EndX, req.EndY))
  119. costTime := ct.NowDiffMillisecond()
  120. if !found {
  121. c.JSON(http.StatusOK, gin.H{"path": []Point{}, "error": "No path found"})
  122. return
  123. }
  124. // Convert to simple Point struct for JSON
  125. path := make([]Point, len(pathNodes))
  126. for i, node := range pathNodes {
  127. path[i] = Point{
  128. X: node.X(),
  129. Y: node.Y(),
  130. }
  131. }
  132. c.JSON(http.StatusOK, gin.H{
  133. "path": path,
  134. "costTime": costTime,
  135. })
  136. })
  137. fmt.Println("Server running on http://localhost:8080")
  138. r.Run(":8080")
  139. }