DevWalker.py 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187
  1. """
  2. DevWalker.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 direct.showbase.InputStateGlobal import inputState
  14. from direct.directnotify import DirectNotifyGlobal
  15. from direct.showbase import DirectObject
  16. from direct.task.Task import Task
  17. from pandac.PandaModules import *
  18. class DevWalker(DirectObject.DirectObject):
  19. notify = DirectNotifyGlobal.directNotify.newCategory("DevWalker")
  20. wantDebugIndicator = base.config.GetBool('want-avatar-physics-indicator', 0)
  21. runMultiplier = base.config.GetFloat('dev-run-multiplier', 4.0)
  22. # Ghost mode overrides this:
  23. slideName = "slide-is-disabled"
  24. # special methods
  25. def __init__(self):
  26. DirectObject.DirectObject.__init__(self)
  27. self.speed=0.0
  28. self.rotationSpeed=0.0
  29. self.slideSpeed=0.0
  30. self.vel=Vec3(0.0, 0.0, 0.0)
  31. self.task = None
  32. def setWalkSpeed(self, forward, jump, reverse, rotate):
  33. assert self.debugPrint("setWalkSpeed()")
  34. self.avatarControlForwardSpeed=forward
  35. #self.avatarControlJumpForce=jump
  36. self.avatarControlReverseSpeed=reverse
  37. self.avatarControlRotateSpeed=rotate
  38. def getSpeeds(self):
  39. #assert self.debugPrint("getSpeeds()")
  40. return (self.speed, self.rotationSpeed, self.slideSpeed)
  41. def setAvatar(self, avatar):
  42. self.avatar = avatar
  43. if avatar is not None:
  44. pass # setup the avatar
  45. def setWallBitMask(self, bitMask):
  46. pass
  47. def setFloorBitMask(self, bitMask):
  48. pass
  49. def initializeCollisions(self, collisionTraverser, avatarNodePath,
  50. wallCollideMask, floorCollideMask,
  51. avatarRadius = 1.4, floorOffset = 1.0, reach = 1.0):
  52. assert not avatarNodePath.isEmpty()
  53. self.cTrav = collisionTraverser
  54. self.avatarNodePath = avatarNodePath
  55. def setAirborneHeightFunc(self, getAirborneHeight):
  56. pass
  57. def deleteCollisions(self):
  58. pass
  59. def setTag(self, key, value):
  60. pass
  61. def setCollisionsActive(self, active = 1):
  62. pass
  63. def placeOnFloor(self):
  64. pass
  65. def oneTimeCollide(self):
  66. pass
  67. def addBlastForce(self, vector):
  68. pass
  69. def displayDebugInfo(self):
  70. """
  71. For debug use.
  72. """
  73. onScreenDebug.add("w controls", "DevWalker")
  74. def handleAvatarControls(self, task):
  75. """
  76. Check on the arrow keys and update the avatar.
  77. """
  78. # get the button states:
  79. forward = inputState.isSet("forward")
  80. reverse = inputState.isSet("reverse")
  81. turnLeft = inputState.isSet("turnLeft")
  82. turnRight = inputState.isSet("turnRight")
  83. slideLeft = inputState.isSet("slideLeft")
  84. slideRight = inputState.isSet("slideRight")
  85. levitateUp = inputState.isSet("levitateUp")
  86. levitateDown = inputState.isSet("levitateDown")
  87. run = inputState.isSet("run") and self.runMultiplier or 1.0
  88. # Check for Auto-Run
  89. if base.localAvatar.getAutoRun():
  90. forward = 1
  91. reverse = 0
  92. # Determine what the speeds are based on the buttons:
  93. self.speed=(
  94. (forward and self.avatarControlForwardSpeed or
  95. reverse and -self.avatarControlReverseSpeed))
  96. self.liftSpeed=(
  97. (levitateUp and self.avatarControlForwardSpeed or
  98. levitateDown and -self.avatarControlReverseSpeed))
  99. self.slideSpeed=(
  100. (slideLeft and -self.avatarControlForwardSpeed) or
  101. (slideRight and self.avatarControlForwardSpeed))
  102. self.rotationSpeed=(
  103. (turnLeft and self.avatarControlRotateSpeed) or
  104. (turnRight and -self.avatarControlRotateSpeed))
  105. if self.wantDebugIndicator:
  106. self.displayDebugInfo()
  107. # Check to see if we're moving at all:
  108. if self.speed or self.liftSpeed or self.slideSpeed or self.rotationSpeed:
  109. # How far did we move based on the amount of time elapsed?
  110. dt=ClockObject.getGlobalClock().getDt()
  111. distance = dt * self.speed * run
  112. lift = dt * self.liftSpeed * run
  113. slideDistance = dt * self.slideSpeed * run
  114. rotation = dt * self.rotationSpeed
  115. # Take a step in the direction of our previous heading.
  116. self.vel=Vec3(Vec3.forward() * distance +
  117. Vec3.up() * lift +
  118. Vec3.right() * slideDistance)
  119. if self.vel != Vec3.zero():
  120. # rotMat is the rotation matrix corresponding to
  121. # our previous heading.
  122. rotMat=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
  123. step=rotMat.xform(self.vel)
  124. self.avatarNodePath.setFluidPos(Point3(self.avatarNodePath.getPos()+step))
  125. self.avatarNodePath.setH(self.avatarNodePath.getH()+rotation)
  126. messenger.send("avatarMoving")
  127. else:
  128. self.vel.set(0.0, 0.0, 0.0)
  129. return Task.cont
  130. def enableAvatarControls(self):
  131. """
  132. Activate the arrow keys, etc.
  133. """
  134. assert self.debugPrint("enableAvatarControls")
  135. if self.task:
  136. # remove any old
  137. self.task.remove(self.task)
  138. # spawn the new task
  139. self.task = taskMgr.add(
  140. self.handleAvatarControls, "AvatarControls-dev-%s"%(id(self),))
  141. def disableAvatarControls(self):
  142. """
  143. Ignore the arrow keys, etc.
  144. """
  145. assert self.debugPrint("disableAvatarControls")
  146. if self.task:
  147. self.task.remove()
  148. self.task = None
  149. if __debug__:
  150. def debugPrint(self, message):
  151. """for debugging"""
  152. return self.notify.debug(
  153. str(id(self))+' '+message)