ShipCannonController.re.ts 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. import RapierBody from '@RE/RogueEngine/rogue-rapier/Components/RapierBody.re';
  2. import GetForwardVector from 'Assets/Library/GetForwardVector';
  3. import * as RE from 'rogue-engine';
  4. import * as THREE from 'three'
  5. export default class ShipCannonController extends RE.Component {
  6. @RE.props.prefab() cannonball: RE.Prefab
  7. objectVectorCalculator: GetForwardVector
  8. @RE.props.list.audio(true) cannonShotSounds: THREE.Audio[] = []
  9. @RE.props.checkbox() debug: boolean = false
  10. @RE.props.object3d() positionObject
  11. delayedActionQueue:Function[] = []
  12. lines = new THREE.LineSegments(
  13. new THREE.BufferGeometry(),
  14. new THREE.LineBasicMaterial({ color: new THREE.Color("#00FF00") })
  15. );
  16. shotIterator = 0
  17. @RE.props.checkbox() fireLeft = false
  18. @RE.props.checkbox() fireRight = false
  19. @RE.props.checkbox() fireForward = false
  20. awake() {
  21. if(!this.positionObject) {
  22. this.positionObject = this.object3d.parent
  23. }
  24. this.objectVectorCalculator = new GetForwardVector(this.positionObject)
  25. if(this.debug) {
  26. this.lines.frustumCulled = false;
  27. RE.App.currentScene.remove(this.lines);
  28. this.lines.userData.isEditorObject = true;
  29. RE.App.currentScene.add(this.lines);
  30. }
  31. }
  32. start() {
  33. }
  34. update() {
  35. this.delayedActionQueue.forEach((action) => {
  36. action()
  37. })
  38. this.delayedActionQueue = []
  39. const powderStrength = 50
  40. const forwardVector = this.objectVectorCalculator.getForward().clone().normalize()
  41. const rightVector = this.objectVectorCalculator.getRight().clone().normalize()
  42. if(this.debug) {
  43. this.lines.visible = false
  44. }
  45. const worldPosition = this.positionObject.position ?? new THREE.Vector3(0,0,0)
  46. const forwardLaunchPosition = forwardVector.clone().multiplyScalar(3.8)
  47. const shiftedForward = forwardVector.clone().multiplyScalar(1.38)
  48. const shiftedOutward = rightVector.clone().multiplyScalar(0.1)
  49. const rightLaunchPosition = rightVector.clone().add(shiftedOutward).add(shiftedForward)
  50. const leftLaunchPosition = rightVector.clone().add(shiftedOutward).negate().add(shiftedForward)
  51. const verticalOffset = new THREE.Vector3(0,1.8,0)
  52. if(this.fireForward) {
  53. let forwardCannonball = this.cannonball.instantiate()
  54. forwardCannonball.position.set(forwardLaunchPosition.x,forwardLaunchPosition.y,forwardLaunchPosition.z).add(verticalOffset).add(worldPosition)
  55. let forwardCannonballBody = RE.getObjectComponents(forwardCannonball).filter(component => component instanceof RapierBody)[0] as RapierBody
  56. if(forwardCannonballBody){
  57. this.delayedActionQueue.push(() => {
  58. this.playShotSound(forwardCannonball)
  59. forwardCannonballBody.body.applyImpulse(forwardVector.clone().multiplyScalar(powderStrength).multiplyScalar(RE.Runtime.deltaTime), true)
  60. this.fireForward = false
  61. })
  62. } else {
  63. RE.Debug.logWarning("forward cannon body not loaded yet")
  64. }
  65. }
  66. if(this.fireRight) {
  67. let rightCannonball = this.cannonball.instantiate()
  68. rightCannonball.position.set(rightLaunchPosition.x,rightLaunchPosition.y,rightLaunchPosition.z).add(verticalOffset).add(worldPosition)
  69. let rightCannonballBody = RE.getObjectComponents(rightCannonball).filter(component => component instanceof RapierBody)[0] as RapierBody
  70. if(rightCannonballBody){
  71. this.delayedActionQueue.push(() => {
  72. this.playShotSound(rightCannonball)
  73. rightCannonballBody.body.applyImpulse(rightVector.clone().multiplyScalar(powderStrength).multiplyScalar(RE.Runtime.deltaTime), true)
  74. this.fireRight = false
  75. })
  76. } else {
  77. RE.Debug.logWarning("right cannon body not loaded yet")
  78. }
  79. }
  80. if(this.fireLeft) {
  81. let leftCannonball = this.cannonball.instantiate()
  82. leftCannonball.position.set(leftLaunchPosition.x,leftLaunchPosition.y,leftLaunchPosition.z).add(verticalOffset).add(worldPosition)
  83. let leftCannonballBody = RE.getObjectComponents(leftCannonball).filter(component => component instanceof RapierBody)[0] as RapierBody
  84. if(leftCannonballBody){
  85. this.delayedActionQueue.push(() => {
  86. this.playShotSound(leftCannonball)
  87. leftCannonballBody.body.applyImpulse(rightVector.clone().negate().multiplyScalar(powderStrength).multiplyScalar(RE.Runtime.deltaTime), true)
  88. this.fireLeft = false
  89. })
  90. } else {
  91. RE.Debug.logWarning("left cannon body not loaded yet")
  92. }
  93. }
  94. if(this.debug)
  95. {
  96. this.lines.visible = true
  97. let vertexes = new Float32Array([
  98. ...worldPosition.clone().add(verticalOffset).toArray(),
  99. ...forwardLaunchPosition.clone().add(worldPosition).add(verticalOffset).toArray(),
  100. ...worldPosition.clone().add(verticalOffset).add(shiftedForward).toArray(),
  101. ...rightLaunchPosition.clone().add(verticalOffset).add(worldPosition).toArray(),
  102. ...worldPosition.clone().add(verticalOffset).add(shiftedForward).toArray(),
  103. ...leftLaunchPosition.clone().add(verticalOffset).add(worldPosition).toArray()
  104. ])
  105. this.lines.geometry.setAttribute(
  106. "position",
  107. new THREE.BufferAttribute(vertexes, 3),
  108. )
  109. }
  110. }
  111. playShotSound(target) {
  112. if(this.cannonShotSounds.length > 0) {
  113. let randomSound = this.cannonShotSounds[this.shotIterator++]
  114. target.add(randomSound)
  115. randomSound.setVolume(10)
  116. randomSound.play()
  117. }
  118. if(this.shotIterator >= this.cannonShotSounds.length) {
  119. this.shotIterator = 0
  120. }
  121. }
  122. }
  123. RE.registerComponent(ShipCannonController);