PhysicsWalker.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. """
  2. PhysicsWalker.py is for avatars.
  3. A walker control such as this one provides:
  4. - creation of the collision nodes
  5. - handling the keyboard and mouse input for avatar movement
  6. - moving the avatar
  7. it does not:
  8. - play sounds
  9. - play animations
  10. although it does send messeges that allow a listener to play sounds or
  11. animations based on walker events.
  12. """
  13. from ShowBaseGlobal import *
  14. import DirectNotifyGlobal
  15. import DirectObject
  16. import PhysicsManager
  17. import math
  18. class PhysicsWalker(DirectObject.DirectObject):
  19. notify = DirectNotifyGlobal.directNotify.newCategory("PhysicsWalker")
  20. wantAvatarPhysicsIndicator = base.config.GetBool('want-avatar-physics-indicator', 1)
  21. # special methods
  22. def __init__(self, gravity = -32.1740, standableGround=0.707,
  23. hardLandingForce=16.0):
  24. assert(self.debugPrint("PhysicsWalker(gravity=%s, standableGround=%s)"%(
  25. gravity, standableGround)))
  26. DirectObject.DirectObject.__init__(self)
  27. self.__gravity=gravity
  28. self.__standableGround=standableGround
  29. self.__hardLandingForce=hardLandingForce
  30. self.physVelocityIndicator=None
  31. self.__old_contact=None
  32. self.__forwardButton=0
  33. self.__reverseButton=0
  34. self.__jumpButton=0
  35. self.__leftButton=0
  36. self.__rightButton=0
  37. self.__speed=0.0
  38. self.__rotationSpeed=0.0
  39. self.__slideSpeed=0.0
  40. self.__vel=Vec3(0.0)
  41. self.__slideButton = 0
  42. def setWalkSpeed(self, forward, jump, reverse, rotate):
  43. assert(self.debugPrint("setWalkSpeed()"))
  44. self.avatarControlForwardSpeed=forward
  45. self.avatarControlJumpForce=jump
  46. self.avatarControlReverseSpeed=reverse
  47. self.avatarControlRotateSpeed=rotate
  48. def getSpeeds(self):
  49. #assert(self.debugPrint("getSpeeds()"))
  50. return (self.__speed, self.__rotationSpeed)
  51. def initializeCollisions(self, collisionTraverser, avatarNodePath,
  52. wallBitmask, floorBitmask,
  53. avatarRadius = 1.4, floorOffset = 1.0):
  54. """
  55. Set up the avatar collisions
  56. """
  57. assert(self.debugPrint("initializeCollisions()"))
  58. assert not avatarNodePath.isEmpty()
  59. self.cTrav = collisionTraverser
  60. # Set up the collision sphere
  61. # This is a sphere on the ground to detect barrier collisions
  62. self.cSphere = CollisionSphere(0.0, 0.0, avatarRadius, avatarRadius)
  63. self.cSphereNode = CollisionNode('cSphereNode')
  64. self.cSphereNode.addSolid(self.cSphere)
  65. self.cSphereNodePath = avatarNodePath.attachNewNode(self.cSphereNode)
  66. self.cSphereBitMask = wallBitmask|floorBitmask
  67. self.cSphereNode.setFromCollideMask(self.cSphereBitMask)
  68. self.cSphereNode.setIntoCollideMask(BitMask32.allOff())
  69. # set up collision mechanism
  70. self.pusher = PhysicsCollisionHandler()
  71. self.pusher.setInPattern("enter%in")
  72. self.pusher.setOutPattern("exit%in")
  73. # Connect to Physics Manager:
  74. self.actorNode=ActorNode("physicsActor")
  75. self.actorNode.getPhysicsObject().setOriented(1)
  76. self.actorNode.getPhysical(0).setViscosity(0.1)
  77. physicsActor=NodePath(self.actorNode)
  78. avatarNodePath.reparentTo(physicsActor)
  79. avatarNodePath.assign(physicsActor)
  80. self.phys=PhysicsManager.PhysicsManager()
  81. fn=ForceNode("gravity")
  82. fnp=NodePath(fn)
  83. #fnp.reparentTo(physicsActor)
  84. fnp.reparentTo(render)
  85. gravity=LinearVectorForce(0.0, 0.0, self.__gravity)
  86. fn.addForce(gravity)
  87. self.phys.addLinearForce(gravity)
  88. fn=ForceNode("viscosity")
  89. fnp=NodePath(fn)
  90. #fnp.reparentTo(physicsActor)
  91. fnp.reparentTo(render)
  92. self.avatarViscosity=LinearFrictionForce(0.0, 1.0, 0)
  93. #self.avatarViscosity.setCoef(0.9)
  94. fn.addForce(self.avatarViscosity)
  95. self.phys.addLinearForce(self.avatarViscosity)
  96. self.phys.attachLinearIntegrator(LinearEulerIntegrator())
  97. self.phys.attachPhysicalnode(physicsActor.node())
  98. self.acForce=LinearVectorForce(0.0, 0.0, 0.0)
  99. fn=ForceNode("avatarControls")
  100. fnp=NodePath(fn)
  101. fnp.reparentTo(render)
  102. fn.addForce(self.acForce)
  103. self.phys.addLinearForce(self.acForce)
  104. #self.phys.removeLinearForce(self.acForce)
  105. #fnp.remove()
  106. # activate the collider with the traverser and pusher
  107. self.collisionsOn()
  108. self.pusher.addColliderNode(self.cSphereNode, avatarNodePath.node())
  109. self.avatarNodePath = avatarNodePath
  110. def setAvatarPhysicsIndicator(self, indicator):
  111. """
  112. indicator is a NodePath
  113. """
  114. assert(self.debugPrint("setAvatarPhysicsIndicator()"))
  115. self.cSphereNodePath.show()
  116. if indicator:
  117. # Indicator Node:
  118. change=render.attachNewNode("change")
  119. #change.setPos(Vec3(1.0, 1.0, 1.0))
  120. #change.setHpr(0.0, 0.0, 0.0)
  121. change.setScale(0.1)
  122. #change.setColor(Vec4(1.0, 1.0, 1.0, 1.0))
  123. indicator.reparentTo(change)
  124. indicatorNode=render.attachNewNode("physVelocityIndicator")
  125. #indicatorNode.setScale(0.1)
  126. #indicatorNode.setP(90.0)
  127. indicatorNode.setPos(self.avatarNodePath, 0.0, 0.0, 6.0)
  128. indicatorNode.setColor(0.0, 0.0, 1.0, 1.0)
  129. change.reparentTo(indicatorNode)
  130. self.physVelocityIndicator=indicatorNode
  131. # Contact Node:
  132. contactIndicatorNode=render.attachNewNode("physContactIndicator")
  133. contactIndicatorNode.setScale(0.25)
  134. contactIndicatorNode.setP(90.0)
  135. contactIndicatorNode.setPos(self.avatarNodePath, 0.0, 0.0, 5.0)
  136. contactIndicatorNode.setColor(1.0, 0.0, 0.0, 1.0)
  137. indicator.instanceTo(contactIndicatorNode)
  138. self.physContactIndicator=contactIndicatorNode
  139. else:
  140. print "failed load of physics indicator"
  141. def avatarPhysicsIndicator(self, task):
  142. #assert(self.debugPrint("avatarPhysicsIndicator()"))
  143. # Velosity:
  144. self.physVelocityIndicator.setPos(self.avatarNodePath, 0.0, 0.0, 6.0)
  145. physObject=self.actorNode.getPhysicsObject()
  146. a=physObject.getVelocity()
  147. self.physVelocityIndicator.setScale(math.sqrt(a.length()))
  148. a+=self.physVelocityIndicator.getPos()
  149. self.physVelocityIndicator.lookAt(Point3(a))
  150. # Contact:
  151. contact=self.actorNode.getContactVector()
  152. if contact==Vec3.zero():
  153. self.physContactIndicator.hide()
  154. else:
  155. self.physContactIndicator.show()
  156. self.physContactIndicator.setPos(self.avatarNodePath, 0.0, 0.0, 5.0)
  157. #contact=self.actorNode.getContactVector()
  158. point=Point3(contact+self.physContactIndicator.getPos())
  159. self.physContactIndicator.lookAt(point)
  160. return Task.cont
  161. def deleteCollisions(self):
  162. assert(self.debugPrint("deleteCollisions()"))
  163. del self.cTrav
  164. del self.cSphere
  165. del self.cSphereNode
  166. self.cSphereNodePath.removeNode()
  167. del self.cSphereNodePath
  168. del self.pusher
  169. def collisionsOff(self):
  170. assert(self.debugPrint("collisionsOff()"))
  171. self.cTrav.removeCollider(self.cSphereNode)
  172. # Now that we have disabled collisions, make one more pass
  173. # right now to ensure we aren't standing in a wall.
  174. self.oneTimeCollide()
  175. def collisionsOn(self):
  176. assert(self.debugPrint("collisionsOn()"))
  177. self.cTrav.addCollider(self.cSphereNode, self.pusher)
  178. def oneTimeCollide(self):
  179. """
  180. Makes one quick collision pass for the avatar, for instance as
  181. a one-time straighten-things-up operation after collisions
  182. have been disabled.
  183. """
  184. assert(self.debugPrint("oneTimeCollide()"))
  185. tempCTrav = CollisionTraverser()
  186. tempCTrav.addCollider(self.cSphereNode, self.pusher)
  187. tempCTrav.traverse(render)
  188. def handleAvatarControls(self, task):
  189. """
  190. Check on the arrow keys and update the avatar.
  191. """
  192. #assert(self.debugPrint("handleAvatarControls(task=%s)"%(task,)))
  193. physObject=self.actorNode.getPhysicsObject()
  194. rotAvatarToPhys=Mat3.rotateMatNormaxis(-self.avatarNodePath.getH(), Vec3.up())
  195. #rotPhysToAvatar=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
  196. contact=self.actorNode.getContactVector()
  197. # hack fix for falling through the floor:
  198. if contact==Vec3.zero() and self.avatarNodePath.getZ()<-50.0:
  199. # reset:
  200. # DCR: don't reset X and Y; allow player to move
  201. self.avatarNodePath.setZ(50.0)
  202. self.resetPhys()
  203. # Determine what the speeds are based on the buttons:
  204. self.__speed=(self.__forwardButton and self.avatarControlForwardSpeed or
  205. self.__reverseButton and -self.avatarControlReverseSpeed)
  206. self.__slideSpeed=self.__slideButton and (
  207. (self.__leftButton and -self.avatarControlForwardSpeed) or
  208. (self.__rightButton and self.avatarControlForwardSpeed))
  209. self.__rotationSpeed=not self.__slideButton and (
  210. (self.__leftButton and self.avatarControlRotateSpeed) or
  211. (self.__rightButton and -self.avatarControlRotateSpeed))
  212. # How far did we move based on the amount of time elapsed?
  213. dt=min(ClockObject.getGlobalClock().getDt(), 0.1)
  214. if contact!=Vec3.zero():
  215. contactLength = contact.length()
  216. contact.normalize()
  217. angle=contact.dot(Vec3.up())
  218. if angle>self.__standableGround:
  219. # ...avatar is on standable ground.
  220. if self.__old_contact==Vec3.zero():
  221. jumpTime = 0.0
  222. if contactLength>self.__hardLandingForce:
  223. # ...avatar was airborne.
  224. messenger.send("jumpHardLand")
  225. else:
  226. messenger.send("jumpLand")
  227. if self.__jumpButton:
  228. self.__jumpButton=0
  229. messenger.send("jumpStart")
  230. jump=Vec3(contact+Vec3.up())
  231. #jump=Vec3(rotAvatarToPhys.xform(jump))
  232. jump.normalize()
  233. jump*=self.avatarControlJumpForce
  234. physObject.addImpulse(Vec3(jump))
  235. if contact!=self.__old_contact:
  236. # We must copy the vector to preserve it:
  237. self.__old_contact=Vec3(contact)
  238. self.phys.doPhysics(dt)
  239. # Check to see if we're moving at all:
  240. if self.__speed or self.__slideSpeed or self.__rotationSpeed:
  241. distance = dt * self.__speed
  242. slideDistance = dt * self.__slideSpeed
  243. rotation = dt * self.__rotationSpeed
  244. #debugTempH=self.avatarNodePath.getH()
  245. assert self.avatarNodePath.getHpr().almostEqual(physObject.getOrientation().getHpr(), 0.0001)
  246. assert self.avatarNodePath.getPos().almostEqual(physObject.getPosition(), 0.0001)
  247. # update pos:
  248. # Take a step in the direction of our previous heading.
  249. self.__vel=Vec3(Vec3.forward() * distance +
  250. Vec3.right() * slideDistance)
  251. # rotMat is the rotation matrix corresponding to
  252. # our previous heading.
  253. rotMat=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
  254. step=rotMat.xform(self.__vel)
  255. physObject.setPosition(Point3(
  256. physObject.getPosition()+step))
  257. # update hpr:
  258. o=physObject.getOrientation()
  259. r=LOrientationf()
  260. r.setHpr(Vec3(rotation, 0.0, 0.0))
  261. physObject.setOrientation(o*r)
  262. # sync the change:
  263. self.actorNode.updateTransform()
  264. assert self.avatarNodePath.getHpr().almostEqual(physObject.getOrientation().getHpr(), 0.0001)
  265. assert self.avatarNodePath.getPos().almostEqual(physObject.getPosition(), 0.0001)
  266. #assert self.avatarNodePath.getH()==debugTempH-rotation
  267. messenger.send("avatarMoving")
  268. else:
  269. self.__vel.set(0.0, 0.0, 0.0)
  270. # Clear the contact vector so we can tell if we contact something next frame:
  271. self.actorNode.setContactVector(Vec3.zero())
  272. return Task.cont
  273. def handleAvatarControls_wip(self, task):
  274. """
  275. Check on the arrow keys and update the avatar.
  276. """
  277. #assert(self.debugPrint("handleAvatarControls(task=%s)"%(task,)))
  278. physObject=self.actorNode.getPhysicsObject()
  279. rotAvatarToPhys=Mat3.rotateMatNormaxis(-self.avatarNodePath.getH(), Vec3.up())
  280. #rotPhysToAvatar=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
  281. contact=self.actorNode.getContactVector()
  282. # hack fix for falling through the floor:
  283. if contact==Vec3.zero() and self.avatarNodePath.getZ()<-50.0:
  284. # reset:
  285. self.avatarNodePath.setPos(Vec3(0.0, 0.0, 20.0))
  286. # Determine what the speeds are based on the buttons:
  287. self.__speed=(self.__forwardButton and self.avatarControlForwardSpeed or
  288. self.__reverseButton and -self.avatarControlReverseSpeed)
  289. self.__slideSpeed=self.__slideButton and (
  290. (self.__leftButton and -self.avatarControlForwardSpeed) or
  291. (self.__rightButton and self.avatarControlForwardSpeed))
  292. self.__rotationSpeed=not self.__slideButton and (
  293. (self.__leftButton and self.avatarControlRotateSpeed) or
  294. (self.__rightButton and -self.avatarControlRotateSpeed))
  295. # How far did we move based on the amount of time elapsed?
  296. dt=min(ClockObject.getGlobalClock().getDt(), 0.1)
  297. doPhysics=1
  298. if not contact.almostEqual(Vec3.zero()):
  299. contactLength = contact.length()
  300. contact.normalize()
  301. angle=contact.dot(Vec3.up())
  302. if angle>self.__standableGround:
  303. # ...avatar is on standable ground.
  304. #print "standableGround"
  305. if self.__old_contact==Vec3.zero():
  306. jumpTime = 0.0
  307. if contactLength>self.__hardLandingForce:
  308. # ...avatar was airborne.
  309. messenger.send("jumpHardLand")
  310. else:
  311. messenger.send("jumpLand")
  312. if self.__jumpButton:
  313. self.__jumpButton=0
  314. messenger.send("jumpStart")
  315. jump=Vec3(contact+Vec3.up())
  316. #jump=Vec3(rotAvatarToPhys.xform(jump))
  317. jump.normalize()
  318. jump*=self.avatarControlJumpForce
  319. physObject.addImpulse(Vec3(jump))
  320. else:
  321. physObject.setVelocity(Vec3(0.0))
  322. self.__vel.set(0.0, 0.0, 0.0)
  323. doPhysics=0
  324. if contact!=self.__old_contact:
  325. # We must copy the vector to preserve it:
  326. self.__old_contact=Vec3(contact)
  327. #print "doPhysics", doPhysics
  328. #print "contact", contact
  329. if doPhysics:
  330. self.phys.doPhysics(dt)
  331. # Check to see if we're moving at all:
  332. if self.__speed or self.__slideSpeed or self.__rotationSpeed:
  333. distance = dt * self.__speed
  334. slideDistance = dt * self.__slideSpeed
  335. rotation = dt * self.__rotationSpeed
  336. #debugTempH=self.avatarNodePath.getH()
  337. assert self.avatarNodePath.getHpr().almostEqual(physObject.getOrientation().getHpr(), 0.0001)
  338. assert self.avatarNodePath.getPos().almostEqual(physObject.getPosition(), 0.0001)
  339. # update pos:
  340. # Take a step in the direction of our previous heading.
  341. self.__vel=Vec3(Vec3.forward() * distance +
  342. Vec3.right() * slideDistance)
  343. # rotMat is the rotation matrix corresponding to
  344. # our previous heading.
  345. rotMat=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
  346. step=rotMat.xform(self.__vel)
  347. physObject.setPosition(Point3(
  348. physObject.getPosition()+step))
  349. # update hpr:
  350. o=physObject.getOrientation()
  351. r=LOrientationf()
  352. r.setHpr(Vec3(rotation, 0.0, 0.0))
  353. physObject.setOrientation(o*r)
  354. # sync the change:
  355. self.actorNode.updateTransform()
  356. assert self.avatarNodePath.getHpr().almostEqual(physObject.getOrientation().getHpr(), 0.0001)
  357. assert self.avatarNodePath.getPos().almostEqual(physObject.getPosition(), 0.0001)
  358. #assert self.avatarNodePath.getH()==debugTempH-rotation
  359. messenger.send("avatarMoving")
  360. else:
  361. self.__vel.set(0.0, 0.0, 0.0)
  362. # Clear the contact vector so we can tell if we contact something next frame:
  363. self.actorNode.setContactVector(Vec3.zero())
  364. return Task.cont
  365. def resetPhys(self):
  366. assert(self.debugPrint("resetPhys()"))
  367. self.actorNode.getPhysicsObject().resetPosition(self.avatarNodePath.getPos())
  368. self.actorNode.setContactVector(Vec3.zero())
  369. def enableAvatarControls(self):
  370. """
  371. Activate the arrow keys, etc.
  372. """
  373. assert(self.debugPrint("enableAvatarControls()"))
  374. self.accept("control", self.moveJump, [1])
  375. self.accept("control-up", self.moveJump, [0])
  376. self.accept("control-arrow_left", self.moveJumpLeft, [1])
  377. self.accept("control-arrow_left-up", self.moveJumpLeft, [0])
  378. self.accept("control-arrow_right", self.moveJumpRight, [1])
  379. self.accept("control-arrow_right-up", self.moveJumpRight, [0])
  380. self.accept("control-arrow_up", self.moveJumpForward, [1])
  381. self.accept("control-arrow_up-up", self.moveJumpForward, [0])
  382. self.accept("control-arrow_down", self.moveJumpInReverse, [1])
  383. self.accept("control-arrow_down-up", self.moveJumpInReverse, [0])
  384. self.accept("arrow_left", self.moveTurnLeft, [1])
  385. self.accept("arrow_left-up", self.moveTurnLeft, [0])
  386. self.accept("arrow_right", self.moveTurnRight, [1])
  387. self.accept("arrow_right-up", self.moveTurnRight, [0])
  388. self.accept("arrow_up", self.moveForward, [1])
  389. self.accept("arrow_up-up", self.moveForward, [0])
  390. self.accept("arrow_down", self.moveInReverse, [1])
  391. self.accept("arrow_down-up", self.moveInReverse, [0])
  392. if 1:
  393. self.accept("f3", self.resetPhys) # for debugging only.
  394. taskName = "AvatarControls%s"%(id(self),)
  395. # remove any old
  396. taskMgr.remove(taskName)
  397. # spawn the new task
  398. taskMgr.add(self.handleAvatarControls, taskName, 10)
  399. if self.physVelocityIndicator:
  400. taskMgr.add(self.avatarPhysicsIndicator, "AvatarControlsIndicator%s"%(id(self),), 35)
  401. def disableAvatarControls(self):
  402. """
  403. Ignore the arrow keys, etc.
  404. """
  405. assert(self.debugPrint("disableAvatarControls()"))
  406. taskName = "AvatarControls%s"%(id(self),)
  407. taskMgr.remove(taskName)
  408. taskName = "AvatarControlsIndicator%s"%(id(self),)
  409. taskMgr.remove(taskName)
  410. self.ignore("control")
  411. self.ignore("control-up")
  412. self.ignore("control-arrow_left")
  413. self.ignore("control-arrow_left-up")
  414. self.ignore("control-arrow_right")
  415. self.ignore("control-arrow_right-up")
  416. self.ignore("control-arrow_up")
  417. self.ignore("control-arrow_up-up")
  418. self.ignore("control-arrow_down")
  419. self.ignore("control-arrow_down-up")
  420. self.ignore("arrow_left")
  421. self.ignore("arrow_left-up")
  422. self.ignore("arrow_right")
  423. self.ignore("arrow_right-up")
  424. self.ignore("arrow_up")
  425. self.ignore("arrow_up-up")
  426. self.ignore("arrow_down")
  427. self.ignore("arrow_down-up")
  428. self.ignore("f3")
  429. # reset state
  430. self.moveTurnLeft(0)
  431. self.moveTurnRight(0)
  432. self.moveForward(0)
  433. self.moveInReverse(0)
  434. self.moveJumpLeft(0)
  435. self.moveJumpRight(0)
  436. self.moveJumpForward(0)
  437. self.moveJumpInReverse(0)
  438. self.moveJump(0)
  439. self.moveSlide(0)
  440. def moveTurnLeft(self, isButtonDown):
  441. assert(self.debugPrint("moveTurnLeft(isButtonDown=%s)"%(isButtonDown,)))
  442. self.__leftButton=isButtonDown
  443. def moveTurnRight(self, isButtonDown):
  444. assert(self.debugPrint("moveTurnRight(isButtonDown=%s)"%(isButtonDown,)))
  445. self.__rightButton=isButtonDown
  446. def moveForward(self, isButtonDown):
  447. assert(self.debugPrint("moveForward(isButtonDown=%s)"%(isButtonDown,)))
  448. self.__forwardButton=isButtonDown
  449. def moveInReverse(self, isButtonDown):
  450. assert(self.debugPrint("moveInReverse(isButtonDown=%s)"%(isButtonDown,)))
  451. self.__reverseButton=isButtonDown
  452. def moveJumpLeft(self, isButtonDown):
  453. assert(self.debugPrint("moveJumpLeft(isButtonDown=%s)"%(isButtonDown,)))
  454. self.__jumpButton=isButtonDown
  455. self.__leftButton=isButtonDown
  456. def moveJumpRight(self, isButtonDown):
  457. assert(self.debugPrint("moveJumpRight(isButtonDown=%s)"%(isButtonDown,)))
  458. self.__jumpButton=isButtonDown
  459. self.__rightButton=isButtonDown
  460. def moveJumpForward(self, isButtonDown):
  461. assert(self.debugPrint("moveJumpForward(isButtonDown=%s)"%(isButtonDown,)))
  462. self.__jumpButton=isButtonDown
  463. self.__forwardButton=isButtonDown
  464. def moveJumpInReverse(self, isButtonDown):
  465. assert(self.debugPrint("moveJumpInReverse(isButtonDown=%s)"%(isButtonDown,)))
  466. self.__jumpButton=isButtonDown
  467. self.__reverseButton=isButtonDown
  468. def moveJump(self, isButtonDown):
  469. assert(self.debugPrint("moveJump()"))
  470. self.__jumpButton=isButtonDown
  471. def moveSlide(self, isButtonDown):
  472. assert(self.debugPrint("moveSlide(isButtonDown=%s)"%(isButtonDown,)))
  473. self.__slideButton=isButtonDown
  474. if __debug__:
  475. def debugPrint(self, message):
  476. """for debugging"""
  477. return self.notify.debug(
  478. str(id(self))+' '+message)