Add tracking target parameter

This commit is contained in:
MrKBear 2022-04-11 17:33:56 +08:00
parent c3d4c13c10
commit 0afb0b6aee
5 changed files with 104 additions and 23 deletions

View File

@ -57,7 +57,6 @@ class BoundaryConstraint extends Behavior<IBoundaryConstraintBehaviorParameter,
} }
} else { } else {
fx = 0; fx = 0;
fy = 0; fy = 0;
fz = 0; fz = 0;
@ -65,11 +64,13 @@ class BoundaryConstraint extends Behavior<IBoundaryConstraintBehaviorParameter,
} }
} }
individual.applyForce( if (fLen && fLen !== Infinity) {
fx * this.parameter.strength, individual.applyForce(
fy * this.parameter.strength, fx * this.parameter.strength / fLen,
fz * this.parameter.strength fy * this.parameter.strength / fLen,
); fz * this.parameter.strength / fLen
);
}
} }
public override terms: Record<string, Record<string, string>> = { public override terms: Record<string, Record<string, string>> = {

View File

@ -5,7 +5,9 @@ import { Model } from "@Model/Model";
type ITrackingBehaviorParameter = { type ITrackingBehaviorParameter = {
target: "LG", target: "LG",
strength: "number" strength: "number",
range: "number",
lock: "boolean"
} }
type ITrackingBehaviorEvent = {} type ITrackingBehaviorEvent = {}
@ -24,12 +26,15 @@ class Tracking extends Behavior<ITrackingBehaviorParameter, ITrackingBehaviorEve
public override parameterOption = { public override parameterOption = {
target: { type: "CLG", name: "$Target" }, target: { type: "CLG", name: "$Target" },
strength: { type: "number", name: "$Strength", defaultValue: 10, numberMin: 0, numberStep: .1 } lock: { type: "boolean", name: "$Lock", defaultValue: false },
range: { type: "number", name: "$Range", defaultValue: 4, numberMin: 0, numberStep: .1 },
strength: { type: "number", name: "$Strength", defaultValue: 1, numberMin: 0, numberStep: .1 }
}; };
public effect = (individual: Individual, group: Group, model: Model, t: number): void => { private target: Individual | undefined = undefined;
let target: Individual | undefined; private currentDistant: number = Infinity;
let currentDistant: number = Infinity;
private searchTarget(individual: Individual) {
for (let i = 0; i < this.parameter.target.objects.length; i++) { for (let i = 0; i < this.parameter.target.objects.length; i++) {
const targetGroup = this.parameter.target.objects[i]; const targetGroup = this.parameter.target.objects[i];
@ -40,19 +45,79 @@ class Tracking extends Behavior<ITrackingBehaviorParameter, ITrackingBehaviorEve
if (targetIndividual === individual) return; if (targetIndividual === individual) return;
let dis = targetIndividual.distanceTo(individual); let dis = targetIndividual.distanceTo(individual);
if (dis < currentDistant) { if (dis < this.currentDistant && dis <= this.parameter.range) {
target = targetIndividual; this.target = targetIndividual;
currentDistant = dis; this.currentDistant = dis;
} }
}); });
} }
}
if (target) { private clearTarget() {
this.target = undefined as Individual | undefined;
this.currentDistant = Infinity;
}
public effect = (individual: Individual, group: Group, model: Model, t: number): void => {
this.clearTarget();
if (this.parameter.lock) {
let isValidTarget = false;
this.target = individual.getData("Tracking.lock.target");
if (this.target) {
// 校验目标所在的群是否仍是目标
let isInTarget = false;
for (let i = 0; i < this.parameter.target.objects.length; i++) {
if (this.parameter.target.objects[i].equal(this.target.group)) {
isInTarget = true;
break;
}
}
// 如果还在目标范围内,校验距离
if (isInTarget) {
let dis = individual.distanceTo(this.target);
// 校验成功
if (dis <= this.parameter.range) {
this.currentDistant = dis;
isValidTarget = true;
}
}
}
// 如果目标无效,尝试搜索新的目标
if (!isValidTarget) {
this.clearTarget();
this.searchTarget(individual);
// 如果成功搜索,缓存目标
if (this.target && this.currentDistant && this.currentDistant !== Infinity) {
individual.setData("Tracking.lock.target", this.target);
}
// 搜索失败,清除目标
else {
individual.setData("Tracking.lock.target", undefined);
}
}
}
else {
this.searchTarget(individual);
}
if (this.target && this.currentDistant && this.currentDistant !== Infinity) {
individual.applyForce( individual.applyForce(
(target.position[0] - individual.position[0]) * this.parameter.strength, (this.target.position[0] - individual.position[0]) * this.parameter.strength / this.currentDistant,
(target.position[1] - individual.position[1]) * this.parameter.strength, (this.target.position[1] - individual.position[1]) * this.parameter.strength / this.currentDistant,
(target.position[2] - individual.position[2]) * this.parameter.strength (this.target.position[2] - individual.position[2]) * this.parameter.strength / this.currentDistant
); );
} }
} }
@ -66,6 +131,14 @@ class Tracking extends Behavior<ITrackingBehaviorParameter, ITrackingBehaviorEve
"ZH_CN": "追踪目标", "ZH_CN": "追踪目标",
"EN_US": "Tracking target" "EN_US": "Tracking target"
}, },
"$Lock": {
"ZH_CN": "追踪锁定",
"EN_US": "Tracking lock"
},
"$Range": {
"ZH_CN": "追踪范围",
"EN_US": "Tracking range"
},
"$Strength": { "$Strength": {
"ZH_CN": "追踪强度系数", "ZH_CN": "追踪强度系数",
"EN_US": "Tracking intensity coefficient" "EN_US": "Tracking intensity coefficient"

View File

@ -61,8 +61,8 @@ class CtrlObject extends LabelObject {
/** /**
* *
*/ */
public equal(obj: CtrlObject): boolean { public equal(obj?: CtrlObject): boolean {
return this === obj || this.id === obj.id; return this === obj || this.id === obj?.id;
} }
/** /**

View File

@ -272,9 +272,11 @@ class Group extends CtrlObject {
public remove(individual: Individual[] | Individual): this { public remove(individual: Individual[] | Individual): this {
if (Array.isArray(individual)) { if (Array.isArray(individual)) {
for (let i = 0; i < individual.length; i++) { for (let i = 0; i < individual.length; i++) {
individual[i].group = undefined;
this.individuals.delete(individual[i]); this.individuals.delete(individual[i]);
} }
} else { } else {
individual.group = undefined;
this.individuals.delete(individual); this.individuals.delete(individual);
} }
return this; return this;

View File

@ -88,7 +88,7 @@ class Individual {
/** /**
* *
*/ */
public group: Group; public group: Group | undefined;
/** /**
* *
@ -97,11 +97,16 @@ class Individual {
this.group = group; this.group = group;
} }
public isDie(): boolean {
return !!this.group;
}
/** /**
* *
*/ */
public die(): this { public die(): this {
this.group.remove(this); this.group?.remove(this);
this.group = undefined;
return this; return this;
} }
@ -110,7 +115,7 @@ class Individual {
* @param newGroup * @param newGroup
*/ */
public transfer(newGroup: Group): this { public transfer(newGroup: Group): this {
this.group.remove(this); this.group?.remove(this);
newGroup.add(this); newGroup.add(this);
this.group = newGroup; this.group = newGroup;
return this; return this;