代码之家  ›  专栏  ›  技术社区  ›  Snailer

沿着直线(通过路径?)

  •  1
  • Snailer  · 技术社区  · 15 年前

    @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像素/拍的速度移动)?

    我还需要子弹在到达终点后继续移动。。我需要使用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 回复  |  直到 15 年前
        1
  •  2
  •   Jon Snyder    15 年前

    最好的建模方法是 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);
    
        2
  •  1
  •   Zack Bloom    15 年前

    从几何学上讲,如果它是一条直线,你可以用极坐标计算它上的任何一点。

    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 = line_length / 2 = (sqrt((target_y - player_y)^2 + (target_x - player_x)^2)) / 2
    

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

    dist_along_line = 100 * X
    

    希望有人能评论一种更直接使用android libs的方法。

        3
  •  0
  •   Ivo Bosticky    15 年前

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

    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;
    

    到达特吉的时间是

    停靠点位置为

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