View Single Post
  #2  
Old 04-25-2007, 05:58 PM
farshizzo farshizzo is offline
WorldViz Team Member
 
Join Date: Mar 2003
Posts: 2,849
Hi,

You could still use a hand-animation and simply rotate the snake so that it is perpendicular to the normal of the terrain it is on. However, this will only work on terrain with gradual height changes.

Vizard allows you to take control of individual avatar bones. So you could manually animate the snake and use intersection tests to keep it above the terrain.

I made a script a while back that simulates a snake moving, but only in 2D. The snake will follow the mouse cursor. You could perform a similar technique, except make sure that each new location is above the terrain. The snake does not check for collisions between itself though. Here is the code, hope it helps:
Code:
import viz
viz.go()

class Snake(object):
	
	def __init__(self,num=50,skin=None,speed=0.1,turnSpeed=420.0,step=10):
		
		self.__buffer = [(0.0,[0.5,0.5,0],0.0)]
		self.__body = []				#List of body parts
		self.__step = step				#Step time between each body
		self.__speed = speed			#Movement speed
		self.__turnSpeed = turnSpeed	#Maximum turn speed
		self.__bufsize = 500			#Size of position buffer
		self.__skin = skin				#Skin texture

		#Add initial elements
		for x in xrange(num):
			self.addBody()
			
	def updateMouse(self,elapsed):
		
		#Get current mouse position
		pos = viz.mouse.getPosition(immediate=True)
		
		#If position is too close from previous, then stop
		if vizmat.Distance(pos+[0],self.__buffer[0][1]+[0]) < 0.01:
			return
		
		#Compute angle to mouse position
		angle = vizmat.AngleToPoint(self.__buffer[0][1],pos)
		
		#Make sure turn speed does not exceed max turn speed
		diff = vizmat.AngleDiff(self.__buffer[0][2],angle)
		maxDiff = elapsed * self.__turnSpeed
		if abs(diff) > maxDiff:
			angle = self.__buffer[0][2] + (viz.sign(diff) * maxDiff)
		
		#Compute matrix for new position
		mat = viz.Matrix.axisangle(0,0,-1,angle)
		mat.setPosition(self.__buffer[0][1])
		mat.preTrans(0,self.__speed*elapsed,0)
		
		#Add position to buffer
		self.__buffer.insert(0,(viz.getFrameTime(),mat.getPosition(),angle))
		if len(self.__buffer) > self.__bufsize:
			self.__buffer.pop()
		
		self.updateStepSample()
			
	def updateStepSample(self):
		
		size = len(self.__buffer)-1
		
		for i,b in enumerate(self.__body):
			
			sample = min(self.__step * i,size)

			b.setPosition(self.__buffer[sample][1])
			b.setAxisAngle(0,0,-1,self.__buffer[sample][2])

	def addBody(self):
		b = viz.addTexQuad(viz.SCREEN,size=30,texture=self.__skin)
		b.drawOrder(-len(self.__body))
		self.__body.append(b)
		
s = Snake(skin=viz.add('radio_up.gif'))

def UpdateSnake():
	s.updateMouse(viz.elapsed())
vizact.ontimer(0,UpdateSnake)
Reply With Quote