Add tracking target parameter
This commit is contained in:
parent
c3d4c13c10
commit
0afb0b6aee
@ -57,7 +57,6 @@ class BoundaryConstraint extends Behavior<IBoundaryConstraintBehaviorParameter,
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
fx = 0;
|
||||
fy = 0;
|
||||
fz = 0;
|
||||
@ -65,11 +64,13 @@ class BoundaryConstraint extends Behavior<IBoundaryConstraintBehaviorParameter,
|
||||
}
|
||||
}
|
||||
|
||||
individual.applyForce(
|
||||
fx * this.parameter.strength,
|
||||
fy * this.parameter.strength,
|
||||
fz * this.parameter.strength
|
||||
);
|
||||
if (fLen && fLen !== Infinity) {
|
||||
individual.applyForce(
|
||||
fx * this.parameter.strength / fLen,
|
||||
fy * this.parameter.strength / fLen,
|
||||
fz * this.parameter.strength / fLen
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public override terms: Record<string, Record<string, string>> = {
|
||||
|
@ -5,7 +5,9 @@ import { Model } from "@Model/Model";
|
||||
|
||||
type ITrackingBehaviorParameter = {
|
||||
target: "LG",
|
||||
strength: "number"
|
||||
strength: "number",
|
||||
range: "number",
|
||||
lock: "boolean"
|
||||
}
|
||||
|
||||
type ITrackingBehaviorEvent = {}
|
||||
@ -24,12 +26,15 @@ class Tracking extends Behavior<ITrackingBehaviorParameter, ITrackingBehaviorEve
|
||||
|
||||
public override parameterOption = {
|
||||
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 => {
|
||||
let target: Individual | undefined;
|
||||
let currentDistant: number = Infinity;
|
||||
private target: Individual | undefined = undefined;
|
||||
private currentDistant: number = Infinity;
|
||||
|
||||
private searchTarget(individual: Individual) {
|
||||
|
||||
for (let i = 0; i < this.parameter.target.objects.length; i++) {
|
||||
const targetGroup = this.parameter.target.objects[i];
|
||||
@ -40,19 +45,79 @@ class Tracking extends Behavior<ITrackingBehaviorParameter, ITrackingBehaviorEve
|
||||
if (targetIndividual === individual) return;
|
||||
let dis = targetIndividual.distanceTo(individual);
|
||||
|
||||
if (dis < currentDistant) {
|
||||
target = targetIndividual;
|
||||
currentDistant = dis;
|
||||
if (dis < this.currentDistant && dis <= this.parameter.range) {
|
||||
this.target = targetIndividual;
|
||||
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(
|
||||
(target.position[0] - individual.position[0]) * this.parameter.strength,
|
||||
(target.position[1] - individual.position[1]) * this.parameter.strength,
|
||||
(target.position[2] - individual.position[2]) * this.parameter.strength
|
||||
(this.target.position[0] - individual.position[0]) * this.parameter.strength / this.currentDistant,
|
||||
(this.target.position[1] - individual.position[1]) * this.parameter.strength / this.currentDistant,
|
||||
(this.target.position[2] - individual.position[2]) * this.parameter.strength / this.currentDistant
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -66,6 +131,14 @@ class Tracking extends Behavior<ITrackingBehaviorParameter, ITrackingBehaviorEve
|
||||
"ZH_CN": "追踪目标",
|
||||
"EN_US": "Tracking target"
|
||||
},
|
||||
"$Lock": {
|
||||
"ZH_CN": "追踪锁定",
|
||||
"EN_US": "Tracking lock"
|
||||
},
|
||||
"$Range": {
|
||||
"ZH_CN": "追踪范围",
|
||||
"EN_US": "Tracking range"
|
||||
},
|
||||
"$Strength": {
|
||||
"ZH_CN": "追踪强度系数",
|
||||
"EN_US": "Tracking intensity coefficient"
|
||||
|
@ -61,8 +61,8 @@ class CtrlObject extends LabelObject {
|
||||
/**
|
||||
* 判断是否为相同对象
|
||||
*/
|
||||
public equal(obj: CtrlObject): boolean {
|
||||
return this === obj || this.id === obj.id;
|
||||
public equal(obj?: CtrlObject): boolean {
|
||||
return this === obj || this.id === obj?.id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -272,9 +272,11 @@ class Group extends CtrlObject {
|
||||
public remove(individual: Individual[] | Individual): this {
|
||||
if (Array.isArray(individual)) {
|
||||
for (let i = 0; i < individual.length; i++) {
|
||||
individual[i].group = undefined;
|
||||
this.individuals.delete(individual[i]);
|
||||
}
|
||||
} else {
|
||||
individual.group = undefined;
|
||||
this.individuals.delete(individual);
|
||||
}
|
||||
return this;
|
||||
|
@ -88,7 +88,7 @@ class Individual {
|
||||
/**
|
||||
* 所属群组
|
||||
*/
|
||||
public group: Group;
|
||||
public group: Group | undefined;
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
@ -97,11 +97,16 @@ class Individual {
|
||||
this.group = group;
|
||||
}
|
||||
|
||||
public isDie(): boolean {
|
||||
return !!this.group;
|
||||
}
|
||||
|
||||
/**
|
||||
* 死亡
|
||||
*/
|
||||
public die(): this {
|
||||
this.group.remove(this);
|
||||
this.group?.remove(this);
|
||||
this.group = undefined;
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -110,7 +115,7 @@ class Individual {
|
||||
* @param newGroup 新群体
|
||||
*/
|
||||
public transfer(newGroup: Group): this {
|
||||
this.group.remove(this);
|
||||
this.group?.remove(this);
|
||||
newGroup.add(this);
|
||||
this.group = newGroup;
|
||||
return this;
|
||||
|
Loading…
Reference in New Issue
Block a user