i have updated the AI on the spiders to better make use of the map.
they have 3 states now
roaming, path follow and chase the player.
monsterAI.py looks like this now.
import bge
import random , time
def roundnum(n,base=100):
rem = n % base
if rem < base // 2:
n = (n // base) * base
else:
n = ((n + base) // base) * base
return int(n)
def chase(scene,own,actu,cont,grid):
own["target"].worldPosition = scene.objects["player"].worldPosition
cont.activate(actu)
hit = own.rayCast(own.worldPosition , scene.objects["player"].worldPosition,0.0,"",1,0,0)
current = getgridpositionkey(grid,own)
if hit[0] or grid.grid[current]["dist"] >= 1:
own["mystate"] = "pathfollow"
own["targetkey"] = current
def roam(grid,own,scene):
if getgridpositionkey(grid,own) == own["targetkey"] :
pos = own["spawner"].worldPosition
targetkey = getrandomkeyinrange(grid,pos,80)
tpos = grid.grid[targetkey]["pos"]
hit = own.rayCast(own.worldPosition , tpos,0.0,"",1,0,0)
if hit[0] == None:
own["targetkey"] = targetkey
own["target"].worldPosition = grid.grid[targetkey]["pos"]
own["stuck"]=0
#print(tpos)
else:
own["stuck"] += 1
if own["stuck"] > 100:
key = getgridpositionkey(grid,own)
valid = None
if grid.grid[key]["neighbour"]:
for n in grid.grid[key]["neighbour"]:
if valid:
valid.append(n)
else:
valid = [n]
targetkey = random.choice(valid)
own["targetkey"]=targetkey
own["stuck"]=0
own["target"].worldPosition = grid.grid[targetkey]["pos"]
def patrol():
pass
def pathfollow(grid,own,player):
gr = grid.grid
if "key" in own:
own["stuck"] += 1
key = own["key"]
dist = gr[key]["dist"]
if "targetkey" in own:
targetkey = own["targetkey"]
else:
targetkey = gr[key]["from"]
if getgridpositionkey(grid,own) == targetkey and getgridpositionkey(grid,player) != targetkey:
own["key"] = targetkey
key = own["key"]
fromkey = gr[key]["from"]
valid = [fromkey,fromkey,fromkey,fromkey,fromkey]
if gr[key]["neighbour"]:
for n in gr[key]["neighbour"]:
if gr[n]["dist"] < gr[key]["dist"] :
valid.append(n)
targetkey = random.choice(valid)
own["targetkey"]=targetkey
own["stuck"]=0
if own["stuck"] > 50:
own.worldPosition = own["spawner"].worldPosition
own["stuck"]=0
own["targetkey"] = getgridpositionkey(grid,own)
own["mystate"] = "roam"
return targetkey
else:
own["key"] = getgridpositionkey(grid,own)
own["stuck"]=0
def getrandomkeyinrange(grid,pos,range):
waypoints = grid.kd.find_range(pos,range)
pos , a,b = random.choice(list(waypoints))
x,y,z = pos
if x != None:
kx = roundnum(int(x),grid.step)
ky = roundnum(int(y),grid.step)
key = "{:>05}:{:>05}".format(kx,ky)
return key
else:
return None
def getgridpositionkey(grid,own):
posx,posy,posz = own.worldPosition
x = roundnum(int(posx),grid.step)
y = roundnum(int(posy),grid.step)
key = "{:>05}:{:>05}".format(x,y)
if key in grid.grid:
return key
index = grid.kd.find(own.worldPosition)
if index[1]:
x,y,z = index[0]
kx = roundnum(int(x),grid.step)
ky = roundnum(int(y),grid.step)
key = "{:>05}:{:>05}".format(kx,ky)
return key
def main():
cont = bge.logic.getCurrentController()
scene = bge.logic.getCurrentScene()
actu = cont.actuators['Steering']
own = cont.owner
random.seed(time.time())
if "grid" in scene.objects["1Lamp"]:
grid = scene.objects["1Lamp"]["grid"]
key = getgridpositionkey(grid,own)
if key in grid.grid:
if own["mystate"] == "chase" or own["mystate"] == "pathfollow":
if own["mystate"] == "chase":
chase(scene,own,actu,cont,grid)
if own["mystate"] == "pathfollow":
targetkey = pathfollow(grid,own,scene.objects["player"])
if targetkey:
if grid.grid[targetkey]["pos"]:
if actu.target == None:
actu.target = own["target"]
own["target"].worldPosition = grid.grid[targetkey]["pos"]
actu.velocity = 7.000
cont.activate(actu)
hit = own.rayCast(own.children["eyes"].worldPosition , scene.objects["player"].children["Camera"].worldPosition,0.0,"",1,0,0)
if not hit[0] or hit[0] == "monster":
own["mystate"] = "chase"
own["target"].worldPosition = scene.objects["player"].worldPosition
else:
if own["mystate"] != "roam":
own["mystate"] = "pathfollow"
else:
actu.velocity = 3.000
cont.activate(actu)
else:
distance = own.getDistanceTo(scene.objects["player"])
if distance < 100:
hit = own.rayCast(own.children["eyes"].worldPosition , scene.objects["player"].children["Camera"].worldPosition,0.0,"",1,0,0)
if hit[0] == None:
own["mystate"] = "chase"
roam(grid,own,scene)
if actu.target == None:
own["targetkey"] = getgridpositionkey(grid,own)
actu.target = own["target"]
cont.activate(actu)
main()
her is a updated blend
http://15b.dk/blendfiles/grid-pathfinding-betterAI.blend