Advertisement
Guest User

Untitled

a guest
Jun 25th, 2017
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 28.32 KB | None | 0 0
  1. """
  2. GravityWalker.py is for avatars.
  3.  
  4. A walker control such as this one provides:
  5. - creation of the collision nodes
  6. - handling the keyboard and mouse input for avatar movement
  7. - moving the avatar
  8.  
  9. it does not:
  10. - play sounds
  11. - play animations
  12.  
  13. although it does send messeges that allow a listener to play sounds or
  14. animations based on walker events.
  15. """
  16. from direct.directnotify.DirectNotifyGlobal import directNotify
  17. from direct.showbase import DirectObject
  18. from direct.controls.ControlManager import CollisionHandlerRayStart
  19. from direct.showbase.InputStateGlobal import inputState
  20. from direct.task.Task import Task
  21. from pandac.PandaModules import *
  22. import math
  23.  
  24.  
  25. class GravityWalker(DirectObject.DirectObject):
  26. notify = directNotify.newCategory("GravityWalker")
  27. wantDebugIndicator = 1# base.config.GetBool('want-avatar-physics-indicator', 0)
  28. wantFloorSphere = 0 #base.config.GetBool('want-floor-sphere', 0)
  29. earlyEventSphere = 0 #base.config.GetBool('early-event-sphere', 0)
  30.  
  31. DiagonalFactor = math.sqrt(2.) / 2.
  32.  
  33. # special methods
  34. def __init__(self, gravity = 64.348, standableGround=0.707,
  35. hardLandingForce=16.0, legacyLifter=False):
  36. assert self.notify.debugStateCall(self)
  37. DirectObject.DirectObject.__init__(self)
  38. self.__gravity=gravity
  39. self.__standableGround=standableGround
  40. self.__hardLandingForce=hardLandingForce
  41. self._legacyLifter = legacyLifter
  42.  
  43. self.mayJump = 1
  44. self.jumpDelayTask = None
  45.  
  46. self.controlsTask = None
  47. self.indicatorTask = None
  48.  
  49. self.falling = 0
  50. self.needToDeltaPos = 0
  51. self.physVelocityIndicator=None
  52. self.avatarControlForwardSpeed=0
  53. self.avatarControlJumpForce=0
  54. self.avatarControlReverseSpeed=0
  55. self.avatarControlRotateSpeed=0
  56. self.getAirborneHeight=None
  57.  
  58. self.priorParent=Vec3(0)
  59. self.__oldPosDelta=Vec3(0)
  60. self.__oldDt=0
  61.  
  62. self.moving=0
  63. self.speed=0.0
  64. self.rotationSpeed=0.0
  65. self.slideSpeed=0.0
  66. self.vel=Vec3(0.0)
  67. self.collisionsActive = 0
  68.  
  69. self.isAirborne = 0
  70. self.highMark = 0
  71.  
  72. """
  73. def spawnTest(self):
  74. assert self.notify.debugStateCall(self)
  75. if not self.wantDebugIndicator:
  76. return
  77. from pandac.PandaModules import *
  78. from direct.interval.IntervalGlobal import *
  79. from toontown.coghq import MovingPlatform
  80.  
  81. if hasattr(self, "platform"):
  82. # Remove the prior instantiation:
  83. self.moveIval.pause()
  84. del self.moveIval
  85. self.platform.destroy()
  86. del self.platform
  87. self.platform2.destroy()
  88. del self.platform2
  89.  
  90. model = loader.loadModel('phase_9/models/cogHQ/platform1')
  91. fakeId = id(self)
  92. self.platform = MovingPlatform.MovingPlatform()
  93. self.platform.setupCopyModel(fakeId, model, 'platformcollision')
  94. self.platformRoot = render.attachNewNode("GravityWalker-spawnTest-%s"%fakeId)
  95. self.platformRoot.setPos(base.localAvatar, Vec3(0.0, 0.0, 1.0))
  96. self.platformRoot.setHpr(base.localAvatar, Vec3.zero())
  97. self.platform.reparentTo(self.platformRoot)
  98.  
  99. self.platform2 = MovingPlatform.MovingPlatform()
  100. self.platform2.setupCopyModel(1+fakeId, model, 'platformcollision')
  101. self.platform2Root = render.attachNewNode("GravityWalker-spawnTest2-%s"%fakeId)
  102. self.platform2Root.setPos(base.localAvatar, Vec3(-16.0, 30.0, 1.0))
  103. self.platform2Root.setHpr(base.localAvatar, Vec3.zero())
  104. self.platform2.reparentTo(self.platform2Root)
  105.  
  106. duration = 5
  107. self.moveIval = Parallel(
  108. Sequence(
  109. WaitInterval(0.3),
  110. LerpPosInterval(self.platform, duration,
  111. Vec3(0.0, 30.0, 0.0),
  112. name='platformOut%s' % fakeId,
  113. fluid = 1),
  114. WaitInterval(0.3),
  115. LerpPosInterval(self.platform, duration,
  116. Vec3(0.0, 0.0, 0.0),
  117. name='platformBack%s' % fakeId,
  118. fluid = 1),
  119. WaitInterval(0.3),
  120. LerpPosInterval(self.platform, duration,
  121. Vec3(0.0, 0.0, 30.0),
  122. name='platformUp%s' % fakeId,
  123. fluid = 1),
  124. WaitInterval(0.3),
  125. LerpPosInterval(self.platform, duration,
  126. Vec3(0.0, 0.0, 0.0),
  127. name='platformDown%s' % fakeId,
  128. fluid = 1),
  129. ),
  130. Sequence(
  131. WaitInterval(0.3),
  132. LerpPosInterval(self.platform2, duration,
  133. Vec3(0.0, -30.0, 0.0),
  134. name='platform2Out%s' % fakeId,
  135. fluid = 1),
  136. WaitInterval(0.3),
  137. LerpPosInterval(self.platform2, duration,
  138. Vec3(0.0, 30.0, 30.0),
  139. name='platform2Back%s' % fakeId,
  140. fluid = 1),
  141. WaitInterval(0.3),
  142. LerpPosInterval(self.platform2, duration,
  143. Vec3(0.0, -30.0, 0.0),
  144. name='platform2Up%s' % fakeId,
  145. fluid = 1),
  146. WaitInterval(0.3),
  147. LerpPosInterval(self.platform2, duration,
  148. Vec3(0.0, 0.0, 0.0),
  149. name='platformDown%s' % fakeId,
  150. fluid = 1),
  151. ),
  152. name='platformIval%s' % fakeId,
  153. )
  154. self.moveIval.loop()
  155. """
  156. def setWalkSpeed(self, forward, jump, reverse, rotate):
  157. assert self.notify.debugStateCall(self)
  158. self.avatarControlForwardSpeed=forward
  159. self.avatarControlJumpForce=jump
  160. self.avatarControlReverseSpeed=reverse
  161. self.avatarControlRotateSpeed=rotate
  162.  
  163. def getSpeeds(self):
  164. #assert self.debugPrint("getSpeeds()")
  165. return (self.speed, self.rotationSpeed, self.slideSpeed)
  166.  
  167. def getIsAirborne(self):
  168. return self.isAirborne
  169.  
  170. def setAvatar(self, avatar):
  171. self.avatar = avatar
  172. if avatar is not None:
  173. pass # setup the avatar
  174.  
  175. def setupRay(self, bitmask, floorOffset, reach):
  176. assert self.notify.debugStateCall(self)
  177. # This is a ray cast from your head down to detect floor polygons.
  178. # This ray start is arbitrarily high in the air. Feel free to use
  179. # a higher or lower value depending on whether you want an avatar
  180. # that is outside of the world to step up to the floor when they
  181. # get under valid floor:
  182. cRay = CollisionRay(0.0, 0.0, CollisionHandlerRayStart, 0.0, 0.0, -1.0)
  183. cRayNode = CollisionNode('GW.cRayNode')
  184. cRayNode.addSolid(cRay)
  185. self.cRayNodePath = self.avatarNodePath.attachNewNode(cRayNode)
  186. cRayNode.setFromCollideMask(bitmask)
  187. cRayNode.setIntoCollideMask(BitMask32.allOff())
  188.  
  189. # set up floor collision mechanism
  190. self.lifter = CollisionHandlerGravity()
  191. #self.lifter = CollisionHandlerHighestEvent()
  192. self.lifter.setLegacyMode(self._legacyLifter)
  193. self.lifter.setGravity(self.__gravity)
  194. self.lifter.addInPattern("enter%in")
  195. self.lifter.addAgainPattern("again%in")
  196. self.lifter.addOutPattern("exit%in")
  197. self.lifter.setOffset(floorOffset)
  198. self.lifter.setReach(reach)
  199.  
  200. # Limit our rate-of-fall with the lifter.
  201. # If this is too low, we actually "fall" off steep stairs
  202. # and float above them as we go down. I increased this
  203. # from 8.0 to 16.0 to prevent this
  204. #self.lifter.setMaxVelocity(16.0)
  205.  
  206. self.lifter.addCollider(self.cRayNodePath, self.avatarNodePath)
  207.  
  208. def setupWallSphere(self, bitmask, avatarRadius):
  209. """
  210. Set up the collision sphere
  211. """
  212. assert self.notify.debugStateCall(self)
  213. # This is a sphere on the ground to detect collisions with
  214. # walls, but not the floor.
  215. self.avatarRadius = avatarRadius
  216. cSphere = CollisionSphere(0.0, 0.0, avatarRadius, avatarRadius)
  217. cSphereNode = CollisionNode('GW.cWallSphereNode')
  218. cSphereNode.addSolid(cSphere)
  219. cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
  220.  
  221. cSphereNode.setFromCollideMask(bitmask)
  222. cSphereNode.setIntoCollideMask(BitMask32.allOff())
  223.  
  224. # set up collision mechanism
  225. if config.GetBool('want-fluid-pusher', 0):
  226. self.pusher = CollisionHandlerFluidPusher()
  227. else:
  228. self.pusher = CollisionHandlerPusher()
  229. self.pusher.addCollider(cSphereNodePath, self.avatarNodePath)
  230. self.cWallSphereNodePath = cSphereNodePath
  231.  
  232. def setupEventSphere(self, bitmask, avatarRadius):
  233. """
  234. Set up the collision sphere
  235. """
  236. assert self.notify.debugStateCall(self)
  237. # This is a sphere a little larger than the wall sphere to
  238. # trigger events.
  239. self.avatarRadius = avatarRadius
  240. cSphere = CollisionSphere(0.0, 0.0, avatarRadius-0.1, avatarRadius*1.04)
  241. # Mark it intangible just to emphasize its non-physical purpose.
  242. cSphere.setTangible(0)
  243. cSphereNode = CollisionNode('GW.cEventSphereNode')
  244. cSphereNode.addSolid(cSphere)
  245. cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
  246.  
  247. cSphereNode.setFromCollideMask(bitmask)
  248. cSphereNode.setIntoCollideMask(BitMask32.allOff())
  249.  
  250. # set up collision mechanism
  251. self.event = CollisionHandlerEvent()
  252. self.event.addInPattern("enter%in")
  253. self.event.addOutPattern("exit%in")
  254. self.cEventSphereNodePath = cSphereNodePath
  255.  
  256. def setupFloorSphere(self, bitmask, avatarRadius):
  257. """
  258. Set up the collision sphere
  259. """
  260. assert self.notify.debugStateCall(self)
  261. # This is a tiny sphere concentric with the wallSphere to keep
  262. # us from slipping through floors.
  263. self.avatarRadius = avatarRadius
  264. cSphere = CollisionSphere(0.0, 0.0, avatarRadius, 0.01)
  265. cSphereNode = CollisionNode('GW.cFloorSphereNode')
  266. cSphereNode.addSolid(cSphere)
  267. cSphereNodePath = self.avatarNodePath.attachNewNode(cSphereNode)
  268.  
  269. cSphereNode.setFromCollideMask(bitmask)
  270. cSphereNode.setIntoCollideMask(BitMask32.allOff())
  271.  
  272. # set up collision mechanism
  273. self.pusherFloorhandler = CollisionHandlerPusher()
  274. self.pusherFloor.addCollider(cSphereNodePath, self.avatarNodePath)
  275. self.cFloorSphereNodePath = cSphereNodePath
  276.  
  277. def setWallBitMask(self, bitMask):
  278. self.wallBitmask = bitMask
  279.  
  280. def setFloorBitMask(self, bitMask):
  281. self.floorBitmask = bitMask
  282.  
  283. def swapFloorBitMask(self, oldMask, newMask):
  284. self.floorBitmask = self.floorBitmask &~ oldMask
  285. self.floorBitmask |= newMask
  286.  
  287. if self.cRayNodePath and not self.cRayNodePath.isEmpty():
  288. self.cRayNodePath.node().setFromCollideMask(self.floorBitmask)
  289.  
  290. def setGravity(self, gravity):
  291. self.__gravity = gravity
  292. self.lifter.setGravity(self.__gravity)
  293.  
  294. def getGravity(self, gravity):
  295. return self.__gravity
  296.  
  297. def initializeCollisions(self, collisionTraverser, avatarNodePath,
  298. avatarRadius = 1.4, floorOffset = 1.0, reach = 1.0):
  299. """
  300. floorOffset is how high the avatar can reach. I.e. if the avatar
  301. walks under a ledge that is <= floorOffset above the ground (a
  302. double floor situation), the avatar will step up on to the
  303. ledge (instantly).
  304.  
  305. Set up the avatar collisions
  306. """
  307. assert self.notify.debugStateCall(self)
  308.  
  309. assert not avatarNodePath.isEmpty()
  310. self.avatarNodePath = avatarNodePath
  311.  
  312. self.cTrav = collisionTraverser
  313.  
  314. self.setupRay(self.floorBitmask, floorOffset, reach)
  315. self.setupWallSphere(self.wallBitmask, avatarRadius)
  316. self.setupEventSphere(self.wallBitmask, avatarRadius)
  317. if self.wantFloorSphere:
  318. self.setupFloorSphere(self.floorBitmask, avatarRadius)
  319.  
  320. self.setCollisionsActive(1)
  321.  
  322. def setTag(self, key, value):
  323. self.cEventSphereNodePath.setTag(key, value)
  324.  
  325. def setAirborneHeightFunc(self, unused_parameter):
  326. assert self.notify.debugStateCall(self)
  327. self.getAirborneHeight = self.lifter.getAirborneHeight
  328.  
  329. def getAirborneHeight(self):
  330. assert self.notify.debugStateCall(self)
  331. self.lifter.getAirborneHeight()
  332.  
  333. def setAvatarPhysicsIndicator(self, indicator):
  334. """
  335. indicator is a NodePath
  336. """
  337. assert self.notify.debugStateCall(self)
  338. self.cWallSphereNodePath.show()
  339.  
  340. def deleteCollisions(self):
  341. assert self.notify.debugStateCall(self)
  342. del self.cTrav
  343.  
  344. self.cWallSphereNodePath.removeNode()
  345. del self.cWallSphereNodePath
  346. if self.wantFloorSphere:
  347. self.cFloorSphereNodePath.removeNode()
  348. del self.cFloorSphereNodePath
  349.  
  350. del self.pusher
  351. # del self.pusherFloor
  352. del self.event
  353. del self.lifter
  354.  
  355. del self.getAirborneHeight
  356.  
  357. def setCollisionsActive(self, active = 1):
  358. assert self.notify.debugStateCall(self)
  359. if self.collisionsActive != active:
  360. self.collisionsActive = active
  361. # Each time we change the collision geometry, make one
  362. # more pass to ensure we aren't standing in a wall.
  363. self.oneTimeCollide()
  364. # make sure we have a shadow traverser
  365. base.initShadowTrav()
  366. if active:
  367. if 1:
  368. # Please let skyler or drose know if this is causing a problem
  369. # This is a bit of a hack fix:
  370. self.avatarNodePath.setP(0.0)
  371. self.avatarNodePath.setR(0.0)
  372. self.cTrav.addCollider(self.cWallSphereNodePath, self.pusher)
  373. if self.wantFloorSphere:
  374. self.cTrav.addCollider(self.cFloorSphereNodePath, self.pusherFloor)
  375. # Add the lifter to the shadow traverser, which runs after
  376. # our traverser. This prevents the "fall through wall and
  377. # off ledge" bug. The problem was that we couldn't control
  378. # which collided first, the wall pusher or the lifter, if
  379. # they're in the same collision traverser. If the lifter
  380. # collided first, we'd start falling before getting pushed
  381. # back behind the wall.
  382. base.shadowTrav.addCollider(self.cRayNodePath, self.lifter)
  383.  
  384. if self.earlyEventSphere:
  385. # If we want to trigger the events at the same
  386. # time as we intersect walls (e.g. Toontown, for
  387. # backward compatibility issues), add the event
  388. # sphere to the main traverser. This allows us to
  389. # hit door triggers that are just slightly behind
  390. # the door itself.
  391. self.cTrav.addCollider(self.cEventSphereNodePath, self.event)
  392. else:
  393. # Normally, we'd rather trigger the events after
  394. # the pusher has had a chance to fix up our
  395. # position, so we never trigger things that are
  396. # behind other polygons.
  397. base.shadowTrav.addCollider(self.cEventSphereNodePath, self.event)
  398.  
  399. else:
  400. if hasattr(self, 'cTrav'):
  401. self.cTrav.removeCollider(self.cWallSphereNodePath)
  402. if self.wantFloorSphere:
  403. self.cTrav.removeCollider(self.cFloorSphereNodePath)
  404. self.cTrav.removeCollider(self.cEventSphereNodePath)
  405. base.shadowTrav.removeCollider(self.cEventSphereNodePath)
  406. base.shadowTrav.removeCollider(self.cRayNodePath)
  407.  
  408. def getCollisionsActive(self):
  409. assert self.debugPrint("getCollisionsActive() returning=%s"%(
  410. self.collisionsActive,))
  411. return self.collisionsActive
  412.  
  413. def placeOnFloor(self):
  414. """
  415. Make a reasonable effor to place the avatar on the ground.
  416. For example, this is useful when switching away from the
  417. current walker.
  418. """
  419. assert self.notify.debugStateCall(self)
  420. self.oneTimeCollide()
  421. self.avatarNodePath.setZ(self.avatarNodePath.getZ()-self.lifter.getAirborneHeight())
  422.  
  423. def oneTimeCollide(self):
  424. """
  425. Makes one quick collision pass for the avatar, for instance as
  426. a one-time straighten-things-up operation after collisions
  427. have been disabled.
  428. """
  429. assert self.notify.debugStateCall(self)
  430. if not hasattr(self, 'cWallSphereNodePath'):
  431. return
  432. self.isAirborne = 0
  433. self.mayJump = 1
  434. tempCTrav = CollisionTraverser("oneTimeCollide")
  435. tempCTrav.addCollider(self.cWallSphereNodePath, self.pusher)
  436. if self.wantFloorSphere:
  437. tempCTrav.addCollider(self.cFloorSphereNodePath, self.event)
  438. tempCTrav.addCollider(self.cRayNodePath, self.lifter)
  439. tempCTrav.traverse(render)
  440.  
  441. def setMayJump(self, task):
  442. """
  443. This function's use is internal to this class (maybe I'll add
  444. the __ someday). Anyway, if you want to enable or disable
  445. jumping in a general way see the ControlManager (don't use this).
  446. """
  447. assert self.notify.debugStateCall(self)
  448. self.mayJump = 1
  449. return Task.done
  450.  
  451. def startJumpDelay(self, delay):
  452. assert self.notify.debugStateCall(self)
  453. if self.jumpDelayTask:
  454. self.jumpDelayTask.remove()
  455. self.mayJump = 0
  456. self.jumpDelayTask=taskMgr.doMethodLater(
  457. delay,
  458. self.setMayJump,
  459. "jumpDelay-%s"%id(self))
  460.  
  461. def addBlastForce(self, vector):
  462. self.lifter.addVelocity(vector.length())
  463.  
  464. def displayDebugInfo(self):
  465. """
  466. For debug use.
  467. """
  468. onScreenDebug.add("w controls", "GravityWalker")
  469.  
  470. onScreenDebug.add("w airborneHeight", self.lifter.getAirborneHeight())
  471. onScreenDebug.add("w falling", self.falling)
  472. onScreenDebug.add("w isOnGround", self.lifter.isOnGround())
  473. #onScreenDebug.add("w gravity", self.lifter.getGravity())
  474. #onScreenDebug.add("w jumpForce", self.avatarControlJumpForce)
  475. onScreenDebug.add("w contact normal", self.lifter.getContactNormal().pPrintValues())
  476. onScreenDebug.add("w mayJump", self.mayJump)
  477. onScreenDebug.add("w impact", self.lifter.getImpactVelocity())
  478. onScreenDebug.add("w velocity", self.lifter.getVelocity())
  479. onScreenDebug.add("w isAirborne", self.isAirborne)
  480. onScreenDebug.add("w hasContact", self.lifter.hasContact())
  481.  
  482. def handleAvatarControls(self, task):
  483. """
  484. Check on the arrow keys and update the avatar.
  485. """
  486. # get the button states:
  487. run = inputState.isSet("run")
  488. forward = inputState.isSet("forward")
  489. reverse = inputState.isSet("reverse")
  490. turnLeft = inputState.isSet("turnLeft")
  491. turnRight = inputState.isSet("turnRight")
  492. slideLeft = inputState.isSet("slideLeft")
  493. slideRight = inputState.isSet("slideRight")
  494. jump = inputState.isSet("jump")
  495.  
  496. # Check for Auto-Run
  497. if 'localAvatar' in __builtins__:
  498. if base.localAvatar and base.localAvatar.getAutoRun():
  499. forward = 1
  500. reverse = 0
  501.  
  502. # Determine what the speeds are based on the buttons:
  503. self.speed=(forward and self.avatarControlForwardSpeed or
  504. reverse and -self.avatarControlReverseSpeed)
  505. # Slide speed is a scaled down version of forward speed
  506. # Note: you can multiply a factor in here if you want slide to
  507. # be slower than normal walk/run. Let's try full speed.
  508. #self.slideSpeed=(slideLeft and -self.avatarControlForwardSpeed*0.75 or
  509. # slideRight and self.avatarControlForwardSpeed*0.75)
  510. self.slideSpeed=(reverse and slideLeft and -self.avatarControlReverseSpeed*0.75 or
  511. reverse and slideRight and self.avatarControlReverseSpeed*0.75 or
  512. slideLeft and -self.avatarControlForwardSpeed*0.75 or
  513. slideRight and self.avatarControlForwardSpeed*0.75)
  514. self.rotationSpeed=not (slideLeft or slideRight) and (
  515. (turnLeft and self.avatarControlRotateSpeed) or
  516. (turnRight and -self.avatarControlRotateSpeed))
  517.  
  518. if self.speed and self.slideSpeed:
  519. self.speed *= GravityWalker.DiagonalFactor
  520. self.slideSpeed *= GravityWalker.DiagonalFactor
  521.  
  522. debugRunning = inputState.isSet("debugRunning")
  523. if(debugRunning):
  524. self.speed*=base.debugRunningMultiplier
  525. self.slideSpeed*=base.debugRunningMultiplier
  526. self.rotationSpeed*=1.25
  527.  
  528. if self.needToDeltaPos:
  529. self.setPriorParentVector()
  530. self.needToDeltaPos = 0
  531. if self.wantDebugIndicator:
  532. self.displayDebugInfo()
  533. if self.lifter.isOnGround():
  534. if self.isAirborne:
  535. self.isAirborne = 0
  536. assert self.debugPrint("isAirborne 0 due to isOnGround() true")
  537. impact = self.lifter.getImpactVelocity()
  538. if impact < -30.0:
  539. messenger.send("jumpHardLand")
  540. self.startJumpDelay(0.3)
  541. else:
  542. messenger.send("jumpLand")
  543. if impact < -5.0:
  544. self.startJumpDelay(0.2)
  545. # else, ignore the little potholes.
  546. assert self.isAirborne == 0
  547. self.priorParent = Vec3.zero()
  548. if jump and self.mayJump:
  549. # The jump button is down and we're close
  550. # enough to the ground to jump.
  551. self.lifter.addVelocity(self.avatarControlJumpForce)
  552. messenger.send("jumpStart")
  553. self.isAirborne = 1
  554. assert self.debugPrint("isAirborne 1 due to jump")
  555. else:
  556. if self.isAirborne == 0:
  557. assert self.debugPrint("isAirborne 1 due to isOnGround() false")
  558. self.isAirborne = 1
  559.  
  560. self.__oldPosDelta = self.avatarNodePath.getPosDelta(render)
  561. # How far did we move based on the amount of time elapsed?
  562. self.__oldDt = ClockObject.getGlobalClock().getDt()
  563. dt=self.__oldDt
  564.  
  565. # Check to see if we're moving at all:
  566. self.moving = self.speed or self.slideSpeed or self.rotationSpeed or (self.priorParent!=Vec3.zero())
  567. if self.moving:
  568. distance = dt * self.speed
  569. slideDistance = dt * self.slideSpeed
  570. rotation = dt * self.rotationSpeed
  571.  
  572. # Take a step in the direction of our previous heading.
  573. if distance or slideDistance or self.priorParent != Vec3.zero():
  574. # rotMat is the rotation matrix corresponding to
  575. # our previous heading.
  576. rotMat=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
  577. if self.isAirborne:
  578. forward = Vec3.forward()
  579. else:
  580. contact = self.lifter.getContactNormal()
  581. forward = contact.cross(Vec3.right())
  582. # Consider commenting out this normalize. If you do so
  583. # then going up and down slops is a touch slower and
  584. # steeper terrain can cut the movement in half. Without
  585. # the normalize the movement is slowed by the cosine of
  586. # the slope (i.e. it is multiplied by the sign as a
  587. # side effect of the cross product above).
  588. forward.normalize()
  589. self.vel=Vec3(forward * distance)
  590. if slideDistance:
  591. if self.isAirborne:
  592. right = Vec3.right()
  593. else:
  594. right = forward.cross(contact)
  595. # See note above for forward.normalize()
  596. right.normalize()
  597. self.vel=Vec3(self.vel + (right * slideDistance))
  598. self.vel=Vec3(rotMat.xform(self.vel))
  599. step=self.vel + (self.priorParent * dt)
  600. self.avatarNodePath.setFluidPos(Point3(
  601. self.avatarNodePath.getPos()+step))
  602. self.avatarNodePath.setH(self.avatarNodePath.getH()+rotation)
  603. else:
  604. self.vel.set(0.0, 0.0, 0.0)
  605. if self.moving or jump:
  606. messenger.send("avatarMoving")
  607. return Task.cont
  608.  
  609. def doDeltaPos(self):
  610. assert self.notify.debugStateCall(self)
  611. self.needToDeltaPos = 1
  612.  
  613. def setPriorParentVector(self):
  614. assert self.notify.debugStateCall(self)
  615. if __debug__:
  616. onScreenDebug.add("__oldDt", "% 10.4f"%self.__oldDt)
  617. onScreenDebug.add("self.__oldPosDelta",
  618. self.__oldPosDelta.pPrintValues())
  619. # avoid divide by zero crash - grw
  620. if self.__oldDt == 0:
  621. velocity = 0
  622. else:
  623. velocity = self.__oldPosDelta*(1.0/self.__oldDt)
  624. self.priorParent = Vec3(velocity)
  625. if __debug__:
  626. if self.wantDebugIndicator:
  627. onScreenDebug.add("priorParent", self.priorParent.pPrintValues())
  628.  
  629. def reset(self):
  630. assert self.notify.debugStateCall(self)
  631. self.lifter.setVelocity(0.0)
  632. self.priorParent=Vec3.zero()
  633.  
  634. def getVelocity(self):
  635. return self.vel
  636.  
  637. def enableAvatarControls(self):
  638. """
  639. Activate the arrow keys, etc.
  640. """
  641. assert self.notify.debugStateCall(self)
  642. assert self.collisionsActive
  643.  
  644. #*#if __debug__:
  645. #*# self.accept("control-f3", self.spawnTest) #*#
  646.  
  647. # remove any old
  648. if self.controlsTask:
  649. self.controlsTask.remove()
  650. # spawn the new task
  651. taskName = "AvatarControls-%s"%(id(self),)
  652. self.controlsTask = taskMgr.add(self.handleAvatarControls, taskName, 25)
  653.  
  654. self.isAirborne = 0
  655. self.mayJump = 1
  656.  
  657. if self.physVelocityIndicator:
  658. if self.indicatorTask:
  659. self.indicatorTask.remove()
  660. self.indicatorTask = taskMgr.add(
  661. self.avatarPhysicsIndicator,
  662. "AvatarControlsIndicator-%s"%(id(self),), 35)
  663.  
  664. def disableAvatarControls(self):
  665. """
  666. Ignore the arrow keys, etc.
  667. """
  668. assert self.notify.debugStateCall(self)
  669. if self.controlsTask:
  670. self.controlsTask.remove()
  671. self.controlsTask = None
  672. if self.indicatorTask:
  673. self.indicatorTask.remove()
  674. self.indicatorTask = None
  675. if self.jumpDelayTask:
  676. self.jumpDelayTask.remove()
  677. self.jumpDelayTask = None
  678.  
  679. if __debug__:
  680. self.ignore("control-f3") #*#
  681.  
  682.  
  683. def flushEventHandlers(self):
  684. if hasattr(self, 'cTrav'):
  685. self.pusher.flush()
  686. if self.wantFloorSphere:
  687. self.floorPusher.flush()
  688. self.event.flush()
  689. self.lifter.flush() # not currently defined or needed
  690.  
  691. if __debug__:
  692. def debugPrint(self, message):
  693. """for debugging"""
  694. return self.notify.debug(
  695. str(id(self))+' '+message)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement