Thanks Russ, I did as you suggested, but now I’m getting a new error message (:evil: it’s enough to make you scream, isn’t it?).
And the new code:
# This program turns a model to the position (point 3) of a left mouse click
# on a 3d surface.
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
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.
self.reducedH = None
# 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 = render.attachNewNode("npLook")
# Declare functions.
self.reducePlayerH()
# 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 closestDestAngle(src, dest):
diff = src - dest
if diff > 180:
# if the difference is greater that 180 it's shorter to go the other way
return src - (diff - 360)
elif diff < -180:
# or perhaps the OTHER other way...
return src - (360 + diff)
else:
# otherwise just go to the original destination
return dest
def reducePlayerH(self):
# Reduce the players heading to eliminate wrap-around
reducedH = self.player.getH()%360.0
self.player.setH(reducedH)
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.setPos(self.player.getPos())
self.npLook.lookAt(self.position) # Look at the clicked position.
currHpr = self.player.getHpr()
newHpr = self.npLook.getHpr()
newH = closestDestAngle(currHpr[0], newHpr[0])
# Create a turn animation from current hpr to the calculated new hpr.
playerTurn = self.player.hprInterval(.2, Point3(newHpr[0], 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()
# Put the animations into a sequence.
playerMove = self.player.posInterval((distance / self.movementSpeed), self.position)
self.playerMovement = Sequence(playerTurn, Func(self.reducedH), playerMove)
self.playerMovement.start()
p = Picker()
run()
I dunno, maybe I’m just not cut out for this programming business .
Thanks again