at the moment it doesnt feel right.
DEMO video:
code:
import {
StandardMaterial, Color3, SphereParticleEmitter, ParticleSystem,
Texture, Vector3, Quaternion,
Animation, CreateCapsuleVertexData, ActionManager, ExecuteCodeAction, CircleEase, Matrix
} from "@babylonjs/core";
import Game from "../Game";
import GameObject from "./GameObject";
export default class HomingMissile extends GameObject {
explosionParticleSystem: ParticleSystem;
private _collisionTriggered: boolean;
private _timer: number;
constructor(pos: Vector3, game: Game, explosionTime: number) {
super("homingMissile", game);
// Create a mesh
const vertexData = CreateCapsuleVertexData({ radius: 0.1, capSubdivisions: 1, height: 1.2, tessellation: 4, topCapSubdivisions: 8 });
vertexData.applyToMesh(this, true);
// Set plane material
const mat = new StandardMaterial("planeMaterial", this.getScene());
mat.diffuseColor = Color3.Red();
this.material = mat;
Game.shadowGenerator.addShadowCaster(this);
// Create an explosion particle system
this.explosionParticleSystem = this.createExplosionParticleSystem();
this.position = pos;
this.rotationQuaternion = Quaternion.RotationYawPitchRoll(0, Math.PI / 2, 0);
this.hommingMissile(game.player!);
// Set a timer for the plane to explode
this._collisionTriggered = false;
// Set a timer for the plane to explode
this._timer = setTimeout(() => {
this.explode();
}, explosionTime);
// Detect collision with the player
this.actionManager = new ActionManager(this.getScene());
this.actionManager.registerAction(
new ExecuteCodeAction(
{
trigger: ActionManager.OnIntersectionEnterTrigger,
parameter: game.player,
},
() => {
console.log('its a hit!');
this._collisionTriggered = true;
window.clearTimeout(this._timer);
this.explode();
}
)
);
}
explode() {
if (!this._collisionTriggered) {
clearTimeout(this._timer);
}
// Trigger the explosion particle system
this.isVisible = false;
this.explosionParticleSystem.start();
// Dispose the plane after the explosion
setTimeout(() => {
this.explosionParticleSystem.dispose();
this.dispose();
}, this.explosionParticleSystem.maxLifeTime * 1000);
}
private createExplosionParticleSystem(): ParticleSystem {
...
}
hommingMissile(player: GameObject) {
const playerPosition = player.position.clone();
// Move the pivot point to the base of the cylinder
const pivotMatrix = Matrix.Translation(0, -1, 0);
this.setPivotMatrix(pivotMatrix);
// Create a quaternion representing a 90-degree pitch rotation
const pitch = Math.PI / 2; // 90 degrees in radians
const yaw = Math.PI / 2; // 90 degrees in radians
const roll = 0;
const rotationQuaternion = Quaternion.RotationYawPitchRoll(yaw, pitch, roll);
// Assign the quaternion to the cylinder's rotationQuaternion property
this.rotationQuaternion = rotationQuaternion;
// Define animation for position
const positionAnimation = new Animation("positionAnimation", "position", 100, Animation.ANIMATIONTYPE_VECTOR3, Animation.ANIMATIONLOOPMODE_CONSTANT);
const [a, b, c] = this.getMissilePath(playerPosition)
this.lookAt(b);
// Define position keyframes
const positionKeys = [
{ frame: 0, value: a },
{ frame: 25, value: b.add(new Vector3(1, -3, 0)) },
{ frame: 50, value: b },
{ frame: 75, value: b.add(new Vector3(-1, -3, 0)) },
{ frame: 100, value: c },
];
// Assign keyframes to position animation
positionAnimation.setKeys(positionKeys);
// Define easing function for curved path
const easingFunction = new CircleEase();
positionAnimation.setEasingFunction(easingFunction);
// Define animation for rotation
const rotationAnimation = new Animation("rotationAnimation", "rotationQuaternion", 100, Animation.ANIMATIONTYPE_QUATERNION, Animation.ANIMATIONLOOPMODE_CONSTANT);
// Define rotation keyframes
const rotationKeys = [
{ frame: 0, value: rotationQuaternion },
{ frame: 25, value: Quaternion.RotationYawPitchRoll(yaw, pitch + Math.PI / 2, roll) },
{ frame: 50, value: Quaternion.RotationYawPitchRoll(yaw, pitch + Math.PI, roll) },
{ frame: 75, value: Quaternion.RotationYawPitchRoll(yaw, pitch + 1.5 * Math.PI, roll) },
{ frame: 100, value: Quaternion.RotationYawPitchRoll(yaw, pitch + 2 * Math.PI, roll) },
];
// Assign keyframes to rotation animation
rotationAnimation.setKeys(rotationKeys);
this.getScene().beginDirectAnimation(this, [positionAnimation, rotationAnimation], 0, 100, false);
}
getMissilePath(destination: Vector3) {
const initialPosition = this.position.clone(); // starting position
// Calculate median position between initial and final positions
const medianPosition = Vector3.Lerp(initialPosition, destination, 0.5);
return [initialPosition, medianPosition, destination]
}
}