沿直线(通过路径?)

时间:2010-11-04 21:50:59

标签: android path coordinate-systems

我正在开发一种使用射弹的游戏。所以我制作了一个Projectile类,当用户触摸屏幕时会创建一个新实例:

@Override
public boolean onTouch(View v, MotionEvent e){
    float touch_x = e.getX();
    float touch_y = e.getY();
    new Projectile(touch_x, touch_y);
}

和弹丸类:

public class Projectile{

    float target_x;
    float target_y;
    Path line;

    public Projectile(float x, float y){
        target_x = x;
        target_y = y;

        line = new Path();
        line.moveTo(MyGame.mPlayerXPos, MyGame.mPlayerYPos);
        line.lineTo(target_x, target_y);
    }
}

所以这会产生一个2点的路径,玩家的位置和触摸坐标。我的问题是 - 你怎么能在这条线上获得积分?例如,如果我想在线的半点获得弹丸的x,y坐标,或者弹丸在100个刻度之后的位置(以X像素/刻度的速度移动)?

我还需要Projectile在到达最终点后继续移动..我是否需要使用line.addPath(line)来继续扩展路径?

修改

我设法使弹丸沿直线移动,但它们朝着奇怪的方向前进。我不得不捏造一些代码:

private void moveProjectiles(){
        ListIterator<Projectile> it = Registry.proj.listIterator();
        while ( it.hasNext() ){
            Projectile p = it.next();
            p.TimeAlive++;

            double dist = p.TimeAlive * p.Speed;
            float dx = (float) (Math.cos(p.Angle) * dist);
            float dy = (float) (Math.sin(p.Angle) * dist);

            p.xPos += dx;
            p.yPos += -dy;
        }
    }

Angle一定是问题..我正在使用这种方法,它完美地运作:

private double getDegreesFromTouchEvent(float x, float y){
        double delta_x = x - mCanvasWidth/2;
        double delta_y = mCanvasHeight/2 - y;
        double radians = Math.atan2(delta_y, delta_x);

        return Math.toDegrees(radians);
    }

然而,对于屏幕中心上方的触摸,它返回0-180,对于下面的触摸,它返回0到-180。这是一个问题吗?

3 个答案:

答案 0 :(得分:2)

对此进行建模的最佳方法是使用parametric equations。无需使用trig函数。

class Path {
  private final float x1,y1,x2,y2,distance;

  public Path( float x1, float y1, float x2, float y2) {
    this.x1 = x1;
    this.y1 = y1;
    this.x2 = x2;
    this.y2 = y2;
    this.distance = Math.sqrt( (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
  }

  public Point position( float t) {
     return new Point( (1-t)*x1 + t*x2,
                       (1-t)*y1 + t*y2);
  }

  public Point position( float ticks, float speed) {
    float t = ticks * speed / distance;
    return position( t); 
  }

}

Path p = new Path(...);
// get halfway point
p.position( 0.5);
// get position after 100 ticks at 1.5 pixels per tick
p.position( 100, 1.5);

答案 1 :(得分:1)

从几何图形中,如果是直线,则可以使用极坐标计算其上的任何点。

如果找到线的角度:

ang = arctan((target_y - player_y) / (target_x - player_x))

然后可以使用trig:

找到线上的任何点
x = cos(ang) * dist_along_line
y = sin(ang) * dist_along_line

如果您想要中点,那么您只需将dist_along_line设为该线长度的一半:

dist_along_line = line_length / 2 = (sqrt((target_y - player_y)^2 + (target_x - player_x)^2)) / 2

如果你想考虑100个刻度后的点,以X像素/刻度的速度移动:

dist_along_line = 100 * X

希望有人可以使用android libs更直接地评论一种方法。

答案 2 :(得分:0)

首先,Path类用于绘制,而不是用于计算射弹位置。

因此,您的Projectile类可以具有以下属性:

float positionX;
float positionY;
float velocityX;
float velocityY;

速度是从targetX,targetY,playerX和playerY计算的,如下所示:

float distance = sqrt(pow(targetX - playerX, 2)+pow(targetY - playerY, 2))
velocityX = (targetX - playerX) * speed / distance;
velocityY = (targetY - playerY) * speed / distance;

你在20个滴答之后的位置是

x = positionX + 20 * velocityX;
y = positionY + 20 * velocityY;

到达terget所需的时间是     ticksToTarget =距离/速度;

halp way point的位置是

halfWayX = positionX + velocityX * (tickToTarget / 2);
halfWayY = positionY + velocityY * (tickToTarget / 2);