2016-11-29 12 views
2

JavaFXからlibGDXへ移行中です。 libGDXにPathTransitionと同等のものがあるかどうかわかりません。libGDXには、JavaFXのPathTransitionに相当するものがありますか?

PathTransitionについて特に気になるものは、Pathを通過する間にノードをそれに応じて回転させることです。 PathTransitionについては、速度を自分で計算する必要があるということです。つまり、トラバーサルを完了するためにどれくらい時間がかかりますが、パスの長さを把握して適切な時間を設定できるようにする必要があります。

libGDXには、PathTransitionの改良されたバージョンと似たような機能があります。

答えて

1

あなたが投稿した例によると、私はlibGDXに相当するの直接に相当するとは思っていませんが、私たちはそれを作ることができます。

libGDXには、Scene2dというシーングラフが付属しており、アクタやアクターのグループにアクションを適用できます。組み込みのアクション(MoveTo、RotateBy)があり、それらを互いに並列に、または順次実行することができます。また、トゥイーンにはInterpolationクラスを適用することもできます。

libGDXもPathインターフェースが付属していますが、1.9.4のようPathActionはありませんが、それはあなたが以下のような何かを構築することはできませんという意味ではありません:だから

package tech.otter.gdxsandbox.demos; 

import com.badlogic.gdx.graphics.g2d.Batch; 
import com.badlogic.gdx.graphics.glutils.ShapeRenderer; 
import com.badlogic.gdx.math.CatmullRomSpline; 
import com.badlogic.gdx.math.Path; 
import com.badlogic.gdx.math.Vector2; 
import com.badlogic.gdx.scenes.scene2d.Action; 
import com.badlogic.gdx.scenes.scene2d.Actor; 
import com.badlogic.gdx.scenes.scene2d.Stage; 

public class PathDemo extends Demo { 
    private ShapeRenderer sr; 
    private Stage stage; 

    public PathDemo() { 
     super("Action Demo"); 
     stage = new Stage(); 
    } 

    @Override 
    public void show() { 
     sr = new ShapeRenderer(); 
     Actor ourCircle = new SimpleCircleActor(sr, 10f); 
     stage.addActor(ourCircle); 

     ourCircle.addAction(new PathAction(5f, 50f, 50f, 100f, 60f, 300f, 200f, 100f, 400f)); 
    } 

    @Override 
    public void render(float delta) { 
     sr.setAutoShapeType(true); 
     sr.begin(); 
     sr.set(ShapeRenderer.ShapeType.Filled); 
     stage.act(delta); 
     stage.draw(); 
     sr.end(); 
    } 

    @Override 
    public void dispose() { 
     stage.dispose(); 
     sr.dispose(); 
    } 

    private class SimpleCircleActor extends Actor { 
     private ShapeRenderer renderer; 
     private float radius; 

     public SimpleCircleActor(ShapeRenderer renderer, float radius) { 
      this.renderer = renderer; 
      this.radius = radius; 
     } 

     /** 
     * Assumes something outside is setting the ShapeRenderer type/begin/end. 
     * Don't do this at home, kids. 
     */ 
     @Override 
     public void draw(Batch batch, float delta) { 
      renderer.circle(this.getX(), this.getY(), this.radius); 
     } 
    } 

    private class PathAction extends Action { 
     private Path<Vector2> path; 
     private float current; 
     private float duration; 
     public PathAction(float duration, float... coordinates) { 
      this.duration = duration; 
      this.current = 0; 

      Vector2[] dataSet = new Vector2[coordinates.length/2]; 
      for(int i = 0; i < dataSet.length; i++) { 
       dataSet[i] = new Vector2(coordinates[2*i], coordinates[2*i+1]); 
      } 
      this.path = new CatmullRomSpline<Vector2>(dataSet, true); 
     } 
     @Override 
     public boolean act(float delta) { 
      if(duration == current) return true; // The action has already completed. 

      if(current + delta >= duration) { 
       current = duration; 
      } else { 
       current += delta; 
      } 

      Vector2 out = new Vector2(); // Get our position on the path. 
      this.path.valueAt(out, current/duration); 
      this.actor.setPosition(out.x, out.y); 

      return duration == current; // Return whether we are now complete. 
     } 
    } 
} 
+0

私はあなたの例を簡単に実行したいと考えていました。 'Demo'クラスのソースコードを提供することができますか?その2つの多くの依存関係はありますか? – DavidS

+1

これは私がgithubに載せた小さなサンドボックスの一部です:https://github.com/madigan/gdx-sandbox – John

+0

しかし、PathDemo.javaがやっていることはほとんどすべてコピーとコピーが可能ですGameを継承したり、ApplicationListenerを実装したりするクラスにペーストされ、ちょっと微調整しても動作します。 – John

0

を私はそれを働かせた。以下のクラスは、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; 
    } 

} 
関連する問題