first commit

This commit is contained in:
zzc
1970-01-01 08:45:37 +08:00
commit e9c9afb3b9
53 changed files with 5254 additions and 0 deletions

View File

@@ -0,0 +1,133 @@
// assets/scripts/BallPhysics.ts
import {
_decorator,
Component,
Node,
RigidBody,
Vec3,
math,
SphereCollider,
Contact2DType,
MeshCollider,
ICollisionEvent,
ITriggerEvent,
} from "cc";
const { ccclass, property } = _decorator;
@ccclass("BallPhysics")
export class BallPhysics extends Component {
@property({ tooltip: "马格努斯系数(越大弧线越明显)" }) magnusK = 0.1;
@property({ tooltip: "空气阻力" }) dragK = 0.001;
@property({ tooltip: "风力m/s^2" }) windStrength = 0;
@property({ tooltip: "风向" }) windDir: Vec3 = new Vec3(1, 0, 0);
@property({ tooltip: "自动重置高度阈值(低于视为无效球)" }) resetY = -2;
@property(Node) spawnPoint!: Node;
@property(Node) ball!: Node;
private rb!: RigidBody;
private tmpF = new Vec3();
private v = new Vec3();
private w = new Vec3();
private wind = new Vec3();
private pos = new Vec3();
// ⚽ 保存 spinKickInput 设置进来)
private spin = new Vec3();
onLoad() {
this.rb = this.ball.getComponent(RigidBody)!;
const col = this.ball.getComponent(MeshCollider);
if (col) {
console.log(22223333, col);
col.on("onTriggerEnter", this.onTriggerEnter, this);
col.on("onTriggerStay", this.onTriggerStay, this);
col.on("onCollisionEnter", this.onCollisionEnter, this);
}
this.wind.set(this.windDir).normalize();
}
private onTriggerStay(event: ITriggerEvent) {
console.log(event.type, event);
}
onTriggerEnter(event: ICollisionEvent) {
console.log("⚽ 触发器进入:", event.otherCollider.node.name);
}
onCollisionEnter(event: ICollisionEvent) {
console.log("⚽ 碰撞进入:", event.otherCollider.node.name);
}
init() {
this.rb = this.node.getComponent(RigidBody)!;
this.wind.set(this.windDir).normalize();
this.pos = this.node.worldPosition.clone();
}
setWind(direction: Vec3, strength: number) {
this.wind.set(direction).normalize();
this.windStrength = strength;
}
resetBall() {
if (!this.spawnPoint) return;
this.rb.clearState();
this.node.worldPosition = this.pos; //this.spawnPoint.worldPosition.clone();
this.rb.setLinearVelocity(new Vec3());
this.rb.setAngularVelocity(new Vec3());
}
/** 设置自旋(由 KickInput 调用) */
public setSpin(spin: Vec3) {
this.spin.set(spin);
}
/** 发射足球 */
shootBall(dir: Vec3, speed: number) {
this.rb.clearState();
this.rb.setLinearVelocity(dir.clone().multiplyScalar(speed));
this.rb.setAngularVelocity(this.spin); // 应用横向旋转
}
update(dt: number) {
if (!this.rb) return;
this.rb.getLinearVelocity(this.v);
// 1. 空气阻力(与预测保持一致: -k * v * |v|
const speed = this.v.length();
if (speed > 0.01) {
const drag = this.v.clone().multiplyScalar(-this.dragK * speed);
this.rb.applyForce(drag);
}
// 2. 马格努斯力: F = k * (spin × v)
if (!this.spin.equals(Vec3.ZERO) && speed > 0.01) {
const magnus = new Vec3();
Vec3.cross(magnus, this.spin, this.v);
magnus.multiplyScalar(this.magnusK);
this.rb.applyForce(magnus);
}
// if (!this.spin.equals(Vec3.ZERO) && speed > 0.01) {
// const magnus = new Vec3();
// const vNorm = this.v.clone().normalize();
// Vec3.cross(magnus, this.spin, vNorm);
// magnus.multiplyScalar(this.magnusK * Math.sqrt(speed));
// this.rb.applyForce(magnus);
// }
// 3. 风
if (this.windStrength > 0.0001) {
this.tmpF.set(this.wind).multiplyScalar(this.windStrength);
this.rb.applyForce(this.tmpF);
}
// 4. 掉出场地自动重置
if (this.node.worldPosition.y < this.resetY && this.spawnPoint) {
this.resetBall();
}
}
}