CamerSegmentation.ts 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import { Vec2, Node, v2, PolygonCollider2D, Rect, CircleCollider2D, AssetManager, Prefab, instantiate, Vec3, Camera, director, tween } from "cc";
  2. import { resLoader } from "../../core_tgx/base/ResLoader";
  3. import { AliensGlobalInstance } from "./AliensGlobalInstance";
  4. export const moveDuration: number = 2.5;
  5. /** 相机镜头切分 */
  6. export class CameraSegmentation {
  7. static cameraFollowDistance: number = 5;
  8. static cameraHeight: number = 2;
  9. static async segmentation(_origin:Node,_target:Node) {
  10. // 重置子弹位置和朝向
  11. const bullet = await this.loadBullet();
  12. const levelNode = AliensGlobalInstance.instance.levels.children[0];
  13. levelNode.addChild(bullet);
  14. bullet.setWorldPosition(_origin.worldPosition.clone());
  15. bullet.lookAt(_target.worldPosition, Vec3.UP);
  16. // 计算子弹路径中点
  17. const midPoint = new Vec3();
  18. Vec3.lerp(midPoint, _origin.worldPosition, _target.worldPosition, 0.5);
  19. // 计算子弹飞行方向向量
  20. const bulletDirection = new Vec3();
  21. Vec3.subtract(bulletDirection, _target.worldPosition, _origin.worldPosition);
  22. Vec3.normalize(bulletDirection, bulletDirection);
  23. // 1. 起始位置 - 子弹正后方
  24. const startCameraPos = new Vec3();
  25. Vec3.scaleAndAdd(startCameraPos, _origin.worldPosition, bulletDirection, -this.cameraFollowDistance * 2);
  26. startCameraPos.y += this.cameraHeight; // 添加高度偏移
  27. // 2. 中间位置 - 子弹侧后方45度
  28. const midCameraPos = new Vec3();
  29. const sideOffset = new Vec3(-bulletDirection.z, 0, bulletDirection.x); // 计算侧向偏移
  30. Vec3.scaleAndAdd(midCameraPos, midPoint, bulletDirection, -this.cameraFollowDistance);
  31. Vec3.scaleAndAdd(midCameraPos, midCameraPos, sideOffset, this.cameraFollowDistance);
  32. midCameraPos.y += this.cameraHeight * 1.5;
  33. // 3. 结束位置 - 目标侧方45度
  34. const endCameraPos = new Vec3();
  35. const targetSideOffset = new Vec3(-bulletDirection.z, 0, bulletDirection.x); // 计算目标侧向偏移
  36. Vec3.scaleAndAdd(endCameraPos, _target.worldPosition, bulletDirection, -this.cameraFollowDistance * 0.5); // 稍微后退
  37. Vec3.scaleAndAdd(endCameraPos, endCameraPos, targetSideOffset, this.cameraFollowDistance); // 侧向偏移
  38. endCameraPos.y += this.cameraHeight * 1; // 适当高度
  39. // 设置相机初始位置和朝向
  40. let camera = await this.getSceneCamera();
  41. camera.node.setRotationFromEuler(0, 0, 0); // 重置旋转
  42. camera.node.setWorldPosition(startCameraPos);
  43. camera.node.lookAt(_target.worldPosition); // 初始看向目标
  44. // 设置更慢的全局时间
  45. director.getScheduler().setTimeScale(0.1);
  46. // 三阶段镜头运动
  47. tween(bullet)
  48. .to(moveDuration,
  49. { worldPosition: _target.worldPosition.clone() },
  50. {
  51. onUpdate: (target, ratio) => {
  52. let currentCameraPos = new Vec3();
  53. let lookAtPos = new Vec3();
  54. if (ratio! < 0.6) {
  55. Vec3.lerp(currentCameraPos, startCameraPos, midCameraPos, ratio! / 0.6);
  56. Vec3.lerp(lookAtPos, _origin.worldPosition, midPoint, ratio! / 0.6);
  57. }
  58. else if (ratio! < 0.9) {
  59. Vec3.lerp(currentCameraPos, midCameraPos, endCameraPos, (ratio! - 0.6) / 0.3);
  60. lookAtPos = bullet.worldPosition; // 中间阶段跟随子弹
  61. } else {
  62. currentCameraPos = endCameraPos.clone();
  63. lookAtPos = _target.worldPosition; // 最后阶段看向目标
  64. }
  65. camera.node.setWorldPosition(currentCameraPos);
  66. camera.node.lookAt(lookAtPos);
  67. },
  68. onComplete: () => {
  69. director.getScheduler().setTimeScale(1.0);
  70. }
  71. }
  72. )
  73. .start();
  74. }
  75. //获取主相机
  76. static async getSceneCamera() :Promise<Camera>{
  77. return new Promise<Camera>((resolve, reject) => {
  78. const levelNode = AliensGlobalInstance.instance.levels.children[0];
  79. if(!levelNode){return;}
  80. const camera = levelNode.getComponentInChildren(Camera)!;
  81. resolve(camera);
  82. });
  83. }
  84. //异步加载子弹
  85. static async loadBullet(): Promise<Node> {
  86. return new Promise<Node>((resolve, reject) => {
  87. resLoader.loadAsync(resLoader.gameBundleName, `Prefabs/bullet`, Prefab).then((prefab: Prefab) => {
  88. const bullet = instantiate(prefab);
  89. resolve(bullet);
  90. })
  91. });
  92. }
  93. }