Files

83 lines
2.3 KiB
TypeScript
Raw Permalink Normal View History

1970-01-01 08:45:37 +08:00
// 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;
}
}
}
}