Thankyou so much for this Russ. This time I was able to get the code working. But sadly, it’s still not doing what I want it to do .
The player now makes a small quarter turn in the direction of the click, which results in him sometimes moving sideways or even backwards to the clicked position (sometimes he turns and moves correctly too, it just depends on where you click ).
It’s kind of difficult to explain. So it’s probably better to show you. I don’t know if this is of any use, or even if you’d have the time to test it, but I’ve uploaded the models that I’m using to Rapidshare. So if you want to, you could take a look at it with the same models:
And this is the new code (Note: The Fleet model isn’t animated, so I removed the animation references):
# 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 import math # To use math (sin, cos..etc) from math import sqrt from direct.showbase.PythonUtil import closestDestAngle import sys class Picker(DirectObject): def __init__(self): base.disableMouse() # Position the camera camera.setPos(0, -35, 18) # X = left & right, Y = zoom, Z = Up & down. camera.setHpr(0, -25, 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("MODELS/grass") self.environ.reparentTo(render) self.environ.setPos(0, 0, 0) self.player = loader.loadModel("MODELS/fleet") 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 = self.player.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) 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) return None def moveToPosition(self): # Get the clicked position self.getPosition(base.mouseWatcherNode.getMouse()) # Calculate the new hpr self.npLook.lookAt(self.position) # Look at the clicked position. currHpr = self.player.getHpr() newHpr = self.npLook.getHpr(render) newH = closestDestAngle(currHpr, newHpr) # Create a turn animation from current hpr to the calculated new hpr. playerTurn = self.player.hprInterval(.2, Point3(newH, newHpr, newHpr)) # 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() p = Picker() run()
This has got to be one of the hardest and most frustrating things I’ve ever tried to do. I can’t tell you how much I appreciate your help with this. My respect and awe for game programmer’s has increased enormously.