From 6e32e478cff34936b8c72ff6e69cf33d8263b10c Mon Sep 17 00:00:00 2001 From: Josh Wilson Date: Thu, 25 Jan 2007 05:24:40 +0000 Subject: [PATCH] ships now have their own control manager that the avatar uses when he takes the wheel --- direct/src/controls/ControlManager.py | 14 +- direct/src/controls/ShipPilot.py | 795 ++++++-------------------- 2 files changed, 185 insertions(+), 624 deletions(-) diff --git a/direct/src/controls/ControlManager.py b/direct/src/controls/ControlManager.py index 8592981f59..93a3c3a19e 100755 --- a/direct/src/controls/ControlManager.py +++ b/direct/src/controls/ControlManager.py @@ -13,7 +13,6 @@ from direct.directnotify import DirectNotifyGlobal #if __debug__: # import DevWalker from direct.task import Task - CollisionHandlerRayStart = 4000.0 # This is a hack, it may be better to use a line instead of a ray. class ControlManager: @@ -162,6 +161,7 @@ class ControlManager: def delete(self): assert self.notify.debugCall(id(self)) self.disable() + # TODO: put controls delete code in here del self.controls del self.currentControls @@ -201,13 +201,21 @@ class ControlManager: def enable(self): assert self.notify.debugCall(id(self)) self.isEnabled = 1 - self.currentControls.enableAvatarControls() + if self.currentControls: + self.currentControls.enableAvatarControls() def disable(self): assert self.notify.debugCall(id(self)) self.isEnabled = 0 - self.currentControls.disableAvatarControls() + if self.currentControls: + self.currentControls.disableAvatarControls() + def stop(self): + self.disable() + self.currentControls.setCollisionsActive(0) + self.currentControls.setAvatar(None) + self.currentControls = None + def disableAvatarJump(self): """ prevent diff --git a/direct/src/controls/ShipPilot.py b/direct/src/controls/ShipPilot.py index 9f085ff4ad..65474e545e 100755 --- a/direct/src/controls/ShipPilot.py +++ b/direct/src/controls/ShipPilot.py @@ -16,7 +16,6 @@ animations based on control events. """ from direct.directnotify.DirectNotifyGlobal import directNotify -from pandac.PandaModules import PhysicsManager from direct.controls.ControlManager import CollisionHandlerRayStart from direct.showbase.InputStateGlobal import inputState from direct.task.Task import Task @@ -26,15 +25,10 @@ import math from PhysicsWalker import PhysicsWalker class ShipPilot(PhysicsWalker): - notify = directNotify.newCategory("PhysicsWalker") wantDebugIndicator = base.config.GetBool( 'want-avatar-physics-indicator', 0) - useBowSternSpheres = 1 - useLifter = 0 - useHeightRay = 0 - # special methods def __init__(self, gravity = -32.1740, standableGround=0.707, hardLandingForce=16.0): @@ -43,326 +37,19 @@ class ShipPilot(PhysicsWalker): gravity, standableGround)) PhysicsWalker.__init__( self, gravity, standableGround, hardLandingForce) - 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 + self.currentTurning = 0.0 + self.ship = None + self.pusher = None 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 setAvatar(self, ship): - if ship is None: - self.takedownPhysics() - self.ship = None - else: - #self.setupShip() - self.setupPhysics(ship) - self.ship = ship - - #*# Debug: - if not hasattr(ship, "acceleration"): - self.ship.acceleration = 60 - self.ship.maxSpeed = 14 - self.ship.reverseAcceleration = 10 - self.ship.maxReverseSpeed = 2 - self.ship.turnRate = 3 - self.ship.maxTurn = 30 - self.ship.anchorDrag = .9 - self.ship.hullDrag = .9 - - 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( - #spammy --> "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 - if 0: - self.avatarRadius = avatarRadius - self.cSphere = CollisionTube( - Point3(0.0, 0.0, 0.0), Point3(0.0, 40.0, 0.0), avatarRadius) - cSphereNode = CollisionNode('SP.cSphereNode') - cSphereNode.addSolid(self.cSphere) - self.cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode) - self.cSphereBitMask = bitmask - else: - # Middle sphere: - self.avatarRadius = avatarRadius - #self.cSphere = CollisionSphere(0.0, -5.0, 0.0, avatarRadius) - #cSphereNode = CollisionNode('SP.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) - - if self.useBowSternSpheres: - # Front sphere: - self.cBowSphere = CollisionSphere( - 0.0, self.frontSphereOffset, -5.0, avatarRadius) - cBowSphereNode = CollisionNode('SP.cBowSphereNode') - cBowSphereNode.addSolid(self.cBowSphere) - self.cBowSphereNodePath = self.avatarNodePath.attachNewNode( - cBowSphereNode) - - cBowSphereNode.setFromCollideMask(self.cSphereBitMask) - cBowSphereNode.setIntoCollideMask(BitMask32.allOff()) - - self.cBowSphereNode = cBowSphereNode - - self.pusher.addCollider( - self.cBowSphereNodePath, self.avatarNodePath) - - # Back sphere: - self.cSternSphere = CollisionSphere( - 0.0, self.backSphereOffset, -5.0, avatarRadius) - cSternSphereNode = CollisionNode('SP.cSternSphereNode') - cSternSphereNode.addSolid(self.cSternSphere) - self.cSternSphereNodePath = self.avatarNodePath.attachNewNode( - cSternSphereNode) - self.cSternSphereBitMask = bitmask - - cSternSphereNode.setFromCollideMask(self.cSphereBitMask) - cSternSphereNode.setIntoCollideMask(BitMask32.allOff()) - - self.pusher.addCollider( - self.cSternSphereNodePath, self.avatarNodePath) - - # hide other things on my ship that these spheres might collide - # with and which I dont need anyways... - shipCollWall = self.avatarNodePath.hull.find("**/collision_hull") - if not shipCollWall.isEmpty(): - shipCollWall.stash() - - def takedownPhysics(self): - assert self.debugPrint("takedownPhysics()") - if hasattr(self, "phys"): - for i in self.nodes: - i.removeNode() - del self.phys - if self.ship != None: - self.ship.worldVelocity = Vec3.zero() - - def setupPhysics(self, avatarNodePath): - assert self.debugPrint("setupPhysics()") - if avatarNodePath is None: - return - assert not avatarNodePath.isEmpty() - - self.takedownPhysics() - self.nodes = [] - self.phys=PhysicsManager() - - if 0: - # Connect to Physics Manager: - self.actorNode=ActorNode("ship-physicsActor") - self.actorNode.getPhysicsObject().setOriented(1) - self.actorNode.getPhysical(0).setViscosity(0.1) - physicsActor=render.attachNewNode(self.actorNode) - physicsActor.setPos(avatarNodePath, Vec3(0)) - physicsActor.setHpr(avatarNodePath, Vec3(0)) - avatarNodePath.reparentTo(physicsActor) - avatarNodePath.setPos(Vec3(0)) - avatarNodePath.setHpr(Vec3(0)) - avatarNodePath.assign(physicsActor) - else: - physicsActor = avatarNodePath - self.actorNode = physicsActor.node() - self.actorNode.getPhysicsObject().setOriented(1) - self.actorNode.getPhysical(0).setViscosity(0.1) - - fn=ForceNode("ship gravity") - fnp=NodePath(fn) - #fnp.reparentTo(physicsActor) - fnp.reparentTo(render) - self.nodes.append(fnp) - gravity=LinearVectorForce(0.0, 0.0, self.__gravity) - fn.addForce(gravity) - self.phys.addLinearForce(gravity) - self.gravity = gravity - - if 0: - fn=ForceNode("ship buoyancy") - fnp=NodePath(fn) - #fnp.reparentTo(physicsActor) - fnp.reparentTo(render) - self.nodes.append(fnp) - buoyancy=LinearVectorForce(0.0, 0.0, 0.0) - fn.addForce(buoyancy) - self.phys.addLinearForce(buoyancy) - self.buoyancy = buoyancy - - fn=ForceNode("ship keel") - fnp=NodePath(fn) - #fnp.reparentTo(physicsActor) - fnp.reparentTo(render) - self.nodes.append(fnp) - self.keel=AngularVectorForce(0.0, 0.0, 0.0) - fn.addForce(self.keel) - self.phys.addAngularForce(self.keel) - - fn=ForceNode("ship priorParent") - fnp=NodePath(fn) - fnp.reparentTo(render) - self.nodes.append(fnp) - priorParent=LinearVectorForce(0.0, 0.0, 0.0) - fn.addForce(priorParent) - self.phys.addLinearForce(priorParent) - self.priorParentNp = fnp - self.priorParent = priorParent - - if 1: - fn=ForceNode("ship viscosity") - fnp=NodePath(fn) - #fnp.reparentTo(physicsActor) - fnp.reparentTo(render) - self.nodes.append(fnp) - self.avatarViscosity=LinearFrictionForce(0.0, 1.0, 0) - self.avatarViscosity.setCoef(0.5) - self.avatarViscosity.setAmplitude(2) - fn.addForce(self.avatarViscosity) - self.phys.addLinearForce(self.avatarViscosity) - - self.phys.attachLinearIntegrator(LinearEulerIntegrator()) - self.phys.attachAngularIntegrator(AngularEulerIntegrator()) - self.phys.attachPhysicalNode(physicsActor.node()) - - if 0: - self.momentumForce=LinearVectorForce(0.0, 0.0, 0.0) - fn=ForceNode("ship momentum") - fnp=NodePath(fn) - fnp.reparentTo(render) - self.nodes.append(fnp) - fn.addForce(self.momentumForce) - self.phys.addLinearForce(self.momentumForce) - - self.acForce=LinearVectorForce(0.0, 0.0, 0.0) - self.acForce.setAmplitude(5) - fn=ForceNode("ship avatarControls") - fnp=NodePath(fn) - fnp.reparentTo(render) - self.nodes.append(fnp) - fn.addForce(self.acForce) - self.phys.addLinearForce(self.acForce) - #self.phys.removeLinearForce(self.acForce) - #fnp.remove() - - if 0 or self.useHeightRay: - #self.setupRay(self.floorBitmask, self.avatarRadius) - self.setupRay(self.floorBitmask, 0.0) - - - #avatarNodePath.reparentTo(render) - self.avatarNodePath = avatarNodePath - #self.actorNode.getPhysicsObject().resetPosition(self.avatarNodePath.getPos()) - #self.actorNode.updateTransform() - self.setupSphere(self.wallBitmask|self.floorBitmask, self.avatarRadius) - - - assert not avatarNodePath.isEmpty() - - self.setCollisionsActive(1) + PhysicsWalker.setWalkSpeed(self, forward, 0, reverse, rotate) def setWallBitMask(self, bitMask): self.wallBitmask = bitMask @@ -370,47 +57,136 @@ class ShipPilot(PhysicsWalker): def setFloorBitMask(self, bitMask): self.floorBitmask = bitMask - def initializeCollisions(self, collisionTraverser, - avatarRadius = 1.4, floorOffset = 1.0, reach = 1.0, - frontSphereOffset = 35.0, backSphereOffset = -80.0): + def setShip(self, ship): + self.setAvatar(ship) + + def setAvatar(self, ship): + if ship is None: + base.controlForce.clearPhysicsObject() + self.takedownPhysics() + self.ship = None + self.setCollisionsActive(0) + else: + base.controlForce.setPhysicsObject(ship.node().getPhysicsObject()) + self.ship = ship + self.setupPhysics(ship) + self.setCollisionsActive(1) + + def initializeCollisions(self, collisionTraverser, cRootNodePath, + bow, stern, starboard, port): """ - Set up the avatar collisions + Set up the avatar collisions. All we do here is assign + the traverser. All the ship specific stuff happens in + setAvatar() and its helper functions. """ assert self.debugPrint("initializeCollisions()") self.cTrav = collisionTraverser - self.avatarRadius = avatarRadius - self.floorOffset = floorOffset - self.reach = reach - if self.useBowSternSpheres: - self.frontSphereOffset = frontSphereOffset - self.backSphereOffset = backSphereOffset + self.cRootNodePath = cRootNodePath + self.bowPos = bow.getPos(cRootNodePath) + self.sternPos = stern.getPos(cRootNodePath) + self.starboardPos = starboard.getPos(cRootNodePath) + self.portPos = port.getPos(cRootNodePath) + + + def setupCollisions(self): + if self.pusher: + return + """ + Set up the collision sphere + """ + # This is a sphere on the ground to detect barrier collisions + + # set up collision mechanism + self.pusher = PhysicsCollisionHandler() + self.pusher.setInPattern("enter%in") + self.pusher.setOutPattern("exit%in") + + # Front sphere: + sRadius = abs((self.portPos - self.starboardPos)[0] / 2.0) + cBowSphere = CollisionSphere( + 0.0, self.bowPos[1], 0.0, sRadius) + cBowSphereNode = CollisionNode('SP.cBowSphereNode') + cBowSphereNode.addSolid(cBowSphere) + self.cBowSphereNodePath = self.shipNodePath.attachNewNode( + cBowSphereNode) + # self.cBowSphereNodePath.show() + + self.pusher.addCollider( + self.cBowSphereNodePath, self.shipNodePath) + + # Back sphere: + cSternSphere = CollisionSphere( + 0.0, self.sternPos[1], 0.0, sRadius) + cSternSphereNode = CollisionNode('SP.cSternSphereNode') + cSternSphereNode.addSolid(cSternSphere) + self.cSternSphereNodePath = self.shipNodePath.attachNewNode( + cSternSphereNode) + # self.cSternSphereNodePath.show() + + self.pusher.addCollider( + self.cSternSphereNodePath, self.shipNodePath) + + # hide other things on my ship that these spheres might collide + # with and which I dont need anyways... + shipCollWall = self.shipNodePath.find("**/collision_hull") + if not shipCollWall.isEmpty(): + shipCollWall.stash() + + def setCollisionsActive(self, active = 1): + if active: + self.setupCollisions() + + assert self.debugPrint("collisionsActive(active=%s)"%(active,)) + if self.collisionsActive != active: + self.collisionsActive = active + shipCollWall = self.shipNodePath.find("**/collision_hull;+s") + if active: + self.cBowSphereNodePath.node().setFromCollideMask(self.wallBitmask | self.floorBitmask) + self.cBowSphereNodePath.node().setFromCollideMask(BitMask32.allOff()) + self.cSternSphereNodePath.node().setFromCollideMask(self.wallBitmask | self.floorBitmask) + self.cSternSphereNodePath.node().setFromCollideMask(BitMask32.allOff()) + self.cTrav.addCollider(self.cBowSphereNodePath, self.pusher) + self.cTrav.addCollider(self.cSternSphereNodePath, self.pusher) + shipCollWall.stash() + else: + self.cTrav.removeCollider(self.cBowSphereNodePath) + self.cTrav.removeCollider(self.cSternSphereNodePath) + shipCollWall.unstash() + # Now that we have disabled collisions, make one more pass + # right now to ensure we aren't standing in a wall. + self.oneTimeCollide() def deleteCollisions(self): + import pdb;pdb.set_trace() assert self.debugPrint("deleteCollisions()") del self.cTrav - if self.useHeightRay: - del self.cRayQueue - self.cRayNodePath.removeNode() - del self.cRayNodePath - - if hasattr(self, "cSphere"): - del self.cSphere + if hasattr(self, "cSphereNodePath"): self.cSphereNodePath.removeNode() del self.cSphereNodePath del self.pusher - self.getAirborneHeight = None + def setupPhysics(self, shipNodePath): + assert self.debugPrint("setupPhysics()") + if shipNodePath is None: + return + assert not shipNodePath.isEmpty() + + self.takedownPhysics() + + # these are used in collision setup and handleControls + self.shipNodePath = shipNodePath + self.actorNode = shipNodePath.node() + + def takedownPhysics(self): + assert self.debugPrint("takedownPhysics()") def setTag(self, key, value): if not hasattr(self, "collisionTags"): self.collisionTags = {} self.collisionTags[key] = value - def setAirborneHeightFunc(self, getAirborneHeight): - self.getAirborneHeight = getAirborneHeight - def setAvatarPhysicsIndicator(self, indicator): """ indicator is a NodePath @@ -429,7 +205,7 @@ class ShipPilot(PhysicsWalker): indicatorNode=render.attachNewNode("physVelocityIndicator") #indicatorNode.setScale(0.1) #indicatorNode.setP(90.0) - indicatorNode.setPos(self.avatarNodePath, 0.0, 0.0, 6.0) + indicatorNode.setPos(self.shipNodePath, 0.0, 0.0, 6.0) indicatorNode.setColor(0.0, 0.0, 1.0, 1.0) change.reparentTo(indicatorNode) @@ -438,7 +214,7 @@ class ShipPilot(PhysicsWalker): contactIndicatorNode=render.attachNewNode("physContactIndicator") contactIndicatorNode.setScale(0.25) contactIndicatorNode.setP(90.0) - contactIndicatorNode.setPos(self.avatarNodePath, 0.0, 0.0, 5.0) + contactIndicatorNode.setPos(self.shipNodePath, 0.0, 0.0, 5.0) contactIndicatorNode.setColor(1.0, 0.0, 0.0, 1.0) indicator.instanceTo(contactIndicatorNode) self.physContactIndicator=contactIndicatorNode @@ -448,7 +224,7 @@ class ShipPilot(PhysicsWalker): def avatarPhysicsIndicator(self, task): #assert self.debugPrint("avatarPhysicsIndicator()") # Velocity: - self.physVelocityIndicator.setPos(self.avatarNodePath, 0.0, 0.0, 6.0) + self.physVelocityIndicator.setPos(self.shipNodePath, 0.0, 0.0, 6.0) physObject=self.actorNode.getPhysicsObject() a=physObject.getVelocity() self.physVelocityIndicator.setScale(math.sqrt(a.length())) @@ -460,70 +236,12 @@ class ShipPilot(PhysicsWalker): self.physContactIndicator.hide() else: self.physContactIndicator.show() - self.physContactIndicator.setPos(self.avatarNodePath, 0.0, 0.0, 5.0) + self.physContactIndicator.setPos(self.shipNodePath, 0.0, 0.0, 5.0) #contact=self.actorNode.getContactVector() point=Point3(contact+self.physContactIndicator.getPos()) self.physContactIndicator.lookAt(point) return Task.cont - def setCollisionsActive(self, active = 1): - assert self.debugPrint("collisionsActive(active=%s)"%(active,)) - if self.collisionsActive != active: - self.collisionsActive = active - if active: - if self.useBowSternSpheres: - #self.cTrav.addCollider(self.cSphereNodePath, self.pusher) - self.cTrav.addCollider(self.cBowSphereNodePath, self.pusher) - self.cTrav.addCollider(self.cSternSphereNodePath, self.pusher) - if self.useHeightRay: - if self.useLifter: - self.cTrav.addCollider(self.cRayNodePath, self.lifter) - else: - self.cTrav.addCollider(self.cRayNodePath, self.cRayQueue) - else: - if self.useBowSternSpheres: - #self.cTrav.removeCollider(self.cSphereNodePath) - self.cTrav.removeCollider(self.cBowSphereNodePath) - self.cTrav.removeCollider(self.cSternSphereNodePath) - 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 addBlastForce(self, vector): - pass - def displayDebugInfo(self): """ For debug use. @@ -533,17 +251,15 @@ class ShipPilot(PhysicsWalker): onScreenDebug.add("w ship", self.ship) onScreenDebug.add("w isAirborne", self.isAirborne) onScreenDebug.add("posDelta1", - self.avatarNodePath.getPosDelta(render).pPrintValues()) + self.shipNodePath.getPosDelta(render).pPrintValues()) physObject=self.actorNode.getPhysicsObject() if 0: onScreenDebug.add("w posDelta3", render.getRelativeVector( - self.avatarNodePath, - self.avatarNodePath.getPosDelta(render)).pPrintValues()) + self.shipNodePath, + self.shipNodePath.getPosDelta(render)).pPrintValues()) if 0: - onScreenDebug.add("w gravity", - self.gravity.getLocalVector().pPrintValues()) onScreenDebug.add("w priorParent", self.priorParent.getLocalVector().pPrintValues()) @@ -560,20 +276,8 @@ class ShipPilot(PhysicsWalker): onScreenDebug.add("w physObject len", "% 10.4f"%physObject.length()) - acForce = self.acForce.getLocalVector() - onScreenDebug.add("w acForce vec", - acForce.pPrintValues()) - onScreenDebug.add("w acForce len", - "% 10.4f"%acForce.length()) - - onScreenDebug.add("w avatarViscosity", - "% 10.4f"%(self.avatarViscosity.getCoef(),)) - - #onScreenDebug.add("physMgr", - # self.phys.debugOutput()) onScreenDebug.add("orientation", self.actorNode.getPhysicsObject().getOrientation().pPrintValues()) - #print "ship orientation:", self.actorNode.getPhysicsObject().getOrientation().pPrintValues() if 0: momentumForce = self.momentumForce.getLocalVector() @@ -582,16 +286,12 @@ class ShipPilot(PhysicsWalker): onScreenDebug.add("w momentumForce len", "% 10.4f"%momentumForce.length()) - ## if 1: - ## keel = self.keel.getLocalVector() - ## onScreenDebug.add("w keel vec", - ## keel.pPrintValues()) if 0: onScreenDebug.add("posDelta4", self.priorParentNp.getRelativeVector( render, - self.avatarNodePath.getPosDelta(render)).pPrintValues()) - if 1: + self.shipNodePath.getPosDelta(render)).pPrintValues()) + if 0: onScreenDebug.add("w priorParent", self.priorParent.getLocalVector().pPrintValues()) if 0: @@ -601,8 +301,6 @@ class ShipPilot(PhysicsWalker): if 1: onScreenDebug.add("w contact", self.actorNode.getContactVector().pPrintValues()) - #onScreenDebug.add("airborneHeight", "% 10.4f"%( - # self.getAirborneHeight(),)) def handleAvatarControls(self, task): """ @@ -614,28 +312,9 @@ class ShipPilot(PhysicsWalker): base.localAvatar.getPos().pPrintValues(),)) onScreenDebug.append("localAvatar hpr = %s\n"%( base.localAvatar.getHpr().pPrintValues(),)) - #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() - - depth=physObject.getPosition().getZ() - if depth < 0.0: - # self.buoyancy.setVector(Vec3.zero()) - pass - else: - # self.buoyancy.setVector(Vec3.zero()) - physObject.setPosition(Point3( - physObject.getPosition().getX(), - physObject.getPosition().getY(), - 0.0)) - self.actorNode.updateTransform() - #self.buoyancy.setVector(Vec3(0, 0, -depth)) + physObject = self.actorNode.getPhysicsObject() + contact = self.actorNode.getContactVector() # get the button states: forward = inputState.isSet("forward") @@ -648,6 +327,14 @@ class ShipPilot(PhysicsWalker): jump = inputState.isSet("jump") # Determine what the speeds are based on the buttons: + # Check for Auto-Sailing + if self.ship.getIsAutoSailing(): + forward = 1 + reverse = 0 + + # How far did we move based on the amount of time elapsed? + dt=ClockObject.getGlobalClock().getDt() + # this was causing the boat to get stuck moving forward or back if 0: if not hasattr(self, "sailsDeployed"): @@ -666,8 +353,11 @@ class ShipPilot(PhysicsWalker): self.sailsDeployed = -1.0 self.__speed = self.ship.acceleration * self.sailsDeployed else: - self.__speed=(forward and self.ship.acceleration or - reverse and -self.ship.reverseAcceleration) + self.__speed=(forward and self.ship.acceleration) or \ + (reverse and -self.ship.reverseAcceleration) + #self.__speed=(forward and min(dt*(self.__speed + self.ship.acceleration), self.ship.maxSpeed) or + # reverse and min(dt*(self.__speed - self.ship.reverseAcceleration), self.ship.maxReverseSpeed)) + avatarSlideSpeed=self.ship.acceleration*0.5 #self.__slideSpeed=slide and ( # (turnLeft and -avatarSlideSpeed) or @@ -678,8 +368,7 @@ class ShipPilot(PhysicsWalker): self.__rotationSpeed=not slide and ( (turnLeft and self.ship.turnRate) or (turnRight and -self.ship.turnRate)) - - + # Enable debug turbo mode maxSpeed = self.ship.maxSpeed if __debug__: @@ -690,10 +379,12 @@ class ShipPilot(PhysicsWalker): self.__rotationSpeed*=1.25 maxSpeed = self.ship.maxSpeed * 4.0 - + self.__speed*=4.0 + self.__slideSpeed*=4.0 + self.__rotationSpeed*=1.25 + maxSpeed = self.ship.maxSpeed * 4.0 + #*# - if not hasattr(self, "currentTurning"): - self.currentTurning = 0.0 self.currentTurning += self.__rotationSpeed if self.currentTurning > self.ship.maxTurn: self.currentTurning = self.ship.maxTurn @@ -714,119 +405,21 @@ class ShipPilot(PhysicsWalker): if self.wantDebugIndicator: self.displayDebugInfo() - # How far did we move based on the amount of time elapsed? - dt=ClockObject.getGlobalClock().getDt() - if self.needToDeltaPos: self.setPriorParentVector() self.needToDeltaPos = 0 - 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: - messenger.send("jumpHardLand") - else: - messenger.send("jumpLand") - self.priorParent.setVector(Vec3.zero()) - self.isAirborne = 0 - elif 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 - - #debugTempH=self.avatarNodePath.getH() + #------------------------------ + #debugTempH=self.shipNodePath.getH() if __debug__: - q1=self.avatarNodePath.getQuat() + q1=self.shipNodePath.getQuat() q2=physObject.getOrientation() q1.normalize() q2.normalize() assert q1.isSameDirection(q2) or (q1.getHpr() == q2.getHpr()) - assert self.avatarNodePath.getPos().almostEqual(physObject.getPosition(), 0.0001) - - 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") - - #debugTempH=self.avatarNodePath.getH() - if __debug__: - q1=self.avatarNodePath.getQuat() - q2=physObject.getOrientation() - q1.normalize() - q2.normalize() - assert q1.isSameDirection(q2) or (q1.getHpr() == q2.getHpr()) - assert self.avatarNodePath.getPos().almostEqual(physObject.getPosition(), 0.0001) + assert self.shipNodePath.getPos().almostEqual( + physObject.getPosition(), 0.0001) + #------------------------------ # Check to see if we're moving at all: physVel = physObject.getVelocity() @@ -834,13 +427,11 @@ class ShipPilot(PhysicsWalker): if (physVelLen!=0. or self.__speed or self.__slideSpeed - or self.__rotationSpeed - or moveToGround!=Vec3.zero()): + or self.__rotationSpeed): distance = dt * self.__speed goForward = True if (distance < 0): goForward = False - distance /= 5 slideDistance = dt * self.__slideSpeed rotation = dt * self.__rotationSpeed @@ -853,7 +444,7 @@ class ShipPilot(PhysicsWalker): # rotMat is the rotation matrix corresponding to # our previous heading. rotMat=Mat3.rotateMatNormaxis( - self.avatarNodePath.getH(), Vec3.up()) + self.shipNodePath.getH(), Vec3.up()) step=rotMat.xform(self.__vel) #newVector = self.acForce.getLocalVector()+Vec3(step) @@ -869,24 +460,20 @@ class ShipPilot(PhysicsWalker): newVector *= maxLen - newVector.normalize() - newVector *= maxLen if __debug__: - onScreenDebug.add("newVector", - newVector) - onScreenDebug.add("newVector length", - newVector.length()) - self.acForce.setVector(Vec3(newVector)) - + onScreenDebug.add( + "newVector", newVector) + onScreenDebug.add( + "newVector length", newVector.length()) + base.controlForce.setVector(newVector) + assert base.controlForce.getLocalVector() == newVector + assert base.controlForce.getPhysicsObject() + assert base.controlForce.getPhysicsObject() == physObject #momentum = self.momentumForce.getLocalVector() #momentum *= 0.9 #self.momentumForce.setVector(momentum) - - #physObject.setPosition(Point3( - # physObject.getPosition()+step+moveToGround)) - # update hpr: o=physObject.getOrientation() r=LRotationf() @@ -895,12 +482,12 @@ class ShipPilot(PhysicsWalker): # sync the change: self.actorNode.updateTransform() - #assert self.avatarNodePath.getH()==debugTempH-rotation + #assert self.shipNodePath.getH()==debugTempH-rotation messenger.send("avatarMoving") else: # even if there are no active inputs, we still might be moving assert physObject.getVelocity().length() == 0. - self.__vel.set(0.0, 0.0, 0.0) + #base.controlForce.setVector(Vec3.zero()) goForward = True @@ -920,9 +507,9 @@ class ShipPilot(PhysicsWalker): # modify based on sail damage speed *= self.ship.Sp speed /= self.ship.maxSp - physObject.setVelocity(speed) + ## physObject.setVelocity(speed) - #rotMat=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up()) + #rotMat=Mat3.rotateMatNormaxis(self.shipNodePath.getH(), Vec3.up()) #speed=rotMat.xform(speed) # The momentumForce makes it feel like we are sliding on ice -- Joe # f = Vec3(self.__vel) @@ -931,28 +518,29 @@ class ShipPilot(PhysicsWalker): if __debug__: - q1=self.avatarNodePath.getQuat() + q1=self.shipNodePath.getQuat() q2=physObject.getOrientation() q1.normalize() q2.normalize() assert q1.isSameDirection(q2) or q1.getHpr() == q2.getHpr() - assert self.avatarNodePath.getPos().almostEqual(physObject.getPosition(), 0.0001) + assert self.shipNodePath.getPos().almostEqual( + physObject.getPosition(), 0.0001) # Clear the contact vector so we can # tell if we contact something next frame self.actorNode.setContactVector(Vec3.zero()) - self.__oldPosDelta = self.avatarNodePath.getPosDelta(render) - self.__oldDt = dt + oldPosDelta = self.shipNodePath.getPosDelta(render) + oldDt = dt assert hasattr(self.ship, 'worldVelocity') - self.ship.worldVelocity = self.__oldPosDelta*(1/self.__oldDt) + self.ship.worldVelocity = oldPosDelta*(1/oldDt) if self.wantDebugIndicator: onScreenDebug.add("w __oldPosDelta vec", - self.__oldPosDelta.pPrintValues()) + oldPosDelta.pPrintValues()) onScreenDebug.add("w __oldPosDelta len", - "% 10.4f"%self.__oldPosDelta.length()) + "% 10.4f"%oldPosDelta.length()) onScreenDebug.add("w __oldDt", - "% 10.4f"%self.__oldDt) + "% 10.4f"%oldDt) onScreenDebug.add("w worldVelocity vec", self.ship.worldVelocity.pPrintValues()) onScreenDebug.add("w worldVelocity len", @@ -966,41 +554,6 @@ class ShipPilot(PhysicsWalker): 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.wantDebugIndicator: - 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 getVelocity(self): return self.__vel @@ -1024,7 +577,7 @@ class ShipPilot(PhysicsWalker): taskMgr.add( self.avatarPhysicsIndicator, "AvatarControlsIndicator%s"%(id(self),), 35) - + def disableAvatarControls(self): """ Ignore the arrow keys, etc.