Files
ball/assets/scripts/Preview.ts
1970-01-01 08:45:37 +08:00

83 lines
2.3 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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;
}
}
}
}