を私はそれを働かせた。以下のクラスは、Action
インスタンス、正確にはSequenceAction
を作成します。それが作成するAction
は、ユーザが提供するポイントを通じてActor
を通過します。スピード、継続時間、パス上のActor
の位置をオフセットし、Actor
を回転させ、さらに画面に出入りするときにActor
をインデントします。
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.actions.SequenceAction;
import java.util.ArrayList;
import java.util.List;
/**
*
* @author jmart
*/
public class PathActionMaker {
private final float[][] points;
private float speed = 0;
private final float rotationSpeed = 600;
private float[] screenSize;
/**
*
* @param points - all the path points that must be traversed
* @param duration - how long it should take to traverse the path points
* @param screenSize - the size of the screen
*/
public PathActionMaker(float[][] points, float duration, float[] screenSize) {
this.points = points;
this.speed = getSpeed(points, duration);
this.screenSize = screenSize;
}
/**
*
* @param speed - the speed at which the Actor should move traverse through
* all the points
* @param points - all the path points that must be traversed
* @param screenSize - the size of the screen
*/
public PathActionMaker(float speed, float[][] points, float[] screenSize) {
this.points = points;
this.speed = speed;
this.screenSize = screenSize;
}
/**
* The offsets are used to allow centering of an actor on the provided
* points.
*
* @param xOffset
* @param yOffset
* @param offScreenIndent number of pixels to move the actor out of screen
* when entering and leaving
* @return
*/
public SequenceAction getAction(float xOffset, float yOffset, float offScreenIndent) {
float[] prev = null;
float prevTheta = 0;
int i = 0;
SequenceAction seqAction = Actions.sequence();
boolean firstRotation = true;
float[][] fixedPoints = getOffSetFixedPoints(points, xOffset, yOffset, offScreenIndent);
for (float[] point : fixedPoints) {
float[] p = point;
if (prev == null) {
seqAction.addAction(Actions.moveTo(p[0], p[1]));
} else {
float dist = MathUtils.getDistance(prev[0], prev[1], p[0], p[1]);
float time = dist/speed;
float theta = MathUtils.angle(prev[0], prev[1], p[0], p[1]) + 90;
if (theta > 360) {
theta -= 360;
}
float dTheta = Math.abs(prevTheta - theta);
float rotateDuration = dTheta/rotationSpeed;
// the first rotation should be immediate.
if (firstRotation) {
firstRotation = false;
seqAction.addAction(Actions.parallel(
Actions.moveTo(p[0], p[1], time),
Actions.rotateTo(theta)));//...rotation duration is 0, aka immediate
} else {
seqAction.addAction(Actions.parallel(
Actions.moveTo(p[0], p[1], time),
Actions.rotateTo(theta, rotateDuration)));
}
prevTheta = theta;
}
prev = p;
}
return seqAction;
}
public float[][] getOffSetFixedPoints(float[][] points, float xOffset, float yOffset, float offScreenIndent) {
List<Float[]> list = new ArrayList<>();
//apply offset indent at beginning of path
float[] p1 = points[0];
float[] p2 = points[1];
float slope = (p1[1] - p2[1])/(p1[0] - p2[0]);
float c = p1[1] - slope * p1[0];
if (p1[0] == 0) {
float x = -offScreenIndent;
float y = slope * x + c;
list.add(new Float[]{x - xOffset, y - yOffset});
} else if (p1[0] == screenSize[0]) {
float x = screenSize[0] + offScreenIndent;
float y = slope * x + c;
list.add(new Float[]{x - xOffset, y - yOffset});
} else if (p1[1] == 0) {
float y = -offScreenIndent;
float x = (y - c)/slope;
list.add(new Float[]{x - xOffset, y - yOffset});
} else if (p1[1] == screenSize[1]) {
float y = screenSize[1] + offScreenIndent;
float x = (y - c)/slope;
list.add(new Float[]{x - xOffset, y - yOffset});
}
//apply the remaining points
for (float[] point : points) {
float[] p = {point[0] - xOffset, point[1] - yOffset};
addPointToList(p, list);
}
//apply offscreen indent at end of path
float[] p4 = points[points.length - 1];
float[] p3 = points[points.length - 2];
slope = (p3[1] - p4[1])/(p3[0] - p4[0]);
c = p3[1] - slope * p3[0];
if (p4[0] <= 0) {
float x = -offScreenIndent;
float y = slope * x + c;
list.add(new Float[]{x - xOffset, y - yOffset});
} else if (p4[0] >= screenSize[0]) {
float x = screenSize[0] + offScreenIndent;
float y = slope * x + c;
list.add(new Float[]{x - xOffset, y - yOffset});
} else if (p4[1] <= 0) {
float y = -offScreenIndent;
float x = (y - c)/slope;
list.add(new Float[]{x - xOffset, y - yOffset});
} else if (p4[1] >= screenSize[1]) {
float y = screenSize[1] + offScreenIndent;
float x = (y - c)/slope;
list.add(new Float[]{x - xOffset, y - yOffset});
}
//convert list to float[][]
float[][] rv = new float[list.size()][];
int i = 0;
for (Float[] p : list) {
float[] j = new float[2];
j[0] = p[0];
j[1] = p[1];
rv[i++] = j;
}
return rv;
}
private static void addPointToList(float[] point, List<Float[]> list) {
list.add(new Float[]{point[0], point[1]});
}
private float getSpeed(float[][] points, float duration) {
//speed = distance/time
float distance = MathUtils.getDistance(points);
return distance/duration;
}
}
私はあなたの例を簡単に実行したいと考えていました。 'Demo'クラスのソースコードを提供することができますか?その2つの多くの依存関係はありますか? – DavidS
これは私がgithubに載せた小さなサンドボックスの一部です:https://github.com/madigan/gdx-sandbox – John
しかし、PathDemo.javaがやっていることはほとんどすべてコピーとコピーが可能ですGameを継承したり、ApplicationListenerを実装したりするクラスにペーストされ、ちょっと微調整しても動作します。 – John