All pastes #476275 Raw Edit

scabootssca

public text v1 · immutable
·published 2007-05-07 23:34 UTC
rendered paste body
# Pathfinding Crap
# BY:scabootssca
# scabootssca@yahoo.com

import Blender
import operator

### Generate The Node Tree
pathTree = Blender.Mesh.Get("path")

def dist(a,b):
	return ((a[0]-b[0])**2+(a[1]-b[1])**2+(a[2]-b[2])**2)**.5

class point:
	def __init__(self,co):
		self.neighbors = {}
		self.distance = 0
		self.co = co
		
class path:
	def __init__(self,points,distance,length):
		self.points = points
		self.distance = distance
		self.length = length
	
def generateTree(pathTree):
	points = {}
	for v in pathTree.verts:
		points[v.index] = point(v.co)
		#print v.index,v.sel
	
	for edge in pathTree.edges:
		distance = dist(edge.v1.co,edge.v2.co)
		points[edge.v1.index].neighbors[edge.v2.index] = distance
		points[edge.v2.index].neighbors[edge.v1.index] = distance
	return points

### Extra Stuff
def getClosestTo(pos,points):
	closestPoint = 0
	closestPos = dist(pos,points[closestPoint].co)
	for pointTest in points:
		if dist(pos,points[pointTest].co) < closestPos:
			closestPoint = pointTest
			closestPos = dist(pos,points[pointTest].co)
	return closestPoint
			
def getPath(start,end,points):
	p = [] # create a list P
	
	# estimate The Distance
	endPoint = points[end]
	for pointTest in points.values():
		pointTest.distance = dist(endPoint.co,pointTest.co)
	
	# add the start node S, to P giving it one element
	p.append(path([start],0,0))
	
	print "-"*30
	
	iter = 0
	while True:
		iter += 1
		#if iter > 10000: print "itered out"; break
	
		# Until first path of P ends with G, or P is empty
		if not p: print "not p"; break
		elif p[0].points[-1] == end: print "found end On Iter:%i"%iter; break
	
		# extract the first path from P
		test = p.pop(0)
	
		# extend first path one step to all neighbors creating X new paths
		news = []
		for neighbor in points[test.points[-1]].neighbors:
			new = path(test.points[:],test.distance,0)
			new.points.append(neighbor)
			new.distance += points[test.points[-1]].neighbors[neighbor]
			new.length = new.distance+points[neighbor].distance
			news.append(new)
	
		# reject all paths with loops
		tmp = news[:]
		for pos,new in enumerate(news):
			if len(new.points) != len(set(new.points)): #passes if there is a duplicate
				tmp.remove(new)
		news = tmp[:]
	
		# for all paths that end at the same node, keep only the shortest one.
		same = {}
		for pos,new in enumerate(news):
			try: same[new.points[-1]].append(new)
			except KeyError: same[new.points[-1]] = [new]
	
		for sameNum in same:
			lists = same[sameNum]
			lowest = lists[0]
			for pathTest in lists:
				if pathTest.length < lowest.length:
					lowest = pathTest
			same[sameNum] = lowest
	
		# add each remaining new path to of P
		for pathTest in same.values(): p.append(pathTest)
		
	
		#for new in news: p.append(new)
	
		#Sort all paths by total distance travelled, shortest first.
		p.sort(key=operator.attrgetter("length"))#,reverse=1)
	return p[0]

			
### Solve
cont = GameLogic.getCurrentController()
endOwn = cont.getOwner()
startMove = cont.getActuator("start")
startOwn = startMove.getOwner()
trackOwn = cont.getActuator("trackOwn").getOwner()
track = cont.getActuator("track")

if not hasattr(GameLogic,"points"):
	GameLogic.points = generateTree(pathTree)

start = getClosestTo(startOwn.getPosition(),GameLogic.points)#0
end = getClosestTo(endOwn.getPosition(),GameLogic.points)#28

startOwn.r = dist(eval(startOwn.lastEndPos),endOwn.getPosition())
if dist(eval(startOwn.lastEndPos),endOwn.getPosition()) > .2:
	startOwn.resolve = 1


if startOwn.resolve:# cont.getSensor("solveKey").isPositive():
	startOwn.isSolving = 1
	startOwn.resolve = 0

	GameLogic.path = getPath(start,end,GameLogic.points)
	startOwn.lastEndPos = str(endOwn.getPosition())
	
if startOwn.isSolving:
	
	speed = .01
	cur = GameLogic.points[GameLogic.path.points[0]].co
	pos = startOwn.getPosition()
	dist = dist(cur,pos)
	if dist < speed:
		del GameLogic.path.points[0]
		if GameLogic.path.points:
			trackOwn.setPosition(GameLogic.points[GameLogic.path.points[0]].co)
		else:
			startOwn.isSolving = 0
			GameLogic.addActiveActuator(startMove,0)
	else:
	
		startMove.setDLoc(0,speed,0,1)	
		GameLogic.addActiveActuator(startMove,1)
		GameLogic.addActiveActuator(track,1)