import RapierBody from '@RE/RogueEngine/rogue-rapier/Components/RapierBody.re'; import GetForwardVector from 'Assets/Library/GetForwardVector'; import * as RE from 'rogue-engine'; import * as THREE from 'three' export default class ShipCannonController extends RE.Component { @RE.props.prefab() cannonball: RE.Prefab objectVectorCalculator: GetForwardVector @RE.props.list.audio(true) cannonShotSounds: THREE.Audio[] = [] @RE.props.checkbox() debug: boolean = false @RE.props.object3d() positionObject delayedActionQueue:Function[] = [] lines = new THREE.LineSegments( new THREE.BufferGeometry(), new THREE.LineBasicMaterial({ color: new THREE.Color("#00FF00") }) ); shotIterator = 0 @RE.props.checkbox() fireLeft = false @RE.props.checkbox() fireRight = false @RE.props.checkbox() fireForward = false awake() { if(!this.positionObject) { this.positionObject = this.object3d.parent } this.objectVectorCalculator = new GetForwardVector(this.positionObject) if(this.debug) { this.lines.frustumCulled = false; RE.App.currentScene.remove(this.lines); this.lines.userData.isEditorObject = true; RE.App.currentScene.add(this.lines); } } start() { } update() { this.delayedActionQueue.forEach((action) => { action() }) this.delayedActionQueue = [] const powderStrength = 50 const forwardVector = this.objectVectorCalculator.getForward().clone().normalize() const rightVector = this.objectVectorCalculator.getRight().clone().normalize() if(this.debug) { this.lines.visible = false } const worldPosition = this.positionObject.position ?? new THREE.Vector3(0,0,0) const forwardLaunchPosition = forwardVector.clone().multiplyScalar(3.8) const shiftedForward = forwardVector.clone().multiplyScalar(1.38) const shiftedOutward = rightVector.clone().multiplyScalar(0.1) const rightLaunchPosition = rightVector.clone().add(shiftedOutward).add(shiftedForward) const leftLaunchPosition = rightVector.clone().add(shiftedOutward).negate().add(shiftedForward) const verticalOffset = new THREE.Vector3(0,1.8,0) if(this.fireForward) { let forwardCannonball = this.cannonball.instantiate() forwardCannonball.position.set(forwardLaunchPosition.x,forwardLaunchPosition.y,forwardLaunchPosition.z).add(verticalOffset).add(worldPosition) let forwardCannonballBody = RE.getObjectComponents(forwardCannonball).filter(component => component instanceof RapierBody)[0] as RapierBody if(forwardCannonballBody){ this.delayedActionQueue.push(() => { this.playShotSound(forwardCannonball) forwardCannonballBody.body.applyImpulse(forwardVector.clone().multiplyScalar(powderStrength).multiplyScalar(RE.Runtime.deltaTime), true) this.fireForward = false }) } else { RE.Debug.logWarning("forward cannon body not loaded yet") } } if(this.fireRight) { let rightCannonball = this.cannonball.instantiate() rightCannonball.position.set(rightLaunchPosition.x,rightLaunchPosition.y,rightLaunchPosition.z).add(verticalOffset).add(worldPosition) let rightCannonballBody = RE.getObjectComponents(rightCannonball).filter(component => component instanceof RapierBody)[0] as RapierBody if(rightCannonballBody){ this.delayedActionQueue.push(() => { this.playShotSound(rightCannonball) rightCannonballBody.body.applyImpulse(rightVector.clone().multiplyScalar(powderStrength).multiplyScalar(RE.Runtime.deltaTime), true) this.fireRight = false }) } else { RE.Debug.logWarning("right cannon body not loaded yet") } } if(this.fireLeft) { let leftCannonball = this.cannonball.instantiate() leftCannonball.position.set(leftLaunchPosition.x,leftLaunchPosition.y,leftLaunchPosition.z).add(verticalOffset).add(worldPosition) let leftCannonballBody = RE.getObjectComponents(leftCannonball).filter(component => component instanceof RapierBody)[0] as RapierBody if(leftCannonballBody){ this.delayedActionQueue.push(() => { this.playShotSound(leftCannonball) leftCannonballBody.body.applyImpulse(rightVector.clone().negate().multiplyScalar(powderStrength).multiplyScalar(RE.Runtime.deltaTime), true) this.fireLeft = false }) } else { RE.Debug.logWarning("left cannon body not loaded yet") } } if(this.debug) { this.lines.visible = true let vertexes = new Float32Array([ ...worldPosition.clone().add(verticalOffset).toArray(), ...forwardLaunchPosition.clone().add(worldPosition).add(verticalOffset).toArray(), ...worldPosition.clone().add(verticalOffset).add(shiftedForward).toArray(), ...rightLaunchPosition.clone().add(verticalOffset).add(worldPosition).toArray(), ...worldPosition.clone().add(verticalOffset).add(shiftedForward).toArray(), ...leftLaunchPosition.clone().add(verticalOffset).add(worldPosition).toArray() ]) this.lines.geometry.setAttribute( "position", new THREE.BufferAttribute(vertexes, 3), ) } } playShotSound(target) { if(this.cannonShotSounds.length > 0) { let randomSound = this.cannonShotSounds[this.shotIterator++] target.add(randomSound) randomSound.setVolume(10) randomSound.play() } if(this.shotIterator >= this.cannonShotSounds.length) { this.shotIterator = 0 } } } RE.registerComponent(ShipCannonController);