我有一组三角形,它们基于植绒算法移动。我使用了JavaFX的路径转换,以便它们沿着一条路径移动,同时保留该路径中的植绒行为。但是,当我尝试通过设置持续时间(以毫秒为单位)来减慢路径转换时,三角形要么移动得非常快,要么仍然卡在一个地方。我一直试图寻找其他解决方案,但我们找不到任何解决方案,所以我在这里提出这个问题。
package model;
import utility.Vector2d;
import java.util.Random;
import javafx.animation.PathTransition;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.CubicCurveTo;
import javafx.scene.shape.LineTo;
import javafx.scene.shape.MoveTo;
import javafx.scene.shape.Path;
import javafx.util.Duration;
public class BusinessPersonBoid extends Circle{
public Vector2d position;
protected Vector2d position2;
protected Vector2d position3;
protected Vector2d position4;
protected Vector2d position5;
protected Vector2d velocity;
protected final int speedLimit = 2;
protected String name;
protected ImageView display;
protected Circle circle;
public LineTo line1;
public LineTo line2;
public LineTo line3;
public LineTo line4;
public BusinessPersonBoid(int x, int y, String n, Circle c) {
this.display = new ImageView();
this.display.setX(x);
this.display.setY(y);
this.display.setSmooth(true);
this.display.setCache(true);
this.display.setImage(new Image("images2/boid-green.png"));
this.circle = new Circle(15,Color.BLUE);
this.position = new Vector2d(x, y);
this.velocity = new Vector2d(0,0);
if( n != null) {
this.name = n;
}
}
public Vector2d getPosition() {
return new Vector2d(position.xPos, position.yPos);
}
public Vector2d getVelocity() {
return velocity;
}
public void setVelocity(Vector2d velocity) {
if ( velocity.xPos > speedLimit) {
velocity.xPos = speedLimit;
}
if ( velocity.yPos > speedLimit) {
velocity.yPos = speedLimit;
}
this.velocity = velocity;
}
public void setPosition(Vector2d pos) {
setAngle(this.position, pos);
this.display.setX(pos.xPos);
this.display.setY(pos.yPos);
this.position = pos;
}
public void setPosition2(Vector2d pos, Vector2d pos2) {
setAngle(this.position, pos);
this.display.setX(pos.xPos);
this.display.setY(pos.yPos);
this.display.setX(pos.xPos);
this.display.setY(pos.yPos);
this.position = pos;
}
public void setPathway() {
Random randNum = new Random();
Path path = new Path();
MoveTo moveTo = new MoveTo(108, 71);
LineTo line1 = new LineTo(150, 140);
LineTo line2 = new LineTo(550, 140);
LineTo line3 = new LineTo(750, 140);
LineTo line4 = new LineTo(910, -40);
path.getElements().add(moveTo);
path.getElements().addAll(line1, line2, line3, line4);
PathTransition pathTransition = new PathTransition();
pathTransition.setDuration(Duration.millis(100));
pathTransition.setNode(display);
pathTransition.setPath(path);
pathTransition.play();
}
public void setAngle(Vector2d current, Vector2d next) {
double delta_x = next.xPos - current.xPos;
double delta_y = next.yPos - current.yPos;
Double theta = Math.atan2(delta_y, delta_x);
double angle = theta*180/Math.PI;
this.display.setRotate(angle);
}
public String getName() {
return this.name;
}
public ImageView getDisplay() {
return this.display;
}
}
这是植绒类:
package model;
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;
public BusinessPersonBoid cBoid;
public Vector2d Checkin;
public Vector2d CurrencyExchange;
public Vector2d Lounge;
public Vector2d Shop;
public Vector2d BoardingGate;
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(50) + 1;
int y = randNum.nextInt(140) + 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) {
v1 = groupFlock(cBoid);
v2 = collisionAvoidance(cBoid);
v3 = matchFlockVelocity(cBoid);
v4 = bounding(cBoid);
v5 = positionTend(cBoid);
Vector2d v12 = new Vector2d(-50,140);
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.setPathway();
cBoid.setVelocity(cBoid.getVelocity().add(sum));
Vector2d next = new Vector2d( cBoid.getPosition().add(cBoid.getVelocity()) );
cBoid.setPosition(next);
}
}
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;
}
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;
}
public int tendToPlace(BusinessPersonBoid cBoid) {
Vector2d place = new Vector2d(-50,140);
return place.minus(cBoid.position)/100;
}
我的问题是如何将三角形减慢到可以实际看到它们正常移动的速度?
RandomName class:
package model;
import java.util.ArrayList;
import java.util.Random;
public class RandomName {
private Random randomGenerator;
private ArrayList<Integer> usedList;
private String[] nameBank = { "Alpha",
"Bravo",
"Charlie",
"Delta",
"Echo",
"Foxtrot",
"Golf",
"Hotel",
"India",
"Juliet",
"Kilo",
"Lima",
"Mike",
"November",
"Oscar",
"Papa",
"Quebec",
"Romeo",
"Sierra",
"Tango",
"Uniform",
"Victor",
"Whiskey",
"X-ray",
"Yankee",
"Zulu" };
public RandomName() {
randomGenerator = new Random();
usedList = new ArrayList<Integer>();
}
public String getName() {
return nameBank[getIndex()];
}
private int getIndex() {
int i = randomGenerator.nextInt(nameBank.length);
while(usedList.contains(i)) {
if(usedList.size() >= nameBank.length ) {
usedList.clear();
}
i = randomGenerator.nextInt(nameBank.length);
}
usedList.add(i);
return i;
}
public void addName(String add) {
nameBank[nameBank.length+1+1] = add;
}
public void addName(String[] add) {
for(int i = 0; i < add.length; i++) {
nameBank[nameBank.length+1] = add[i];
}
}
}
Vector2d类:
package utility;
public class Vector2d {
public double xPos;
public double yPos;
public Vector2d(){
this.xPos = 0;
this.yPos = 0;
}
public Vector2d(Vector2d v){
this.xPos = v.xPos;
this.yPos = v.yPos;
}
public Vector2d(double x, double y){
this.xPos = x;
this.yPos = y;
}
public Vector2d add(Vector2d addVector){
return new Vector2d(this.xPos += addVector.xPos, this.yPos += addVector.yPos );
}
public Vector2d add(double x, double y){
return new Vector2d(this.xPos += x, this.yPos += y );
}
public Vector2d subtract(double x, double y){
return new Vector2d(this.xPos += x, this.yPos += y );
}
public Vector2d subtract(Vector2d subVector){
return new Vector2d(this.xPos = (this.xPos - subVector.xPos), this.yPos = (this.yPos - subVector.yPos));
}
public Vector2d division(double divider) {
return new Vector2d(this.xPos =( xPos / divider), this.yPos =( yPos / divider));
}
public double absX() {
return Math.sqrt(Math.pow(this.xPos, 2));
}
public double absY() {
return Math.sqrt(Math.pow(this.yPos, 2));
}
public double abs() {
return Math.sqrt(Math.pow(this.xPos, 2) + Math.pow(this.yPos, 2));
}
public int minus(Vector2d position) {
// TODO Auto-generated method stub
return 0;
}
}