123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128 |
- import { _decorator, Camera, Component, director, Node, tween, Vec3 } from 'cc';
- import { EventDispatcher } from 'db://assets/core_tgx/easy_ui_framework/EventDispatcher';
- import { GameEvent } from '../Enum/GameEvent';
- const { ccclass, property } = _decorator;
- //相机切分动画时长
- export const CAMERA_SPLIT_DURATION = 3;
- @ccclass('BulletComponent')
- export class BulletComponent extends Component {
- target: Node = null!;
- @property(Camera)
- camera: Camera = null!; // 相机节点
- protected onLoad(): void {
- EventDispatcher.instance.on(GameEvent.EVENT_CAMERA_SPLIT, this.camerSlip, this);
- }
- private camerSlip(target: Node) {
- this.hideGun();
- this.target = target;
- this.lookAtTarget();
- this.flyToTarget();
- }
- private hideGun() {
- const gun = this.camera.node.getChildByName('gun');
- gun.active = false;
- }
- //朝向目标
- lookAtTarget() {
- if (!this.target) return;
- // 计算子弹到目标的方向
- const direction = new Vec3();
- Vec3.subtract(direction, this.target.worldPosition, this.node.worldPosition);
- direction.normalize();
- // 计算朝向角度(注意Y轴旋转180度)
- const angle = Math.atan2(direction.x, direction.z) * 180 / Math.PI;
- // 设置子弹旋转
- this.node.setRotationFromEuler(0, angle, 0);
- }
- //飞向目标
- flyToTarget() {
- if (!this.target || !this.camera) return;
- // 1. 计算相机起始位置(子弹后方)
- const bulletDir = new Vec3();
- Vec3.subtract(bulletDir, this.target.worldPosition, this.node.worldPosition);
- bulletDir.normalize();
- const startCameraPos = new Vec3();
- Vec3.scaleAndAdd(startCameraPos, this.node.worldPosition, bulletDir, -5);
- this.camera.node.worldPosition = startCameraPos;
- this.camera.node.lookAt(this.node.worldPosition);
- // 2. 子弹飞行+相机跟随
- const targetPos = this.target.worldPosition.clone();
- let elapsedTime = 0;
- tween(this.node)
- .to(CAMERA_SPLIT_DURATION, { worldPosition: new Vec3(targetPos.x, targetPos.y, targetPos.z) }, {
- onUpdate: (target, ratio) => {
- elapsedTime = ratio! * 3;
- // 第一秒:相机跟随子弹后方
- if (elapsedTime <= 1) {
- const followPos = new Vec3();
- Vec3.scaleAndAdd(followPos, this.node.worldPosition, bulletDir, -5);
- followPos.y += 1;
- this.camera.node.worldPosition = followPos;
- this.camera.node.lookAt(this.node.worldPosition);
- }
- // 第二秒:平滑移动到侧后方45度
- else if (elapsedTime <= 2) {
- // 计算侧后方45度方向向量
- const sideBackDir = new Vec3();
- Vec3.rotateY(sideBackDir, bulletDir, Vec3.UP, Math.PI / 2);
- // 起始位置(后方)和目标位置(侧后方)
- const startPos = new Vec3();
- Vec3.scaleAndAdd(startPos, this.node.worldPosition, bulletDir, -5);
- startPos.y += 3;
- const targetPos = new Vec3();
- Vec3.scaleAndAdd(targetPos, this.node.worldPosition, sideBackDir, -5);
- targetPos.y += 3;
- // 使用lerp平滑过渡
- const currentPos = new Vec3();
- const progress = (elapsedTime - 1) / 1; // 0-1之间的进度
- Vec3.lerp(currentPos, startPos, targetPos, progress);
- this.camera.node.worldPosition = currentPos;
- this.camera.node.lookAt(this.node.worldPosition);
- }
- // 第三秒:相机对准目标节点
- else {
- this.node.setScale(1, 1, 1);
- // 计算目标点前方5单位的位置(距离从10改为5)
- const targetViewPos = new Vec3(
- this.target.worldPosition.x,
- this.target.worldPosition.y + 2, // 高度偏移2单位
- this.target.worldPosition.z + 3 // 前方5单位
- );
- this.camera.node.worldPosition = targetViewPos;
- this.camera.node.lookAt(this.target.worldPosition);
- }
- }
- })
- .start();
- }
- protected onDestroy(): void {
- EventDispatcher.instance.off(GameEvent.EVENT_CAMERA_SPLIT, this.camerSlip, this);
- }
- }
|