From 74c6dad887d6f619ca9a227d1a22e1b0451b6928 Mon Sep 17 00:00:00 2001 From: Dave Schuyler Date: Mon, 9 Aug 2004 19:27:13 +0000 Subject: [PATCH] A ShipPilot is a control for steering a ship --- direct/src/controls/ShipPilot.py | 709 +++++++++++++++++++++++++++++++ 1 file changed, 709 insertions(+) create mode 100755 direct/src/controls/ShipPilot.py diff --git a/direct/src/controls/ShipPilot.py b/direct/src/controls/ShipPilot.py new file mode 100755 index 0000000000..62e18e33b2 --- /dev/null +++ b/direct/src/controls/ShipPilot.py @@ -0,0 +1,709 @@ +""" +ShipPilot.py is for avatars pilotting ships (or more accurately, a ship as the avatar). + +A control such as this one provides: + - creation of the collision nodes + - handling the keyboard and mouse input for avatar movement + - moving the avatar + +it does not: + - play sounds + - play animations + +although it does send messeges that allow a listener to play sounds or +animations based on control events. +""" + +from direct.showbase.ShowBaseGlobal import * + +from direct.directnotify import DirectNotifyGlobal +from pandac import PhysicsManager +import math + +import PhysicsWalker + +#import LineStream + +class ShipPilot(PhysicsWalker.PhysicsWalker): + + notify = DirectNotifyGlobal.directNotify.newCategory("PhysicsWalker") + wantAvatarPhysicsIndicator = base.config.GetBool('want-avatar-physics-indicator', 0) + + useLifter = 0 + useHeightRay = 0 + + # special methods + def __init__(self, gravity = -32.1740, standableGround=0.707, + hardLandingForce=16.0): + assert(self.debugPrint("PhysicsWalker(gravity=%s, standableGround=%s)"%( + gravity, standableGround))) + PhysicsWalker.PhysicsWalker.__init__(self, gravity = -32.1740, standableGround=0.707, + hardLandingForce=16.0) + self.__gravity=gravity + self.__standableGround=standableGround + self.__hardLandingForce=hardLandingForce + + self.needToDeltaPos = 0 + self.physVelocityIndicator=None + self.avatarControlForwardSpeed=0 + self.avatarControlJumpForce=0 + self.avatarControlReverseSpeed=0 + self.avatarControlRotateSpeed=0 + self.__oldAirborneHeight=None + self.getAirborneHeight=None + self.__oldContact=None + self.__oldPosDelta=Vec3(0) + self.__oldDt=0 + self.__speed=0.0 + self.__rotationSpeed=0.0 + self.__slideSpeed=0.0 + self.__vel=Vec3(0.0) + self.collisionsActive = 0 + + self.isAirborne = 0 + self.highMark = 0 + + def setWalkSpeed(self, forward, jump, reverse, rotate): + assert(self.debugPrint("setWalkSpeed()")) + self.avatarControlForwardSpeed=forward + self.avatarControlJumpForce=0.0 + self.avatarControlReverseSpeed=reverse + self.avatarControlRotateSpeed=rotate + + def getSpeeds(self): + #assert(self.debugPrint("getSpeeds()")) + return (self.__speed, self.__rotationSpeed) + + def setupRay(self, floorBitmask, floorOffset): + # This is a ray cast from your head down to detect floor polygons + # A toon is about 4.0 feet high, so start it there + self.cRay = CollisionRay(0.0, 0.0, CollisionHandlerRayStart, 0.0, 0.0, -1.0) + cRayNode = CollisionNode('PW.cRayNode') + cRayNode.addSolid(self.cRay) + self.cRayNodePath = self.avatarNodePath.attachNewNode(cRayNode) + self.cRayBitMask = floorBitmask + cRayNode.setFromCollideMask(self.cRayBitMask) + cRayNode.setIntoCollideMask(BitMask32.allOff()) + + if 0 or self.useLifter: + # set up floor collision mechanism + self.lifter = CollisionHandlerFloor() + self.lifter.setInPattern("enter%in") + self.lifter.setOutPattern("exit%in") + self.lifter.setOffset(floorOffset) + + # Limit our rate-of-fall with the lifter. + # If this is too low, we actually "fall" off steep stairs + # and float above them as we go down. I increased this + # from 8.0 to 16.0 to prevent this + #self.lifter.setMaxVelocity(16.0) + + #self.bobNodePath = self.avatarNodePath.attachNewNode("bob") + #self.lifter.addCollider(self.cRayNodePath, self.cRayNodePath) + self.lifter.addCollider(self.cRayNodePath, self.avatarNodePath) + else: # useCollisionHandlerQueue + self.cRayQueue = CollisionHandlerQueue() + self.cTrav.addCollider(self.cRayNodePath, self.cRayQueue) + + def determineHeight(self): + """ + returns the height of the avatar above the ground. + If there is no floor below the avatar, 0.0 is returned. + aka get airborne height. + """ + if self.useLifter: + height = self.avatarNodePath.getPos(self.cRayNodePath) + # If the shadow where not pointed strait down, we would need to + # get magnitude of the vector. Since it is strait down, we'll + # just get the z: + #spammy --> assert self.debugPrint("getAirborneHeight() returning %s"%(height.getZ(),)) + assert onScreenDebug.add("height", height.getZ()) + return height.getZ() - self.floorOffset + else: # useCollisionHandlerQueue + """ + returns the height of the avatar above the ground. + If there is no floor below the avatar, 0.0 is returned. + aka get airborne height. + """ + height = 0.0 + #*#self.cRayTrav.traverse(render) + if self.cRayQueue.getNumEntries() != 0: + # ...we have a floor. + # Choose the highest of the possibly several floors we're over: + self.cRayQueue.sortEntries() + floorPoint = self.cRayQueue.getEntry(0).getFromIntersectionPoint() + height = -floorPoint.getZ() + self.cRayQueue.clearEntries() + if __debug__: + onScreenDebug.add("height", height) + return height + + def setupSphere(self, bitmask, avatarRadius): + """ + Set up the collision sphere + """ + # This is a sphere on the ground to detect barrier collisions + self.avatarRadius = avatarRadius + centerHeight = avatarRadius + if self.useHeightRay: + centerHeight *= 2.0 + self.cSphere = CollisionSphere(0.0, 0.0, centerHeight, avatarRadius) + cSphereNode = CollisionNode('PW.cSphereNode') + cSphereNode.addSolid(self.cSphere) + self.cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode) + self.cSphereBitMask = bitmask + + cSphereNode.setFromCollideMask(self.cSphereBitMask) + cSphereNode.setIntoCollideMask(BitMask32.allOff()) + + # set up collision mechanism + self.pusher = PhysicsCollisionHandler() + self.pusher.setInPattern("enter%in") + self.pusher.setOutPattern("exit%in") + + self.pusher.addCollider(self.cSphereNodePath, self.avatarNodePath) + + def setupPhysics(self, avatarNodePath): + assert(self.debugPrint("setupPhysics()")) + # Connect to Physics Manager: + self.actorNode=ActorNode("physicsActor") + self.actorNode.getPhysicsObject().setOriented(1) + self.actorNode.getPhysical(0).setViscosity(0.1) + physicsActor=NodePath(self.actorNode) + avatarNodePath.reparentTo(physicsActor) + avatarNodePath.assign(physicsActor) + self.phys=PhysicsManager.PhysicsManager() + + fn=ForceNode("gravity") + fnp=NodePath(fn) + #fnp.reparentTo(physicsActor) + fnp.reparentTo(render) + gravity=LinearVectorForce(0.0, 0.0, self.__gravity) + fn.addForce(gravity) + self.phys.addLinearForce(gravity) + self.gravity = gravity + + fn=ForceNode("priorParent") + fnp=NodePath(fn) + fnp.reparentTo(render) + priorParent=LinearVectorForce(0.0, 0.0, 0.0) + fn.addForce(priorParent) + self.phys.addLinearForce(priorParent) + self.priorParentNp = fnp + self.priorParent = priorParent + + fn=ForceNode("viscosity") + fnp=NodePath(fn) + #fnp.reparentTo(physicsActor) + fnp.reparentTo(render) + self.avatarViscosity=LinearFrictionForce(0.0, 1.0, 0) + #self.avatarViscosity.setCoef(0.9) + fn.addForce(self.avatarViscosity) + self.phys.addLinearForce(self.avatarViscosity) + + self.phys.attachLinearIntegrator(LinearEulerIntegrator()) + self.phys.attachPhysicalnode(physicsActor.node()) + + self.acForce=LinearVectorForce(0.0, 0.0, 0.0) + fn=ForceNode("avatarControls") + fnp=NodePath(fn) + fnp.reparentTo(render) + fn.addForce(self.acForce) + self.phys.addLinearForce(self.acForce) + #self.phys.removeLinearForce(self.acForce) + #fnp.remove() + return avatarNodePath + + def initializeCollisions(self, collisionTraverser, avatarNodePath, + wallBitmask, floorBitmask, + avatarRadius = 1.4, floorOffset = 1.0, reach = 1.0): + """ + Set up the avatar collisions + """ + assert(self.debugPrint("initializeCollisions()")) + + assert not avatarNodePath.isEmpty() + + self.cTrav = collisionTraverser + self.floorOffset = floorOffset = 7.0 + + self.avatarNodePath = self.setupPhysics(avatarNodePath) + if 0 or self.useHeightRay: + #self.setupRay(floorBitmask, avatarRadius) + self.setupRay(floorBitmask, 0.0) + self.setupSphere(wallBitmask|floorBitmask, avatarRadius) + + self.setCollisionsActive(1) + + def setAirborneHeightFunc(self, getAirborneHeight): + self.getAirborneHeight = getAirborneHeight + + def setAvatarPhysicsIndicator(self, indicator): + """ + indicator is a NodePath + """ + assert(self.debugPrint("setAvatarPhysicsIndicator()")) + self.cSphereNodePath.show() + if indicator: + # Indicator Node: + change=render.attachNewNode("change") + #change.setPos(Vec3(1.0, 1.0, 1.0)) + #change.setHpr(0.0, 0.0, 0.0) + change.setScale(0.1) + #change.setColor(Vec4(1.0, 1.0, 1.0, 1.0)) + indicator.reparentTo(change) + + indicatorNode=render.attachNewNode("physVelocityIndicator") + #indicatorNode.setScale(0.1) + #indicatorNode.setP(90.0) + indicatorNode.setPos(self.avatarNodePath, 0.0, 0.0, 6.0) + indicatorNode.setColor(0.0, 0.0, 1.0, 1.0) + change.reparentTo(indicatorNode) + + self.physVelocityIndicator=indicatorNode + # Contact Node: + contactIndicatorNode=render.attachNewNode("physContactIndicator") + contactIndicatorNode.setScale(0.25) + contactIndicatorNode.setP(90.0) + contactIndicatorNode.setPos(self.avatarNodePath, 0.0, 0.0, 5.0) + contactIndicatorNode.setColor(1.0, 0.0, 0.0, 1.0) + indicator.instanceTo(contactIndicatorNode) + self.physContactIndicator=contactIndicatorNode + else: + print "failed load of physics indicator" + + def avatarPhysicsIndicator(self, task): + #assert(self.debugPrint("avatarPhysicsIndicator()")) + # Velocity: + self.physVelocityIndicator.setPos(self.avatarNodePath, 0.0, 0.0, 6.0) + physObject=self.actorNode.getPhysicsObject() + a=physObject.getVelocity() + self.physVelocityIndicator.setScale(math.sqrt(a.length())) + a+=self.physVelocityIndicator.getPos() + self.physVelocityIndicator.lookAt(Point3(a)) + # Contact: + contact=self.actorNode.getContactVector() + if contact==Vec3.zero(): + self.physContactIndicator.hide() + else: + self.physContactIndicator.show() + self.physContactIndicator.setPos(self.avatarNodePath, 0.0, 0.0, 5.0) + #contact=self.actorNode.getContactVector() + point=Point3(contact+self.physContactIndicator.getPos()) + self.physContactIndicator.lookAt(point) + return Task.cont + + def deleteCollisions(self): + assert(self.debugPrint("deleteCollisions()")) + del self.cTrav + + if self.useHeightRay: + del self.cRayQueue + self.cRayNodePath.removeNode() + del self.cRayNodePath + + del self.cSphere + self.cSphereNodePath.removeNode() + del self.cSphereNodePath + + del self.pusher + + del self.getAirborneHeight + + def setCollisionsActive(self, active = 1): + assert(self.debugPrint("collisionsActive(active=%s)"%(active,))) + if self.collisionsActive != active: + self.collisionsActive = active + if active: + self.cTrav.addCollider(self.cSphereNodePath, self.pusher) + if self.useHeightRay: + if self.useLifter: + self.cTrav.addCollider(self.cRayNodePath, self.lifter) + else: + self.cTrav.addCollider(self.cRayNodePath, self.cRayQueue) + else: + self.cTrav.removeCollider(self.cSphereNodePath) + if self.useHeightRay: + self.cTrav.removeCollider(self.cRayNodePath) + # Now that we have disabled collisions, make one more pass + # right now to ensure we aren't standing in a wall. + self.oneTimeCollide() + + def getCollisionsActive(self): + assert(self.debugPrint("getCollisionsActive() returning=%s"%( + self.collisionsActive,))) + return self.collisionsActive + + def placeOnFloor(self): + """ + Make a reasonable effort to place the avatar on the ground. + For example, this is useful when switching away from the + current walker. + """ + self.oneTimeCollide() + self.avatarNodePath.setZ(self.avatarNodePath.getZ()-self.getAirborneHeight()) + + def oneTimeCollide(self): + """ + Makes one quick collision pass for the avatar, for instance as + a one-time straighten-things-up operation after collisions + have been disabled. + """ + assert(self.debugPrint("oneTimeCollide()")) + tempCTrav = CollisionTraverser("oneTimeCollide") + if self.useHeightRay: + if self.useLifter: + tempCTrav.addCollider(self.cRayNodePath, self.lifter) + else: + tempCTrav.addCollider(self.cRayNodePath, self.cRayQueue) + tempCTrav.traverse(render) + + def handleAvatarControls(self, task): + """ + Check on the arrow keys and update the avatar. + """ + if __debug__: + if self.wantAvatarPhysicsIndicator: + onScreenDebug.append("localAvatar pos = %s\n"%(base.localAvatar.getPos().pPrintValues(),)) + onScreenDebug.append("localAvatar h = % 10.4f\n"%(base.localAvatar.getH(),)) + onScreenDebug.append("localAvatar anim = %s\n"%(base.localAvatar.animFSM.getCurrentState().getName(),)) + #assert(self.debugPrint("handleAvatarControls(task=%s)"%(task,))) + physObject=self.actorNode.getPhysicsObject() + #rotAvatarToPhys=Mat3.rotateMatNormaxis(-self.avatarNodePath.getH(), Vec3.up()) + #rotPhysToAvatar=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up()) + contact=self.actorNode.getContactVector() + + # hack fix for falling through the floor: + if contact==Vec3.zero() and self.avatarNodePath.getZ()<-50.0: + # DCR: don't reset X and Y; allow player to move + self.reset() + self.avatarNodePath.setZ(50.0) + messenger.send("walkerIsOutOfWorld", [self.avatarNodePath]) + + # get the button states: + forward = inputState.isSet("forward") + reverse = inputState.isSet("reverse") + turnLeft = inputState.isSet("turnLeft") + turnRight = inputState.isSet("turnRight") + slide = 0#inputState.isSet("slide") + slideLeft = 0#inputState.isSet("slideLeft") + slideRight = 0#inputState.isSet("slideRight") + jump = inputState.isSet("jump") + # Determine what the speeds are based on the buttons: + self.__speed=(forward and self.avatarControlForwardSpeed or + reverse and -self.avatarControlReverseSpeed) + avatarSlideSpeed=self.avatarControlForwardSpeed*0.5 + #self.__slideSpeed=slide and ( + # (turnLeft and -avatarSlideSpeed) or + # (turnRight and avatarSlideSpeed)) + self.__slideSpeed=( + (slideLeft and -avatarSlideSpeed) or + (slideRight and avatarSlideSpeed)) + self.__rotationSpeed=not slide and ( + (turnLeft and self.avatarControlRotateSpeed) or + (turnRight and -self.avatarControlRotateSpeed)) + + # How far did we move based on the amount of time elapsed? + dt=ClockObject.getGlobalClock().getDt() + + if self.needToDeltaPos: + self.setPriorParentVector() + self.needToDeltaPos = 0 + #self.__oldPosDelta = render.getRelativeVector( + # self.avatarNodePath, + # self.avatarNodePath.getPosDelta(render)) + #self.__oldPosDelta = self.avatarNodePath.getRelativeVector( + # render, + # self.avatarNodePath.getPosDelta(render)) + self.__oldPosDelta = self.avatarNodePath.getPosDelta(render) + self.__oldDt = dt + #posDelta = self.avatarNodePath.getPosDelta(render) + #if posDelta==Vec3.zero(): + # self.priorParent.setVector(self.__oldPosDelta) + #else: + # self.priorParent.setVector(Vec3.zero()) + # # We must copy the vector to preserve it: + # self.__oldPosDelta=Vec3(posDelta) + if __debug__: + if self.wantAvatarPhysicsIndicator: + onScreenDebug.add("posDelta1", + self.avatarNodePath.getPosDelta(render).pPrintValues()) + + if 0: + onScreenDebug.add("posDelta3", + render.getRelativeVector( + self.avatarNodePath, + self.avatarNodePath.getPosDelta(render)).pPrintValues()) + + if 0: + onScreenDebug.add("gravity", + self.gravity.getLocalVector().pPrintValues()) + onScreenDebug.add("priorParent", + self.priorParent.getLocalVector().pPrintValues()) + onScreenDebug.add("avatarViscosity", + "% 10.4f"%(self.avatarViscosity.getCoef(),)) + + onScreenDebug.add("physObject pos", + physObject.getPosition().pPrintValues()) + onScreenDebug.add("physObject hpr", + physObject.getOrientation().getHpr().pPrintValues()) + onScreenDebug.add("physObject orien", + physObject.getOrientation().pPrintValues()) + + if 1: + onScreenDebug.add("physObject vel", + physObject.getVelocity().pPrintValues()) + onScreenDebug.add("physObject len", + "% 10.4f"%physObject.getVelocity().length()) + + if 0: + onScreenDebug.add("posDelta4", + self.priorParentNp.getRelativeVector( + render, + self.avatarNodePath.getPosDelta(render)).pPrintValues()) + + if 1: + onScreenDebug.add("priorParent", + self.priorParent.getLocalVector().pPrintValues()) + + if 0: + onScreenDebug.add("priorParent po", + self.priorParent.getVector(physObject).pPrintValues()) + + if 0: + onScreenDebug.add("__posDelta", + self.__oldPosDelta.pPrintValues()) + + if 1: + onScreenDebug.add("contact", + contact.pPrintValues()) + #onScreenDebug.add("airborneHeight", "% 10.4f"%( + # self.getAirborneHeight(),)) + + if 0: + onScreenDebug.add("__oldContact", + contact.pPrintValues()) + onScreenDebug.add("__oldAirborneHeight", "% 10.4f"%( + self.getAirborneHeight(),)) + airborneHeight=self.getAirborneHeight() + if airborneHeight > self.highMark: + self.highMark = airborneHeight + if __debug__: + onScreenDebug.add("highMark", "% 10.4f"%(self.highMark,)) + #if airborneHeight < 0.1: #contact!=Vec3.zero(): + if 1: + if (airborneHeight > self.avatarRadius*0.5 + or physObject.getVelocity().getZ() > 0.0 + ): # Check stair angles before changing this. + # ...the avatar is airborne (maybe a lot or a tiny amount). + self.isAirborne = 1 + else: + # ...the avatar is very close to the ground (close enough to be + # considered on the ground). + if self.isAirborne and physObject.getVelocity().getZ() <= 0.0: + # ...the avatar has landed. + contactLength = contact.length() + if contactLength>self.__hardLandingForce: + #print "jumpHardLand" + messenger.send("jumpHardLand") + else: + #print "jumpLand" + messenger.send("jumpLand") + self.priorParent.setVector(Vec3.zero()) + self.isAirborne = 0 + elif jump: + #print "jump" + #self.__jumpButton=0 + messenger.send("jumpStart") + if 0: + # ...jump away from walls and with with the slope normal. + jumpVec=Vec3(contact+Vec3.up()) + #jumpVec=Vec3(rotAvatarToPhys.xform(jumpVec)) + jumpVec.normalize() + else: + # ...jump straight up, even if next to a wall. + jumpVec=Vec3.up() + jumpVec*=self.avatarControlJumpForce + physObject.addImpulse(Vec3(jumpVec)) + self.isAirborne = 1 # Avoid double impulse before fully airborne. + else: + self.isAirborne = 0 + if __debug__: + onScreenDebug.add("isAirborne", "%d"%(self.isAirborne,)) + else: + if contact!=Vec3.zero(): + # ...the avatar has touched something (but might not be on the ground). + contactLength = contact.length() + contact.normalize() + angle=contact.dot(Vec3.up()) + if angle>self.__standableGround: + # ...avatar is on standable ground. + if self.__oldContact==Vec3.zero(): + #if self.__oldAirborneHeight > 0.1: #self.__oldContact==Vec3.zero(): + # ...avatar was airborne. + self.jumpCount-=1 + if contactLength>self.__hardLandingForce: + messenger.send("jumpHardLand") + else: + messenger.send("jumpLand") + elif jump: + self.jumpCount+=1 + #self.__jumpButton=0 + messenger.send("jumpStart") + jump=Vec3(contact+Vec3.up()) + #jump=Vec3(rotAvatarToPhys.xform(jump)) + jump.normalize() + jump*=self.avatarControlJumpForce + physObject.addImpulse(Vec3(jump)) + + if contact!=self.__oldContact: + # We must copy the vector to preserve it: + self.__oldContact=Vec3(contact) + self.__oldAirborneHeight=airborneHeight + + moveToGround = Vec3.zero() + if not self.useHeightRay or self.isAirborne: + # ...the airborne check is a hack to stop sliding. + self.phys.doPhysics(dt) + if __debug__: + onScreenDebug.add("phys", "on") + else: + physObject.setVelocity(Vec3.zero()) + #if airborneHeight>0.001 and contact==Vec3.zero(): + # moveToGround = Vec3(0.0, 0.0, -airborneHeight) + #moveToGround = Vec3(0.0, 0.0, -airborneHeight) + moveToGround = Vec3(0.0, 0.0, -self.determineHeight()) + if __debug__: + onScreenDebug.add("phys", "off") + # Check to see if we're moving at all: + if self.__speed or self.__slideSpeed or self.__rotationSpeed or moveToGround!=Vec3.zero(): + distance = dt * self.__speed + slideDistance = dt * self.__slideSpeed + rotation = dt * self.__rotationSpeed + + #debugTempH=self.avatarNodePath.getH() + assert self.avatarNodePath.getQuat().isSameDirection(physObject.getOrientation()) + assert self.avatarNodePath.getPos().almostEqual(physObject.getPosition(), 0.0001) + + # update pos: + # Take a step in the direction of our previous heading. + self.__vel=Vec3( + Vec3.forward() * distance + + Vec3.right() * slideDistance) + + # rotMat is the rotation matrix corresponding to + # our previous heading. + rotMat=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up()) + step=rotMat.xform(self.__vel) + + newVector = self.acForce.getLocalVector()+Vec3(step*100.0) + maxLen = 500.0 + if newVector.length() > maxLen: + newVector.normalize() + newVector *= maxLen + onScreenDebug.add("newVector", + newVector) + onScreenDebug.add("newVector length", + newVector.length()) + self.acForce.setVector(Vec3(newVector)) + #physObject.setPosition(Point3( + # physObject.getPosition()+step+moveToGround)) + + # update hpr: + o=physObject.getOrientation() + r=LRotationf() + r.setHpr(Vec3(rotation, 0.0, 0.0)) + physObject.setOrientation(o*r) + + # sync the change: + self.actorNode.updateTransform() + + assert self.avatarNodePath.getQuat().isSameDirection(physObject.getOrientation()) + assert self.avatarNodePath.getPos().almostEqual(physObject.getPosition(), 0.0001) + #assert self.avatarNodePath.getH()==debugTempH-rotation + messenger.send("avatarMoving") + else: + self.__vel.set(0.0, 0.0, 0.0) + # Clear the contact vector so we can tell if we contact something next frame: + self.actorNode.setContactVector(Vec3.zero()) + return Task.cont + + def doDeltaPos(self): + assert(self.debugPrint("doDeltaPos()")) + self.needToDeltaPos = 1 + + def setPriorParentVector(self): + assert(self.debugPrint("doDeltaPos()")) + + print "self.__oldDt", self.__oldDt, "self.__oldPosDelta", self.__oldPosDelta + if __debug__: + onScreenDebug.add("__oldDt", "% 10.4f"%self.__oldDt) + onScreenDebug.add("self.__oldPosDelta", + self.__oldPosDelta.pPrintValues()) + + velocity = self.__oldPosDelta*(1/self.__oldDt)*4.0 # *4.0 is a hack + assert(self.debugPrint(" __oldPosDelta=%s"%(self.__oldPosDelta,))) + assert(self.debugPrint(" velocity=%s"%(velocity,))) + self.priorParent.setVector(Vec3(velocity)) + if __debug__: + if self.wantAvatarPhysicsIndicator: + onScreenDebug.add("velocity", velocity.pPrintValues()) + + def reset(self): + assert(self.debugPrint("reset()")) + self.actorNode.getPhysicsObject().resetPosition(self.avatarNodePath.getPos()) + self.priorParent.setVector(Vec3.zero()) + self.highMark = 0 + self.actorNode.setContactVector(Vec3.zero()) + if __debug__: + contact=self.actorNode.getContactVector() + onScreenDebug.add("priorParent po", + self.priorParent.getVector(self.actorNode.getPhysicsObject()).pPrintValues()) + onScreenDebug.add("highMark", "% 10.4f"%(self.highMark,)) + onScreenDebug.add("contact", contact.pPrintValues()) + + def enableAvatarControls(self): + """ + Activate the arrow keys, etc. + """ + assert(self.debugPrint("enableAvatarControls()")) + assert self.collisionsActive + + if __debug__: + #self.accept("control-f3", self.spawnTest) #*# + self.accept("f3", self.reset) # for debugging only. + + taskName = "AvatarControls-%s"%(id(self),) + # remove any old + taskMgr.remove(taskName) + # spawn the new task + taskMgr.add(self.handleAvatarControls, taskName, 25) + if self.physVelocityIndicator: + taskMgr.add(self.avatarPhysicsIndicator, "AvatarControlsIndicator%s"%(id(self),), 35) + + def disableAvatarControls(self): + """ + Ignore the arrow keys, etc. + """ + assert(self.debugPrint("disableAvatarControls()")) + taskName = "AvatarControls-%s"%(id(self),) + taskMgr.remove(taskName) + + taskName = "AvatarControlsIndicator%s"%(id(self),) + taskMgr.remove(taskName) + + if __debug__: + self.ignore("control-f3") #*# + self.ignore("f3") + + + if __debug__: + def setupAvatarPhysicsIndicator(self): + if self.wantAvatarPhysicsIndicator: + indicator=loader.loadModelCopy('phase_5/models/props/dagger') + #self.walkControls.setAvatarPhysicsIndicator(indicator) + + def debugPrint(self, message): + """for debugging""" + return self.notify.debug( + str(id(self))+' '+message)