基于Java的群组仿真有限状态机
我正在使用Java构建群组模拟。我已经基于MVC框架拆分了我的应用程序。我使用了群集算法来模拟人们的运动。现在我需要一群人沿着既定的道路前进。我试图用FSM来做这件事,但需要一些额外的指导 每组乘客由一个阵列列表组成,该列表中有一个小的三角形符号表示每个乘客基于Java的群组仿真有限状态机,java,javafx,Java,Javafx,我正在使用Java构建群组模拟。我已经基于MVC框架拆分了我的应用程序。我使用了群集算法来模拟人们的运动。现在我需要一群人沿着既定的道路前进。我试图用FSM来做这件事,但需要一些额外的指导 每组乘客由一个阵列列表组成,该列表中有一个小的三角形符号表示每个乘客 import java.util.ArrayList; import java.util.List; import java.util.Random; import utility.Vector2d; import javafx.anim
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import utility.Vector2d;
import javafx.animation.PathTransition;
import javafx.animation.Timeline;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.shape.Circle;
import javafx.scene.shape.CubicCurveTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.scene.shape.Rectangle;
import javafx.util.Duration;
public class Flock2 {
public ArrayList<BusinessPersonBoid> boids2;
private double movementFactor = 1000;
private double boundingFactor = 10;
private int seperationDistance = 43;
private double seperationFactor = 50;
Circle c = new Circle();
Circle c2 = new Circle();
public Flock2() {
boids2 = new ArrayList<BusinessPersonBoid>();
Random randNum = new Random();
RandomName randName = new RandomName();
for(int i = 0; i < 10; i++) {
int x = randNum.nextInt(1000) + 1;
int y = randNum.nextInt(400) + 1;
boids2.add(new BusinessPersonBoid(x,y, randName.getName(), c ));
}
}
public void updateBoidsPostion() {
Vector2d v1, v2, v3, v4, v5 = new Vector2d();
for (BusinessPersonBoid cBoid : boids2) {
Path path = new Path();
path.getElements().add(new MoveTo(-50,140));
path.getElements().add(new MoveTo(150,140));
path.getElements().add(new MoveTo(750,140));
path.getElements().add(new MoveTo(910,-40));
PathTransition pathTransition = new PathTransition();
pathTransition.setPath(path);
pathTransition.setNode(cBoid);
v1 = groupFlock(cBoid);
v2 = collisionAvoidance(cBoid);
v3 = matchFlockVelocity(cBoid);
v4 = bounding(cBoid);
v5 = positionTend(cBoid);
Vector2d sum = new Vector2d();
sum = sum.add(v1);
sum = sum.add(v2);
sum = sum.add(v3);
sum = sum.add(v4);
sum = sum.add(v5);
cBoid.setVelocity(cBoid.getVelocity().add(sum));
Vector2d next = new Vector2d( cBoid.getPosition().add(cBoid.getVelocity()) );
cBoid.setPosition(next);
Vector2d next2 = new Vector2d( cBoid.getPosition().add(cBoid.getVelocity()) );
pathTransition.play();
}
}
private Vector2d groupFlock(BusinessPersonBoid cBoid) {
Vector2d center = new Vector2d();
for (BusinessPersonBoid aBoid : boids2) {
if(!aBoid.equals(cBoid)) {
center = center.add(aBoid.getPosition());
}
}
center = center.division(boids2.size() - 1 );
center = center.subtract(cBoid.getPosition());
center = center.division(movementFactor);
return center;
}
private Vector2d collisionAvoidance(BusinessPersonBoid cBoid) {
Vector2d correction = new Vector2d();
Vector2d cPosition = new Vector2d(cBoid.getPosition());
for (BusinessPersonBoid aBoid : boids2) {
if (!aBoid.equals(cBoid)) {
Vector2d aPosition = aBoid.getPosition();
Vector2d xD = new Vector2d(aPosition.xPos - cPosition.xPos, aPosition.yPos - cPosition.yPos);
if(Math.abs(xD.xPos) < seperationDistance && Math.abs(xD.yPos) < seperationDistance) {
correction = correction.subtract(xD).division(seperationFactor);
}
}
}
return correction;
}
private Vector2d matchFlockVelocity(BusinessPersonBoid cBoid) {
Vector2d perceivedVelocity = new Vector2d();
for(BusinessPersonBoid aBoid : boids2) {
if(!aBoid.equals(cBoid)) {
perceivedVelocity = perceivedVelocity.add(aBoid.getVelocity());
}
}
perceivedVelocity = perceivedVelocity.division(boids2.size() - 1);
perceivedVelocity = perceivedVelocity.subtract(cBoid.getVelocity());
perceivedVelocity = perceivedVelocity.division(8);
return perceivedVelocity;
}
private Vector2d bounding(BusinessPersonBoid cBoid) {
Vector2d bound = new Vector2d();
int xMin = 0, xMax = 1400, yMin = 0, yMax = 320;
Vector2d cPos = cBoid.getPosition();
if (cPos.xPos < xMin) {
bound.xPos += 1;
cPos.xPos = bound.xPos;
} else if (cPos.xPos > xMax){
bound.xPos += -100;
cPos.xPos = bound.xPos;
}
if (cPos.yPos < yMin) {
bound.yPos += 1;
cPos.yPos = bound.yPos;
} else if (cPos.yPos > yMax){
bound.yPos += -100;
cPos.yPos = bound.yPos;
}
bound = bound.division(boundingFactor);
return bound;
}
private Vector2d positionTend(BusinessPersonBoid cBoid) {
Vector2d place = new Vector2d(900,600);
Vector2d tend = new Vector2d();
tend = new Vector2d(place.subtract(cBoid.getPosition()));
tend.division(6000);
return tend;
}
public List<ImageView> getBoidsRepresentation() {
List<ImageView> circles = new ArrayList<ImageView>();
for(BusinessPersonBoid aBoid : boids2) {
circles.add( aBoid.getDisplay() );
}
return circles;
}
private Vector2d bounding2(BusinessPersonBoid cBoid) {
Vector2d bound = new Vector2d();
int xMin = 0, xMax = 600, yMin = 0, yMax = 600;
Vector2d cPos = cBoid.getPosition();
bound.xPos = 100;
cPos.xPos = bound.xPos;
bound.yPos = 100;
cPos.yPos = bound.yPos;
bound = bound.division(boundingFactor);
return bound;
}
目前,它对BOID采取的整体路径没有影响。它们需要作为一个组从屏幕的一个区域移动到另一个区域,但在该组中保留随机移动
我的问题是,在保留BOID组内的随机移动的同时,将BOID从屏幕的一个区域移动到另一个区域的最佳方法是什么?您忘记问实际问题了。请添加一个。我不能评论“最佳”方法,但尝试将boid位置编码为相对于组的位置,这样组作为一个整体移动,因为boid相对于组移动,它也必须移动相同的方向,但它也可以围绕质心随机移动。或者你可以有一个boid“响应”一段时间后,一个群体的运动是随机的,所以它的运动不会完全是随机的。
private Vector2d pathway(BusinessPersonBoid cBoid) {
Vector2d pathway = new Vector2d();
Path path = new Path();
path.getElements().add(new MoveTo(20,20));
path.getElements().add(new CubicCurveTo(380, 0, 380, 120, 200, 120));
path.getElements().add(new CubicCurveTo(0, 120, 0, 240, 380, 240));
PathTransition pathTransition = new PathTransition();
pathTransition.setDuration(Duration.millis(4000));
pathTransition.setPath(path);
pathTransition.setNode(cBoid);
return pathway;
}