BattleWalker.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. from direct.showbase.InputStateGlobal import inputState
  2. from direct.task.Task import Task
  3. from pandac.PandaModules import *
  4. from . import GravityWalker
  5. BattleStrafe = 0
  6. def ToggleStrafe():
  7. global BattleStrafe
  8. BattleStrafe = not BattleStrafe
  9. def SetStrafe(status):
  10. global BattleStrafe
  11. BattleStrafe = status
  12. class BattleWalker(GravityWalker.GravityWalker):
  13. def __init__(self):
  14. GravityWalker.GravityWalker.__init__(self)
  15. self.slideSpeed = 0
  16. self.advanceSpeed = 0
  17. def getSpeeds(self):
  18. return (self.speed, self.rotationSpeed, self.slideSpeed, self.advanceSpeed)
  19. def handleAvatarControls(self, task):
  20. """
  21. Check on the arrow keys and update the avatar.
  22. """
  23. # get the button states:
  24. run = inputState.isSet("run")
  25. forward = inputState.isSet("forward")
  26. reverse = inputState.isSet("reverse")
  27. turnLeft = inputState.isSet("turnLeft")
  28. turnRight = inputState.isSet("turnRight")
  29. slideLeft = inputState.isSet("slideLeft")
  30. slideRight = inputState.isSet("slideRight")
  31. jump = inputState.isSet("jump")
  32. # Check for Auto-Run
  33. if base.localAvatar.getAutoRun():
  34. forward = 1
  35. reverse = 0
  36. # Determine what the speeds are based on the buttons:
  37. self.speed=(forward and self.avatarControlForwardSpeed or
  38. reverse and -self.avatarControlReverseSpeed)
  39. # Slide speed is a scaled down version of forward speed
  40. self.slideSpeed=(slideLeft and -self.avatarControlForwardSpeed or
  41. slideRight and self.avatarControlForwardSpeed) * 0.5
  42. self.rotationSpeed=not (slideLeft or slideRight) and (
  43. (turnLeft and self.avatarControlRotateSpeed) or
  44. (turnRight and -self.avatarControlRotateSpeed))
  45. debugRunning = inputState.isSet("debugRunning")
  46. if(debugRunning):
  47. self.speed*=base.debugRunningMultiplier
  48. self.slideSpeed*=base.debugRunningMultiplier
  49. self.rotationSpeed*=1.25
  50. if self.needToDeltaPos:
  51. self.setPriorParentVector()
  52. self.needToDeltaPos = 0
  53. if self.wantDebugIndicator:
  54. self.displayDebugInfo()
  55. if self.lifter.isOnGround():
  56. if self.isAirborne:
  57. self.isAirborne = 0
  58. assert self.debugPrint("isAirborne 0 due to isOnGround() true")
  59. impact = self.lifter.getImpactVelocity()
  60. if impact < -30.0:
  61. messenger.send("jumpHardLand")
  62. self.startJumpDelay(0.3)
  63. else:
  64. messenger.send("jumpLand")
  65. if impact < -5.0:
  66. self.startJumpDelay(0.2)
  67. # else, ignore the little potholes.
  68. assert self.isAirborne == 0
  69. self.priorParent = Vec3.zero()
  70. if jump and self.mayJump:
  71. # The jump button is down and we're close
  72. # enough to the ground to jump.
  73. self.lifter.addVelocity(self.avatarControlJumpForce)
  74. messenger.send("jumpStart")
  75. self.isAirborne = 1
  76. assert self.debugPrint("isAirborne 1 due to jump")
  77. else:
  78. if self.isAirborne == 0:
  79. assert self.debugPrint("isAirborne 1 due to isOnGround() false")
  80. self.isAirborne = 1
  81. self.__oldPosDelta = self.avatarNodePath.getPosDelta(render)
  82. # How far did we move based on the amount of time elapsed?
  83. self.__oldDt = ClockObject.getGlobalClock().getDt()
  84. dt=self.__oldDt
  85. # Check to see if we're moving at all:
  86. self.moving = self.speed or self.slideSpeed or self.rotationSpeed or (self.priorParent!=Vec3.zero())
  87. if self.moving:
  88. distance = dt * self.speed
  89. slideDistance = dt * self.slideSpeed
  90. rotation = dt * self.rotationSpeed
  91. # Take a step in the direction of our previous heading.
  92. if distance or slideDistance or self.priorParent != Vec3.zero():
  93. # rotMat is the rotation matrix corresponding to
  94. # our previous heading.
  95. rotMat=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
  96. if self.isAirborne:
  97. forward = Vec3.forward()
  98. else:
  99. contact = self.lifter.getContactNormal()
  100. forward = contact.cross(Vec3.right())
  101. # Consider commenting out this normalize. If you do so
  102. # then going up and down slops is a touch slower and
  103. # steeper terrain can cut the movement in half. Without
  104. # the normalize the movement is slowed by the cosine of
  105. # the slope (i.e. it is multiplied by the sign as a
  106. # side effect of the cross product above).
  107. forward.normalize()
  108. self.vel=Vec3(forward * distance)
  109. if slideDistance:
  110. if self.isAirborne:
  111. right = Vec3.right()
  112. else:
  113. right = forward.cross(contact)
  114. # See note above for forward.normalize()
  115. right.normalize()
  116. self.vel=Vec3(self.vel + (right * slideDistance))
  117. self.vel=Vec3(rotMat.xform(self.vel))
  118. step=self.vel + (self.priorParent * dt)
  119. self.avatarNodePath.setFluidPos(Point3(
  120. self.avatarNodePath.getPos()+step))
  121. self.avatarNodePath.setH(self.avatarNodePath.getH()+rotation)
  122. else:
  123. self.vel.set(0.0, 0.0, 0.0)
  124. if self.moving or jump:
  125. messenger.send("avatarMoving")
  126. return Task.cont
  127. if 0:
  128. def handleAvatarControls(self, task):
  129. # If targetNp is not available, revert back to GravityWalker.handleAvatarControls.
  130. # This situation occurs when the target dies, but we aren't switched out of
  131. # battle walker control mode.
  132. targetNp = self.avatarNodePath.currentTarget
  133. if not BattleStrafe or targetNp == None or targetNp.isEmpty():
  134. return GravityWalker.GravityWalker.handleAvatarControls(self, task)
  135. # get the button states:
  136. run = inputState.isSet("run")
  137. forward = inputState.isSet("forward")
  138. reverse = inputState.isSet("reverse")
  139. turnLeft = inputState.isSet("turnLeft")
  140. turnRight = inputState.isSet("turnRight")
  141. slide = inputState.isSet("slide")
  142. jump = inputState.isSet("jump")
  143. # Determine what the speeds are based on the buttons:
  144. self.advanceSpeed=(forward and self.avatarControlForwardSpeed or
  145. reverse and -self.avatarControlReverseSpeed)
  146. if run and self.advanceSpeed>0.0:
  147. self.advanceSpeed*=2.0 #*#
  148. # Should fSlide be renamed slideButton?
  149. self.slideSpeed=.15*(turnLeft and -self.avatarControlForwardSpeed or
  150. turnRight and self.avatarControlForwardSpeed)
  151. print('slideSpeed: %s' % self.slideSpeed)
  152. self.rotationSpeed=0
  153. self.speed=0
  154. debugRunning = inputState.isSet("debugRunning")
  155. if debugRunning:
  156. self.advanceSpeed*=4.0
  157. self.slideSpeed*=4.0
  158. self.rotationSpeed*=1.25
  159. if self.needToDeltaPos:
  160. self.setPriorParentVector()
  161. self.needToDeltaPos = 0
  162. if self.wantDebugIndicator:
  163. self.displayDebugInfo()
  164. if self.lifter.isOnGround():
  165. if self.isAirborne:
  166. self.isAirborne = 0
  167. assert self.debugPrint("isAirborne 0 due to isOnGround() true")
  168. impact = self.lifter.getImpactVelocity()
  169. if impact < -30.0:
  170. messenger.send("jumpHardLand")
  171. self.startJumpDelay(0.3)
  172. else:
  173. messenger.send("jumpLand")
  174. if impact < -5.0:
  175. self.startJumpDelay(0.2)
  176. # else, ignore the little potholes.
  177. assert self.isAirborne == 0
  178. self.priorParent = Vec3.zero()
  179. if jump and self.mayJump:
  180. # The jump button is down and we're close
  181. # enough to the ground to jump.
  182. self.lifter.addVelocity(self.avatarControlJumpForce)
  183. messenger.send("jumpStart")
  184. self.isAirborne = 1
  185. assert self.debugPrint("isAirborne 1 due to jump")
  186. else:
  187. if self.isAirborne == 0:
  188. assert self.debugPrint("isAirborne 1 due to isOnGround() false")
  189. self.isAirborne = 1
  190. self.__oldPosDelta = self.avatarNodePath.getPosDelta(render)
  191. # How far did we move based on the amount of time elapsed?
  192. self.__oldDt = ClockObject.getGlobalClock().getDt()
  193. dt=self.__oldDt
  194. # Before we do anything with position or orientation, make the avatar
  195. # face it's target. Only allow rMax degrees rotation per frame, so
  196. # we don't get an unnatural spinning effect
  197. curH = self.avatarNodePath.getH()
  198. self.avatarNodePath.headsUp(targetNp)
  199. newH = self.avatarNodePath.getH()
  200. delH = reduceAngle(newH-curH)
  201. rMax = 10
  202. if delH < -rMax:
  203. self.avatarNodePath.setH(curH-rMax)
  204. self.rotationSpeed=-self.avatarControlRotateSpeed
  205. elif delH > rMax:
  206. self.avatarNodePath.setH(curH+rMax)
  207. self.rotationSpeed=self.avatarControlRotateSpeed
  208. # Check to see if we're moving at all:
  209. self.moving = self.speed or self.slideSpeed or self.rotationSpeed or (self.priorParent!=Vec3.zero())
  210. if self.moving:
  211. distance = dt * self.speed
  212. slideDistance = dt * self.slideSpeed
  213. print('slideDistance: %s' % slideDistance)
  214. rotation = dt * self.rotationSpeed
  215. # Take a step in the direction of our previous heading.
  216. self.vel=Vec3(Vec3.forward() * distance +
  217. Vec3.right() * slideDistance)
  218. if self.vel != Vec3.zero() or self.priorParent != Vec3.zero():
  219. if 1:
  220. # rotMat is the rotation matrix corresponding to
  221. # our previous heading.
  222. rotMat=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
  223. step=(self.priorParent * dt) + rotMat.xform(self.vel)
  224. self.avatarNodePath.setFluidPos(Point3(
  225. self.avatarNodePath.getPos()+step))
  226. self.avatarNodePath.setH(self.avatarNodePath.getH()+rotation)
  227. else:
  228. self.vel.set(0.0, 0.0, 0.0)
  229. """
  230. # Check to see if we're moving at all:
  231. self.moving = self.advanceSpeed or self.slideSpeed or self.rotationSpeed or (self.priorParent!=Vec3.zero())
  232. if self.moving:
  233. distance = dt * self.advanceSpeed
  234. slideDistance = dt * self.slideSpeed
  235. rotation = dt * self.rotationSpeed
  236. # Prevent avatar from getting too close to target
  237. d = self.avatarNodePath.getPos(targetNp)
  238. # TODO: make min distance adjust for current weapon
  239. if (d[0]*d[0]+d[1]*d[1] < 6.0 and distance > 0):
  240. # move the avatar sideways instead of forward
  241. slideDistance += .2
  242. distance = 0
  243. # Take a step in the direction of our previous heading.
  244. self.vel=Vec3(Vec3.forward() * distance +
  245. Vec3.right() * slideDistance)
  246. if self.vel != Vec3.zero() or self.priorParent != Vec3.zero():
  247. # rotMat is the rotation matrix corresponding to
  248. # our previous heading.
  249. rotMat=Mat3.rotateMatNormaxis(self.avatarNodePath.getH(), Vec3.up())
  250. step=rotMat.xform(self.vel) + (self.priorParent * dt)
  251. self.avatarNodePath.setFluidPos(Point3(
  252. self.avatarNodePath.getPos()+step))
  253. self.avatarNodePath.setH(self.avatarNodePath.getH()+rotation)
  254. else:
  255. self.vel.set(0.0, 0.0, 0.0)
  256. """
  257. if self.moving or jump:
  258. messenger.send("avatarMoving")
  259. return Task.cont