python游戏寻路_python模拟实现A*寻路算法
一、簡介
兩點之間尋找最短路徑,要考慮到存在障礙物遮擋和斜線移動的情況。
二、具體說明
說明可以參考下面的鏈接,對A*算法實現的描述。
三、具體實現
1、實現功能
2、尋路具體流程
3、關于F值
f = g + h
g表示當前移動到下一個點的消耗,平移為1,斜移動為 sqrt((x1-x2)**2 +(y1-y2)**2);
h表示當前移動到終點的消耗,不考慮斜移,不考慮障礙物
具體原理請查看下面的參考鏈接。
完整實現:
# -*- coding: utf-8 -*-
import os,sys,random,math
#地圖設置
gameMapWidth = 10
gameMapHeight = 10
gameMap = []
#地圖障礙物
obstacleCount = 5
#塊狀態
ITEM_STAT_NORMAL = 0 #空點
ITEM_STAT_OBSTACLE = 1 #障礙物
ITEM_STAT_START = 2 #起點
ITEM_STAT_END = 3 #終點
#起點和終點
spNum = -1
epNum = -1
#每塊的屬性
class Item:
def __init__(self,x,y,status):
self.x = x
self.y = y
self.status = status
self.mf = -1
self.mg = -1
self.mh = -1
self.mParent = None
self.isPath = 0
#初始化地圖
def initMap():
for wc in xrange(gameMapWidth):
for hc in xrange(gameMapHeight):
gameMap.append(Item(wc,hc,ITEM_STAT_NORMAL))
#插入障礙物
for oc in xrange(obstacleCount):
choose = random.randint(gameMapWidth,gameMapWidth*gameMapHeight - 1)
gameMap[choose].status = ITEM_STAT_OBSTACLE
global spNum
global epNum
#選取起點和終點
while (spNum == -1):
choose = random.randint(0,gameMapWidth*gameMapHeight - 1)
if gameMap[choose].status == 0:
spNum = choose
gameMap[spNum].status = ITEM_STAT_START
while (epNum == -1):
choose = random.randint(0,gameMapWidth*gameMapHeight - 1)
if gameMap[choose].status == 0:
epNum = choose
gameMap[epNum].status = ITEM_STAT_END
#輸出地圖信息
def printMap():
for itemc in xrange(len(gameMap)):
if gameMap[itemc].status == ITEM_STAT_START:
print "START",
elif gameMap[itemc].status == ITEM_STAT_END:
print "END ",
elif gameMap[itemc].isPath == 1:
print "path ",
else:
print "%d " %(gameMap[itemc].status),
if (itemc + 1) % gameMapHeight == 0:
print "\n"
#尋路
def findPath():
global spNum
global epNum
#開啟列表
openPointList = []
#關閉列表
closePointList = []
#開啟列表插入起始點
openPointList.append(gameMap[spNum])
while (len(openPointList) > 0):
#尋找開啟列表中最小預算值的點
minFPoint = findPointWithMinF(openPointList)
#從開啟列表移除,添加到關閉列表
openPointList.remove(minFPoint)
closePointList.append(minFPoint)
#找到當前點周圍點
surroundList = findSurroundPoint(minFPoint,closePointList)
#開始尋路
for sp in surroundList:
#存在在開啟列表,說明上一塊查找時并不是最優路徑,考慮此次移動是否是最優路徑
if sp in openPointList:
newPathG = CalcG(sp, minFPoint) #計算新路徑下的G值
if newPathG < sp.mg:
sp.mg = newPathG
sp.mf = sp.mg + sp.mh
sp.mParent = minFPoint
else:
sp.mParent = minFPoint #當前查找到點指向上一個節點
CalcF(sp, gameMap[epNum])
openPointList.append(sp)
if gameMap[epNum] in openPointList:
gameMap[epNum].mParent = minFPoint
break
curp = gameMap[epNum]
while True:
curp.isPath = 1
curp = curp.mParent
if curp == None:
break
print "\n"
printMap()
def CalcG(point, minp):
return math.sqrt((point.x - point.mParent.x)**2 + (point.y - point.mParent.y)**2) + minp.mg
#計算每個點的F值
def CalcF(point,endp):
h = abs(endp.x - point.x) + abs(endp.y - point.y)
g = 0
if point.mParent == None:
g = 0
else:
g = point.mParent.mg + math.sqrt((point.x - point.mParent.x)**2 + (point.y - point.mParent.y)**2)
point.mg = g
point.mh = h
point.mf = g + h
return
#不能是障礙塊,不包含在關閉列表中
def notObstacleAndClose(point,closePointList):
if point not in closePointList and point.status != ITEM_STAT_OBSTACLE:
return True
return False
#查找周圍塊
def findSurroundPoint(point,closePointList):
surroundList = []
up = None
down = None
left = None
right = None
leftUp = None
rightUp = None
leftDown = None
rightDown = None
#上面的點存在
if point.x > 0:
up = gameMap[gameMapHeight*(point.x - 1) + point.y]
if notObstacleAndClose(up,closePointList):
surroundList.append(up)
#下面的點存在
if point.x < gameMapWidth - 1:
down = gameMap[gameMapHeight*(point.x + 1)+ point.y]
if notObstacleAndClose(down,closePointList):
surroundList.append(down)
#左邊的點存在
if point.y > 0:
left = gameMap[gameMapHeight*(point.x) + point.y - 1]
if notObstacleAndClose(left, closePointList):
surroundList.append(left)
#右邊的點存在
if point.y < gameMapHeight - 1:
right = gameMap[gameMapHeight*(point.x) + point.y + 1]
if notObstacleAndClose(right,closePointList):
surroundList.append(right)
#斜方向的點還需考慮對應正方向不是障礙物
#左上角的點存在
if point.x > 0 and point.y > 0:
leftUp = gameMap[gameMapHeight*(point.x - 1) + point.y - 1]
if notObstacleAndClose(leftUp,closePointList) and left.status != ITEM_STAT_OBSTACLE and up.status != ITEM_STAT_OBSTACLE:
surroundList.append(leftUp)
#右上角的點存在
if point.x > 0 and point.y < gameMapHeight - 1:
rightUp = gameMap[gameMapHeight*(point.x-1) + point.y + 1]
if notObstacleAndClose(rightUp,closePointList) and right.status != ITEM_STAT_OBSTACLE and up.status != ITEM_STAT_OBSTACLE:
surroundList.append(rightUp)
#左下角的點存在
if point.x < gameMapWidth - 1 and point.y > 0:
leftDown = gameMap[gameMapHeight*(point.x+1) + point.y - 1]
if notObstacleAndClose(leftDown,closePointList) and left.status != ITEM_STAT_OBSTACLE and down.status != ITEM_STAT_OBSTACLE:
surroundList.append(leftDown)
#右下角的點存在
if point.x < gameMapWidth - 1 and point.y < gameMapHeight - 1:
rightDown = gameMap[gameMapHeight*(point.x+1) + point.y + 1]
if notObstacleAndClose(rightDown,closePointList) and right.status != ITEM_STAT_OBSTACLE and down.status != ITEM_STAT_OBSTACLE:
surroundList.append(rightDown)
return surroundList
#查找list中最小的f值
def findPointWithMinF(openPointList):
f = 0xffffff
temp = None
for pc in openPointList:
if pc.mf < f:
temp = pc
f = pc.mf
return temp
def main():
initMap() ##初始化地圖
printMap() ##輸出初始化地圖信息
findPath() ##查找最優路徑
#入口
main()
參考:
https://www.gamedev.net/articles/programming/artificial-intelligence/a-pathfinding-for-beginners-r2003/
https://blog.csdn.net/qq_33747722/article/details/78436919
總結
以上是生活随笔為你收集整理的python游戏寻路_python模拟实现A*寻路算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: P2P网络简介
- 下一篇: python 北京大学陈斌教授_陈斌 -