2016-04-20 75 views
0

你好同胞程序员,JavaFX localToScene会导致结果变大一倍 - 为什么?

我目前正在为我的研究写一个小型图形应用程序,应该在小2D游戏中展示AI。尽管现在我有点困难。 我已经在顶部用Entity做了一个类层次结构来基本上代表任何实体,如玩家,敌人和障碍物,它具有一个Node属性,它应该以图形方式表示实体。实体还具有两个受保护的SimpleIntegerProperty对象x和y,我将绑定Node属性的布局属性,以便每当更改x和y的值时,图形表示也会移动。

到目前为止,我可以做任何不依赖实体对象坐标的事情。 Collision works etc. 但是,当我试图在玩家角色所在的位置(x和y属性的值)生成子弹(小圆对象)的系统时,出现了双倍距离的奇怪偏移量玩家必须到左上角(到右下角)。我进行了一些尝试,看到当我通过localToScene方法检查坐标时,通过两个属性的值或者直接使用Node的layoutX和layoutY方法,它会给我坐标TWICE AS BIG作为实际坐标。 我的窗格大小为600x600像素,当我将我的播放器(另一个延伸到实体的对象)放在300,300处时,一切看起来都很好,但localToScene方法显然告诉我它是这个的两倍,所以600,600。当我将玩家带到右下角​​并通过localToScene打印坐标时,它告诉我它在1200,1200。

public void addProjectile(Projectile p) 
{ 
    Projectile p2 = new PlayerProjectile(100, 100, 0.5); 
    projectiles.add(p2); 
    System.out.println(p2.getSkin().localToScene(p2.getX(), p2.getY())); 
    System.out.println(p2.getSkin().getLayoutX() + " " + p2.getSkin().getLayoutY()); 
    this.getChildren().add(p2.getSkin()); 
    System.out.println(p2.getSkin().getLayoutX() + " " + p2.getSkin().getLayoutY()); 

// p.setPosition(p.getSkin().localToScreen(p.getX(), p.getY())); 

} 

该方法在100,100处创建了子弹(布局X和Y也证实了这一点)。然后,我将这个Projectile p2添加到一个ArrayList(不重要)。 第一次打印给了我两个坐标,200和200. 第二次打印给了我100和100. 第三次打印也给了我100和100(此外,这是一个窗格,不会改变任何东西显然并不是原因)。

有没有人有线索为什么它只是双打一切?这里是每个相关的类。

PlayerProjectile类:

public class PlayerProjectile extends Projectile 
{ 

public static final int FIRE_RATE = 5; // Higher is slower 

public PlayerProjectile(int x, int y, double dir) 
{ 

    super(x, y, dir); 
    range = 150; 
    speed = 4; 
    damage = 20; 

    nx = (int) (speed * Math.cos(angle)); 
    ny = (int) (speed * Math.sin(angle)); 

} 

@Override 
public void update() 
{ 

    move(); 

} 

@Override 
protected void move() 
{ 
    x.setValue(x.getValue() + nx); 
    y.setValue(y.getValue() + ny); 

    // if (distance() > range) 
    // { 
    // remove(); 
    // } 
} 
} 

弹丸类:

public abstract class Projectile extends Entity 
{ 
final protected int xOrigin, yOrigin; 

protected double angle; 

protected int nx, ny; 

protected double distance; 

protected double speed, range, damage; 

public Projectile(int x, int y, double dir) 
{ 
    super(x, y); 
    skin = new Circle(x, y, 3); 
    ((Circle) skin).setFill(new Color(0, 1, 0, 1)); 
    xOrigin = x; 
    yOrigin = y; 
    angle = dir; 
    // this.getVisual().translateXProperty().bind(this.x); 
    // this.getVisual().translateYProperty().bind(this.y); 
    this.getSkin().layoutXProperty().bind(this.x); 
    this.getSkin().layoutYProperty().bind(this.y); 
    // this.getVisual().getChildren().add(skin); 
} 

protected void move() 
{ 

} 

public int getX() 
{ 
    return x.getValue().intValue(); 
} 

public int getY() 
{ 
    return y.getValue().intValue(); 
} 

public int getOriginX() 
{ 
    return xOrigin; 
} 

public int getOriginY() 
{ 
    return yOrigin; 
} 
} 

实体类:

public class Entity 
{ 
private boolean removed = false; 

protected Level level; 

protected Node skin; 

// PROPERTIES FÜR X UND Y KOORDINATEN DES SKINS DES SPIELERS 
protected SimpleIntegerProperty x, y; 

// VISUELLE REPRÄSENTATION DER ENTITY 
// protected Pane visual = new Pane(); 

public Entity() 
{ 

} 

public Entity(int x, int y) 
{ 
    this.x = new SimpleIntegerProperty(x); 
    this.y = new SimpleIntegerProperty(y); 

} 

public void update() 
{ 

} 

public void remove() 
{ 
    // Remove from level 
    removed = true; 
} 

public void setX(int x) 
{ 
    this.x.setValue(x); 
} 

public void setY(int y) 
{ 
    this.y.setValue(y); 
} 

public void setPosition(Point2D p) 
{ 
    this.setX((int) p.getX()); 
    this.setY((int) p.getY()); 
} 

public boolean isRemoved() 
{ 
    return removed; 
} 

public void init(Level level) 
{ 
    this.level = level; 
} 

// public Pane getVisual() 
// { 
// return visual; 
// } 

public Node getSkin() 
{ 
    return skin; 
} 

} 

回答

0

localToScene从局部坐标系转换到现场协调。本地坐标是相对于该方法所要求的节点的原点。该转换已包括此节点的layoutXlayoutY。因此给予P = (layoutX, layoutY)你得到的结果是

Inverse(sceneToLocal) * P = Inverse(Inverse(nodeTransform)) * P 
          = Inverse(Inverse(Translation(P))) * P 
          = Translation(P) * P 
          = 2 * P 

变换原点的局部坐标系中,而不是得到的实际位置:

p.setPosition(p.getSkin().localToScreen(0, 0)); 
+0

感谢您的回答,但我还没有经过真正见过还没完成。 当我用你建议的替换第一个打印图像时,我得到(0,0)的值,尽管在视觉上弹丸产生在100,100处,如参数给出的那样。 我想我仍然不完全了解管道是如何工作的。 – Grougal

+0

我的错。 AFAIK节点当时没有添加到它的父节点。 – fabian

+0

嗯,我现在很困惑。 我现在正在尝试使用它,虽然localToScene(0,0)返回正确的值,但视觉上所有东西仍然是偏移的。 我需要做什么才能使用作为创建参数的值代表我将它们添加到的窗格坐标?如果窗格的大小是600x600,并且我希望弹丸的数量为300,300,我想给构造函数300和300作为参数,并且它的视觉效果也是300,300。 – Grougal