RapierMovementController.re.ts 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. import GetForwardVector from './GetForwardVector';
  2. import * as RE from 'rogue-engine';
  3. import * as THREE from 'three'
  4. import RAPIER from '@dimforge/rapier3d-compat';
  5. import RapierBody from '@RE/RogueEngine/rogue-rapier/Components/RapierBody.re';
  6. import RapierConfig from '@RE/RogueEngine/rogue-rapier/Components/RapierConfig.re';
  7. import RogueRapier from '@RE/RogueEngine/rogue-rapier/Lib/RogueRapier';
  8. export default class RapierMovementController extends RE.Component {
  9. initialized = false
  10. characterController: RAPIER.KinematicCharacterController
  11. rapierConfig: RapierConfig
  12. @RE.props.num() speed: number = 1
  13. @RE.props.num() rotationSpeed: number = 1
  14. // @RE.props.num() jumpStrength: number = 10
  15. @RE.props.checkbox() useCameraForward: boolean = true
  16. @RE.props.checkbox() useObjectForward: boolean = false
  17. cameraVectorCalculator: GetForwardVector
  18. objectVectorCalculator: GetForwardVector
  19. bodyComponent: RapierBody
  20. velocity: THREE.Vector3 = new THREE.Vector3(0,0,0)
  21. gravityAcceleration: THREE.Vector3 = new THREE.Vector3(0,0,0)
  22. @RE.props.vector3() drag: THREE.Vector3 = new THREE.Vector3(0.002, 0.002, 0.002)
  23. @RE.props.num() snapToGroundDistance: number = 1
  24. @RE.props.num() autostepMaxHeight: number = 0.7
  25. @RE.props.num() autostepMinWidth: number = 0.3
  26. @RE.props.checkbox() autostepIncludeDynamicBodies: boolean = true
  27. @RE.props.num() gravityScale: number = 2
  28. @RE.props.num() jumpHeight: number = 5
  29. isFalling: boolean = false
  30. hasJumped: boolean = false
  31. @RE.props.num() minimumHeight: number = -10
  32. @RE.props.vector3() resetPosition: THREE.Vector3 = new THREE.Vector3(0,0,0)
  33. // private jumpVector: RAPIER.Vector3 = new RAPIER.Vector3(0,1,0)
  34. private scaledVelocity: THREE.Vector3 = new THREE.Vector3(0,0,0)
  35. private rapierScaledVelocity: RAPIER.Vector3 = new RAPIER.Vector3(0,0,0)
  36. elapsed = 0
  37. @RE.props.checkbox() thrust = false
  38. @RE.props.checkbox() brake = false
  39. @RE.props.checkbox() strafeLeft = false
  40. @RE.props.checkbox() strafeRight = false
  41. @RE.props.checkbox() rotateLeft = false
  42. @RE.props.checkbox() rotateRight = false
  43. @RE.props.checkbox() jump = false
  44. config: RapierConfig
  45. awake() {
  46. this.bodyComponent = RE.getComponent(RapierBody, this.object3d) as RapierBody
  47. }
  48. start() {
  49. this.cameraVectorCalculator = new GetForwardVector(RE.Runtime.camera)
  50. this.objectVectorCalculator = new GetForwardVector(this.object3d)
  51. this.config = RE.getComponent(RapierConfig) as RapierConfig
  52. }
  53. beforeUpdate(): void {
  54. if (!RogueRapier.initialized) return;
  55. !this.initialized && this.init();
  56. }
  57. init() {
  58. this.characterController = RogueRapier.world.createCharacterController(0.1)
  59. this.characterController.enableAutostep(this.autostepMaxHeight, this.autostepMinWidth, this.autostepIncludeDynamicBodies)
  60. this.characterController.enableSnapToGround(this.snapToGroundDistance)
  61. this.characterController.setCharacterMass(100)
  62. this.characterController.setApplyImpulsesToDynamicBodies(true)
  63. // this.characterController.setSlideEnabled(this.slideEnabled)
  64. }
  65. update() {
  66. if(!this.bodyComponent.body) {
  67. return
  68. }
  69. this.elapsed += RE.Runtime.deltaTime
  70. // if(direction.x != 0) {
  71. // this.moveForward(direction.x * this.speed)
  72. // }
  73. // if(direction.y != 0) {
  74. // this.moveRight(direction.y * this.speed)
  75. // }
  76. // if(direction.z != 0) {
  77. // const floorCheckComponent = RE.getComponent(FloorCheckComponent, this.object3d)
  78. // if(floorCheckComponent) {
  79. // if(floorCheckComponent.isOnFloor) {
  80. // this.jumpVector.y = this.jumpStrength
  81. // this.bodyComponent.body.applyImpulse(this.jumpVector, true)
  82. // }
  83. // }
  84. // }
  85. if(this.thrust) {
  86. this.moveForward(1 * this.speed)
  87. }
  88. if(this.brake) {
  89. this.moveForward(-1 * this.speed)
  90. }
  91. if(this.rotateLeft) {
  92. this.rotate(1 * this.rotationSpeed)
  93. }
  94. if(this.rotateRight) {
  95. this.rotate(-1 * this.rotationSpeed)
  96. }
  97. if(this.strafeLeft) {
  98. this.moveRight(-1 * this.speed)
  99. }
  100. if(this.strafeRight) {
  101. this.moveRight(1 * this.speed)
  102. }
  103. const fixedStep = RE.Runtime.deltaTime
  104. if(this.jump && !this.isFalling && !this.hasJumped) {
  105. this.velocity.y += (this.jumpHeight * 1000) * fixedStep
  106. this.hasJumped = true
  107. }
  108. // console.log(this.config)
  109. this.gravityAcceleration.set(this.config.gravity.x, this.config.gravity.y, this.config.gravity.z)
  110. this.velocity.add(this.gravityAcceleration.multiplyScalar(this.gravityScale * fixedStep))
  111. const nextPosition = this.convertRapierToThreeVec3(this.bodyComponent.body.translation())
  112. const nextVelocity = this.convertRapierToThreeVec3(this.bodyComponent.body.linvel())
  113. nextVelocity.x *= (1 - this.drag.x)
  114. nextVelocity.y *= (1 - this.drag.y)
  115. nextVelocity.z *= (1 - this.drag.z)
  116. this.velocity.x *= (1 - this.drag.x)
  117. this.velocity.y *= (1 - this.drag.x)
  118. this.velocity.z *= (1 - this.drag.x)
  119. nextVelocity.x += this.velocity.x
  120. nextVelocity.y += this.velocity.y
  121. nextVelocity.z += this.velocity.z
  122. this.characterController.computeColliderMovement(
  123. this.bodyComponent.body.collider(0),
  124. nextVelocity.clone().multiplyScalar(fixedStep),
  125. )
  126. const characterMovement = this.characterController.computedMovement()
  127. if(this.characterController.computedGrounded()) {
  128. this.isFalling = false
  129. } else {
  130. this.isFalling = true
  131. }
  132. nextPosition.x += characterMovement.x
  133. nextPosition.y += characterMovement.y
  134. // nextPosition.y = 0
  135. nextPosition.z += characterMovement.z
  136. if(nextPosition.y < this.minimumHeight) {
  137. nextPosition.x = this.resetPosition.x
  138. nextPosition.y = this.resetPosition.y
  139. nextPosition.z = this.resetPosition.z
  140. }
  141. this.bodyComponent.body.setNextKinematicTranslation(nextPosition)
  142. this.thrust = false
  143. this.brake = false
  144. this.strafeLeft = false
  145. this.strafeRight = false
  146. this.rotateLeft = false
  147. this.rotateRight = false
  148. }
  149. moveForward(distance) {
  150. let forwardVector;
  151. if(this.useCameraForward) {
  152. forwardVector = this.cameraVectorCalculator.getForward()
  153. let euler = new THREE.Euler(0,0,0, 'XZY')
  154. euler.setFromQuaternion(RE.Runtime.camera.quaternion.normalize())
  155. euler.x = 0
  156. euler.z = 0
  157. let newRotation = new THREE.Quaternion()
  158. newRotation.setFromEuler(euler)
  159. const nextRotation = this.convertRapierToThreeQuat(this.bodyComponent.body.rotation())
  160. nextRotation.slerp(newRotation, this.rotationSpeed * RE.Runtime.deltaTime)
  161. this.bodyComponent.body.setNextKinematicRotation(nextRotation)
  162. } else {
  163. forwardVector = this.objectVectorCalculator.getForward()
  164. }
  165. this.scaledVelocity.set(0,0,0)
  166. this.scaledVelocity.addScaledVector(forwardVector, distance)
  167. this.velocity.x += this.scaledVelocity.x
  168. this.velocity.y += this.scaledVelocity.y
  169. this.velocity.z += this.scaledVelocity.z
  170. }
  171. moveRight(distance) {
  172. let rightVector;
  173. if(this.useCameraForward) {
  174. rightVector = this.cameraVectorCalculator.getRight()
  175. let euler = new THREE.Euler(0,0,0, 'XZY')
  176. euler.setFromQuaternion(RE.Runtime.camera.quaternion.normalize())
  177. euler.x = 0
  178. euler.z = 0
  179. let newRotation = new THREE.Quaternion()
  180. newRotation.setFromEuler(euler)
  181. const nextRotation = this.convertRapierToThreeQuat(this.bodyComponent.body.rotation())
  182. nextRotation.slerp(newRotation, this.rotationSpeed * RE.Runtime.deltaTime)
  183. this.bodyComponent.body.setNextKinematicRotation(nextRotation)
  184. } else {
  185. rightVector = this.objectVectorCalculator.getRight()
  186. }
  187. this.scaledVelocity.set(0,0,0)
  188. this.scaledVelocity.addScaledVector(rightVector, distance)
  189. // this.rapierScaledVelocity.x = this.scaledVelocity.x
  190. // this.rapierScaledVelocity.y = this.scaledVelocity.y
  191. // this.rapierScaledVelocity.z = this.scaledVelocity.z
  192. // this.bodyComponent.body.applyImpulse(this.rapierScaledVelocity, true)
  193. this.velocity.x += this.scaledVelocity.x
  194. this.velocity.y += this.scaledVelocity.y
  195. this.velocity.z += this.scaledVelocity.z
  196. }
  197. rotate(amount) {
  198. const nextRotation = this.convertRapierToThreeQuat(this.bodyComponent.body.rotation())
  199. const newRotation = this.quaternionFromAxisAngle(this.object3d.up, amount)
  200. nextRotation.multiply(newRotation)
  201. this.bodyComponent.body.setNextKinematicRotation(nextRotation)
  202. }
  203. convertRapierToThreeQuat(oldQuaternion: RAPIER.Quaternion) {
  204. return new THREE.Quaternion(oldQuaternion.x, oldQuaternion.y, oldQuaternion.z, oldQuaternion.w)
  205. }
  206. convertRapierToThreeVec3(oldVector: RAPIER.Vector3) {
  207. return new THREE.Vector3(oldVector.x, oldVector.y, oldVector.z)
  208. }
  209. quaternionFromAxisAngle(axis, rotationRadians) {
  210. let factor = Math.sin(rotationRadians / 2)
  211. let x = axis.x * factor
  212. let y = axis.y * factor
  213. let z = axis.z * factor
  214. let w = Math.cos(rotationRadians / 2)
  215. let normalized = new THREE.Quaternion(x, y, z, w).normalize()
  216. return new THREE.Quaternion(normalized.x, normalized.y, normalized.z, normalized.w)
  217. }
  218. }
  219. RE.registerComponent(RapierMovementController);