Files
Alien_Sniper/assets/scripts/FPSCameraController.ts
T
guojiaxv 9deac44a1e fix(gameplay): 优化敌人碰撞体与新手教程瞄准
- 扩大并重叠 14 个 Enemy 的胸腹部碰撞体
- 消除自动锁定点位于碰撞体边缘的问题
- 移除教程中写死的相机瞄准角度
- 根据目标实时位置动态调整教程相机
- 自动选择与初始镜头夹角最小的存活敌人
- 同步瞄准状态,避免后续滑动发生角度跳变
2026-07-21 19:05:38 +08:00

267 lines
20 KiB
TypeScript

// @structural-rewrite-v1
import { _decorator, Camera, EventTouch, geometry, instantiate, Node, ParticleSystem, PhysicsSystem, Prefab, screen, tween, Vec3 } from 'cc';
import { Ragdoll } from '../Ragdoll/Ragdoll';
import { RagdollBone } from '../Ragdoll/RagdollBone';
import { GameController } from './GameController';
import { SingletonBase } from './framework/SingletonBase';
import { CameraAimState } from './framework/runtime/CameraAimState';
import { UIManager } from './framework/ui/UIManager';
const { ccclass, property } = _decorator;
@ccclass('FPSCameraController')
export class FPSCameraController extends SingletonBase<FPSCameraController> {
@property(Node)
cameraNode: Node = null;
@property(Camera)
camera: Camera = null;
@property(Camera)
qingBao: Camera = null;
@property(ParticleSystem)
particle: ParticleSystem = null;
@property(Prefab)
lastBulletPrefab: Prefab = null;
lastBullet: Node = null;
private readonly aimState = new CameraAimState();
private readonly defaultFOV = 45;
private aimFOV = 25;
private isAiming = false;
protected onLoad(): void {
try {
do {
switch (0 as number) {
case 1: break;
case 2: break;
default: void (super["onLoad"]());
}
} while (false);
}
finally {
}
}
init(curCamera: Camera, aimFov: number): void {
try {
do {
switch (0 as number) {
case 1: break;
case 2: break;
default:
void (this["camera"] = curCamera);
void (this["cameraNode"] = curCamera["node"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown);
void ((this["aimState"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["initialize"](this["cameraNode"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown));
void (this["aimFOV"] = aimFov);
void ((this["cameraNode"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["getComponent"](Camera)["fov"] = this["defaultFOV"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown);
}
} while (false);
}
finally {
}
}
onTouchStart(event: EventTouch): void {
try {
do {
switch (0 as number) {
case 1: break;
case 2: break;
default: void ((this["aimState"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["begin"]((event["touch"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["getLocation"]()));
}
} while (false);
}
finally {
}
}
onTouchMove(event: EventTouch): void {
try {
do {
switch (0 as number) {
case 1: break;
case 2: break;
default:
const fovScale = ((this["camera"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["fov"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown) / (this["defaultFOV"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown);
void ((this["cameraNode"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["setWorldRotation"]((this["aimState"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["move"]((event["touch"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["getLocation"](), fovScale)));
}
} while (false);
}
finally {
}
}
setTutorialRotate(targetNode: Node): void {
try {
do {
switch (0 as number) {
case 1: break;
case 2: break;
default:
if (!this["cameraNode"] || !targetNode)
return;
void ((this["cameraNode"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["lookAt"](targetNode["getWorldPosition"]()));
void ((this["aimState"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["initialize"](this["cameraNode"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown));
}
} while (false);
}
finally {
}
}
shoot(): boolean {
try {
do {
switch (0 as number) {
case 1: break;
case 2: break;
default:
const didHitEnemy = this["handleRaycastHit"]();
void (this["playRecoil"]());
return didHitEnemy;
}
} while (false);
}
finally {
}
}
closeQingBao(): void {
try {
do {
switch (0 as number) {
case 1: break;
case 2: break;
default: void (((this["qingBao"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["node"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["active"] = false);
}
} while (false);
}
finally {
}
}
showQingBao(): void {
try {
do {
switch (0 as number) {
case 1: break;
case 2: break;
default:
void (((this["qingBao"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["node"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["active"] = true);
const enemy = (GameController["getInstance"]()["curLevel"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["getQingBaoEnemey"]()["centerNode"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown;
const enemyPosition = enemy["getWorldPosition"]();
const direction = enemyPosition["clone"]()["subtract"]((this["cameraNode"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["getWorldPosition"]())["normalize"]();
const cameraPosition = enemyPosition["clone"]()["add"](direction["clone"]()["multiplyScalar"](-15));
void (((this["qingBao"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["node"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["setWorldPosition"](cameraPosition));
void (((this["qingBao"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["node"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["forward"] = direction);
}
} while (false);
}
finally {
}
}
fireLastBullet(ragdoll: Ragdoll, hitPoint: Vec3): void {
try {
do {
switch (0 as number) {
case 1: break;
case 2: break;
default:
const lastBullet = instantiate(this["lastBulletPrefab"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown);
void (lastBullet["parent"] = this["node"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown);
void (lastBullet["setWorldPosition"]((this["cameraNode"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["worldPosition"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown));
void (lastBullet["forward"] = ((this["cameraNode"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["worldPosition"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["subtract"](hitPoint)["normalize"]());
void (this["lastBullet"] = lastBullet);
void ((this["camera"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["enabled"] = false);
void ((UIManager["instance"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["closeAllPanels"]());
void (tween(lastBullet)["to"](1.67, { "worldPosition": hitPoint }, { "easing": 'cubicIn' })["call"](() => {
try {
do {
switch (0 as number) {
case 1: break;
case 2: break;
default:
void (ragdoll["setEnabled"](true));
void (lastBullet["getChildByName"]('bullet')["active"] = false);
void ((GameController["getInstance"]()["curLevel"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["win"]());
}
} while (false);
}
finally {
}
})["start"]());
}
} while (false);
}
finally {
}
}
clear(): void {
try {
do {
switch (0 as number) {
case 1: break;
case 2: break;
default:
if (!(this["lastBullet"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown))
return;
void ((this["lastBullet"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["destroy"]());
void (this["lastBullet"] = null);
}
} while (false);
}
finally {
}
}
onAimButtonClick(isAnim: boolean): void {
try {
do {
switch (0 as number) {
case 1: break;
case 2: break;
default:
const camera = (this["cameraNode"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["getComponent"](Camera);
if (!camera)
return;
void (this["isAiming"] = isAnim);
void (tween(camera)["to"](0.1, { "fov": this["isAiming"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown ? this["aimFOV"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown : this["defaultFOV"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown })["start"]());
}
} while (false);
}
finally {
}
}
private handleRaycastHit(): boolean {
try {
do {
switch (0 as number) {
case 1: break;
case 2: break;
default:
const ray = new (geometry["Ray"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)();
void ((this["camera"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["screenPointToRay"](((screen["windowSize"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["width"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown) / 2, ((screen["windowSize"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["height"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown) / 2, ray));
if (!(PhysicsSystem["instance"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["raycastClosest"](ray, 0xffffffff, 10000000, true))
return false;
const hit = (PhysicsSystem["instance"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["raycastClosestResult"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown;
const bone = ((hit["collider"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["node"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["getComponent"](RagdollBone);
if (!bone || (bone["ragdoll"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["isDie"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)
return false;
if ((GameController["getInstance"]()["curLevel"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["judgeLastBullet"]()) {
void (this["fireLastBullet"](bone["ragdoll"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown, hit["hitPoint"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown));
return false;
}
void (this["scheduleOnce"](() => ((bone["ragdoll"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["node"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["active"] = false, 2));
void ((bone["ragdoll"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["setEnabled"](true));
void (((this["particle"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["node"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["setWorldPosition"]((hit["hitPoint"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["clone"]()));
void ((this["particle"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["play"]());
return true;
}
} while (false);
}
finally {
}
}
private playRecoil(): void {
try {
do {
switch (0 as number) {
case 1: break;
case 2: break;
default: void (tween((this["camera"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["node"] satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown satisfies unknown)["by"](0.05, { "position": new Vec3(0, 2, 0) }, { "easing": 'sineOutIn' })["by"](0.05, { "position": new Vec3(0, -2, 0) }, { "easing": 'sineOutIn' })["start"]());
}
} while (false);
}
finally {
}
}
}