Add direction cluster behavior

This commit is contained in:
MrKBear 2022-05-06 23:12:00 +08:00
parent f660aefa4c
commit 974cd2951d
3 changed files with 99 additions and 4 deletions

View File

@ -8,6 +8,7 @@ import { ContactAttacking } from "@Behavior/ContactAttacking";
import { ContactAssimilate } from "@Behavior/ContactAssimilate";
import { DelayAssimilate } from "@Behavior/DelayAssimilate";
import { Avoidance } from "@Behavior/Avoidance";
import { DirectionCluster } from "@Behavior/DirectionCluster";
const AllBehaviors: IAnyBehaviorRecorder[] = [
new BehaviorRecorder(Template),
@ -19,6 +20,7 @@ const AllBehaviors: IAnyBehaviorRecorder[] = [
new BehaviorRecorder(ContactAssimilate),
new BehaviorRecorder(DelayAssimilate),
new BehaviorRecorder(Avoidance),
new BehaviorRecorder(DirectionCluster),
]
/**

View File

@ -0,0 +1,93 @@
import { Behavior } from "@Model/Behavior";
import { Group } from "@Model/Group";
import { Individual } from "@Model/Individual";
import { Model } from "@Model/Model";
type IDirectionClusterBehaviorParameter = {
cluster: "CLG",
strength: "number",
range: "number"
}
type IDirectionClusterBehaviorEvent = {}
class DirectionCluster extends Behavior<IDirectionClusterBehaviorParameter, IDirectionClusterBehaviorEvent> {
public override behaviorId: string = "DirectionCluster";
public override behaviorName: string = "$Title";
public override iconName: string = "RawSource";
public override describe: string = "$Intro";
public override category: string = "$Interactive";
public override parameterOption = {
cluster: { name: "$Cluster", type: "CLG" },
strength: { type: "number", name: "$Strength", defaultValue: 1, numberMin: 0, numberStep: .1 },
range: { type: "number", name: "$Range", defaultValue: 4, numberMin: 0, numberStep: .1 }
};
public effect = (individual: Individual, group: Group, model: Model, t: number): void => {
let findCount = 0;
let centerDir: number[] = [0, 0, 0];
for (let i = 0; i < this.parameter.cluster.objects.length; i++) {
const targetGroup = this.parameter.cluster.objects[i];
targetGroup.individuals.forEach((targetIndividual) => {
// 排除自己
if (targetIndividual === individual) return;
let dis = targetIndividual.distanceTo(individual);
if (dis <= this.parameter.range) {
centerDir[0] += targetIndividual.velocity[0];
centerDir[1] += targetIndividual.velocity[1];
centerDir[2] += targetIndividual.velocity[2];
findCount ++;
}
});
}
if (findCount > 0) {
let length = individual.vectorLength(centerDir);
if (length) {
individual.applyForce(
centerDir[0] * this.parameter.strength / length,
centerDir[1] * this.parameter.strength / length,
centerDir[2] * this.parameter.strength / length
);
}
}
}
public override terms: Record<string, Record<string, string>> = {
"$Title": {
"ZH_CN": "方向结群",
"EN_US": "Directional clustering"
},
"$Intro": {
"ZH_CN": "个体将按照视野范围内目标方向结群对象个体的平均移动方向移动",
"EN_US": "Individuals will move according to the average moving direction of the grouped object individuals in the target direction within the field of vision"
},
"$Cluster": {
"ZH_CN": "方向结群对象",
"EN_US": "Directional clustering object"
},
"$Strength": {
"ZH_CN": "结群强度",
"EN_US": "Clustering strength"
},
"$Range": {
"ZH_CN": "视野范围",
"EN_US": "Field of vision"
}
};
}
export { DirectionCluster };

View File

@ -31,11 +31,11 @@ class PhysicsDynamics extends Behavior<IPhysicsDynamicsBehaviorParameter, IPhysi
limit: { name: "$Limit", type: "boolean", defaultValue: true },
maxAcceleration: {
name: "$Max.Acceleration", type: "number", defaultValue: 6.25,
numberStep: .1, numberMin: 0, condition: { key: "limit", value: true }
numberStep: .1, numberMin: 0.0001, condition: { key: "limit", value: true }
},
maxVelocity: {
name: "$Max.Velocity", type: "number", defaultValue: 12.5,
numberStep: .1, numberMin: 0, condition: { key: "limit", value: true }
numberStep: .1, numberMin: 0.0001, condition: { key: "limit", value: true }
},
};
@ -64,7 +64,7 @@ class PhysicsDynamics extends Behavior<IPhysicsDynamicsBehaviorParameter, IPhysi
// 加速度约束
if (this.parameter.limit) {
const lengthA = individual.vectorLength(individual.acceleration);
if (lengthA > this.parameter.maxAcceleration) {
if (lengthA > this.parameter.maxAcceleration && lengthA) {
individual.acceleration[0] = individual.acceleration[0] * this.parameter.maxAcceleration / lengthA;
individual.acceleration[1] = individual.acceleration[1] * this.parameter.maxAcceleration / lengthA;
individual.acceleration[2] = individual.acceleration[2] * this.parameter.maxAcceleration / lengthA;
@ -79,7 +79,7 @@ class PhysicsDynamics extends Behavior<IPhysicsDynamicsBehaviorParameter, IPhysi
// 速度约束
if (this.parameter.limit) {
const lengthV = individual.vectorLength(individual.velocity);
if (lengthV > this.parameter.maxVelocity) {
if (lengthV > this.parameter.maxVelocity && lengthV) {
individual.velocity[0] = individual.velocity[0] * this.parameter.maxVelocity / lengthV;
individual.velocity[1] = individual.velocity[1] * this.parameter.maxVelocity / lengthV;
individual.velocity[2] = individual.velocity[2] * this.parameter.maxVelocity / lengthV;