1

我正在开发一款将使用射弹的游戏。因此,我创建了一个 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);
}

还有 Projectile 类:

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 个点的路径,即玩家的位置和触摸坐标。我的问题是 - 你如何访问这条线上的点?例如,如果我想在直线的半点处获得 Projectile 的 x、y 坐标,或者 Projectile 在 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。这是一个问题吗?

4

3 回答 3

3

对此进行建模的最佳方法是使用参数方程。无需使用三角函数。

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);
于 2010-11-04T22:13:06.127 回答
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 库更直接地执行此操作的方法。

于 2010-11-04T22:00:47.340 回答
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 = distance / velocity;

中途点的位置是

halfWayX = positionX + velocityX * (tickToTarget / 2);
halfWayY = positionY + velocityY * (tickToTarget / 2);
于 2010-11-04T22:20:38.997 回答