this worked for me. I used some default models so anyone could try it. The panda is modeled backwards, so when he turns, he will face opposite to the direction he is moving.
# This program turns a model to the position (point 3) of a left mouse click
# on a 3d surface and then moves it to that position.
import direct.directbase.DirectStart # Start Panda
from pandac.PandaModules import * # Import the Panda Modules
from direct.showbase.DirectObject import DirectObject # To listen for Events
from direct.task import Task # To use Tasks
from direct.actor import Actor # To use animated Actors
from direct.interval.IntervalGlobal import * # To use Intervals
from direct.showbase.PythonUtil import closestDestAngle
import sys
class Picker(DirectObject):
def __init__(self):
base.disableMouse()
# Position the camera
camera.setPos(0, -0, 100) # X = left & right, Y = zoom, Z = Up & down.
camera.setHpr(0, -90, 0) # Heading, pitch, roll.
# Declare variables
self.position = None
self.playerMovement = None
self.movementSpeed = 8.0 # Controls how fast the player moves.
# Load an environment
self.environ = loader.loadModel("environment")
self.environ.reparentTo(render)
self.environ.setPos(0, 0, 0)
self.player = loader.loadModel("panda")
self.player.reparentTo(render)
self.player.setPos(0, 0, 0)
self.player.setHpr(0, 0, 0)
self.player.setColor(Vec4(0, 148, 213, 1))
self.npLook = render.attachNewNode("npLook")
# Setup collision stuff.
self.picker= CollisionTraverser()
self.queue=CollisionHandlerQueue()
self.pickerNode = CollisionNode('mouseRay')
self.pickerNP = camera.attachNewNode(self.pickerNode)
self.pickerNode.setFromCollideMask(GeomNode.getDefaultCollideMask())
self.pickerRay = CollisionRay()
self.pickerNode.addSolid(self.pickerRay)
self.picker.addCollider(self.pickerNode, self.queue)
# Setup controls
self.accept("escape", sys.exit)
self.accept('mouse1', self.moveToPosition)
self.accept('r', self.reset)
def getPosition(self, mousepos):
self.pickerRay.setFromLens(base.camNode, mousepos.getX(),mousepos.getY())
self.picker.traverse(render)
if self.queue.getNumEntries() > 0:
self.queue.sortEntries()
# This is the clicked position.
self.position = self.queue.getEntry(0).getSurfacePoint(self.environ)
print "position", self.position
return None
def moveToPosition(self):
# Get the clicked position
self.getPosition(base.mouseWatcherNode.getMouse())
# Calculate the new hpr
self.npLook.setPos(self.player.getPos())
self.npLook.lookAt(self.position) # Look at the clicked position.
reducedH = self.player.getH()%360.0
self.player.setH(reducedH)
currHpr = self.player.getHpr()
#print "curr", currHpr
newHpr = self.npLook.getHpr()
#print "new", newHpr
#print self.npLook.getPos(render)
newH = closestDestAngle(currHpr[0], newHpr[0])
#print newH
# Create a turn animation from current hpr to the calculated new hpr.
playerTurn = self.player.hprInterval(.2, Point3(newH, newHpr[1], newHpr[2]))
# Calculate the distance between the start and finish positions.
# This is then used to calculate the duration it should take to
# travel to the new coordinates based on self.movementSpeed
travelVec = self.position - self.player.getPos()
distance = travelVec.length()
playerMove = self.player.posInterval((distance / self.movementSpeed), self.position)
self.playerMovement = Sequence(playerTurn, playerMove)
self.playerMovement.start()
#playerTurn.start()
def reset(self):
self.player.setHpr(0,0,0)
p = Picker()
run()