83 lines
2.3 KiB
TypeScript
83 lines
2.3 KiB
TypeScript
// assets/scripts/Preview.ts
|
||
import { _decorator, Component, Node, Prefab, instantiate, Vec3 } from "cc";
|
||
import { BallPhysics } from "./BallPhysics";
|
||
const { ccclass, property } = _decorator;
|
||
|
||
@ccclass("Preview")
|
||
export class Preview extends Component {
|
||
@property(Prefab) pointPrefab: Prefab = null!;
|
||
@property(Node) goal: Node = null!;
|
||
|
||
@property({ tooltip: "轨迹点数量" }) maxPoints = 30;
|
||
@property({ tooltip: "步长时间(秒)" }) timeStep = 0.05;
|
||
|
||
@property(BallPhysics) ballPhys: BallPhysics = null!;
|
||
|
||
private points: Node[] = [];
|
||
|
||
clear() {
|
||
for (const p of this.points) p.destroy();
|
||
this.points.length = 0;
|
||
}
|
||
|
||
/** 显示预测轨迹 */
|
||
showTrajectory(startPos: Vec3, dir: Vec3, speed: number, spin: Vec3) {
|
||
this.clear();
|
||
if (!this.pointPrefab || !this.ballPhys) return;
|
||
|
||
const goalZ = this.goal?.worldPosition?.z;
|
||
|
||
// 初始状态
|
||
let pos = startPos.clone();
|
||
let v = dir.clone().multiplyScalar(speed);
|
||
let w = spin.clone(); // 自旋
|
||
|
||
// 迭代预测
|
||
// let age = 0;
|
||
for (let i = 0; i < this.maxPoints; i++) {
|
||
// age += this.timeStep;
|
||
// 保存点
|
||
const p = instantiate(this.pointPrefab);
|
||
p.setWorldPosition(pos);
|
||
p.setParent(this.node);
|
||
this.points.push(p);
|
||
|
||
// === 模拟 BallPhysics.update(dt) ===
|
||
// const dt = this.timeStep;
|
||
const dt = this.timeStep * 0.5;
|
||
|
||
// 空气阻力
|
||
const speedNow = v.length();
|
||
if (speedNow > 0.01) {
|
||
const drag = v.clone().multiplyScalar(-this.ballPhys.dragK * speedNow);
|
||
v.add(drag.multiplyScalar(dt));
|
||
}
|
||
|
||
// 马格努斯效应:F = k * (ω × v)
|
||
if (w.lengthSqr() > 0.0001 && v.lengthSqr() > 0.0001) {
|
||
// const tFactor = 1.0 / (1.0 + age * 2.0); // age 是飞行时间,越久衰减越快
|
||
// const magnus = w
|
||
// .clone()
|
||
// .cross(v)
|
||
// .multiplyScalar(this.ballPhys.magnusK * tFactor);
|
||
// v.add(magnus.multiplyScalar(dt));
|
||
const magnus = w.clone().cross(v).multiplyScalar(this.ballPhys.magnusK);
|
||
v.add(magnus.multiplyScalar(dt));
|
||
}
|
||
|
||
// 重力
|
||
v.y += -9.8 * dt;
|
||
|
||
// 移动
|
||
pos = pos.add(v.clone().multiplyScalar(dt));
|
||
|
||
if (
|
||
(startPos.z > goalZ && pos.z <= goalZ) ||
|
||
(startPos.z < goalZ && pos.z >= goalZ)
|
||
) {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|