java 在线性路径中从点到点移动对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7448729/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 20:01:34  来源:igfitidea点击:

moving an object from point to point in a linear path

javaalgorithmcoordinatesgame-physicspathing

提问by Shizumaru18

I'm trying to move a sprite across the screen in a straight line, towards on the location where've I touched the screen, what i did was upon the update() in each loop , it checks to see if the current sprite's location x y is == to the destination x ,y . if it hasn't sprite's x++ and y++... the thing is ..it ain't moving in a straight line... as there are cases where the x or y coordinate reaches the destination x or y first... how do i changed it so that the both x and y meets the destination together?

我试图在屏幕上直线移动精灵,朝向我触摸屏幕的位置,我所做的是在每个循环中的 update() 上,它检查当前精灵的位置xy 是 == 到目的地 x ,y 。如果它没有精灵的 x++ 和 y++ ......事情是......它不会沿直线移动......因为在某些情况下,x 或 y 坐标首先到达目的地 x 或 y ......如何我是否更改它以便 x 和 y 一起到达目的地?

my current pseudo code for the sprite object

我当前的精灵对象伪代码

             destX = destination X
             destY = destination Y

             posX = current X
             posY = current Y
               public void update(){
                if(destX > posX && destY < posY)
                {

                    posX++;
                    posY--;
                }
                else if (destX > posX && destY > posY){
                    posX++;
                    posY++;
                }
                else if(destX < posX && destY > posY)
                {
                    posX--;
                    posY++;
                }
                else if(destX < posX && destY < posY){
                    posX--;
                    posY--;
                }
                else if(destX < posX)
                    posX--;
                else if(destX > posX)
                    posX++;
                else if(destY < posY)
                    posY--;
                else if(destY > posY)
                    posY++;

回答by Josh

Check out: http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm

查看:http: //en.wikipedia.org/wiki/Bresenham%27s_line_algorithm

This simple algorithm will tell you each X,Y coordinate on a line between two points. You could use this algorithm to compute all of the positions it needs to visit, store the coordinates in an array, and iterate over the array as you update the position.

这个简单的算法会告诉你两点之间一条线上的每个 X、Y 坐标。您可以使用此算法来计算它需要访问的所有位置,将坐标存储在一个数组中,并在更新位置时迭代该数组。

From the Article:

从文章:

  function line(x0, x1, y0, y1)
         int deltax := x1 - x0
         int deltay := y1 - y0
         real error := 0
         real deltaerr := abs (deltay / deltax)    // Assume deltax != 0 (line is not vertical),
               // note that this division needs to be done in a way that preserves the fractional part
         int y := y0
         for x from x0 to x1
             plot(x,y)
             error := error + deltaerr
             if error ≥ 0.5 then
                 y := y + 1
                 error := error - 1.0

This is the most primitive version. The article contains a better generalized algorithm that you should look at.

这是最原始的版本。这篇文章包含一个更好的泛化算法,你应该看看。

回答by J. Rahmati

I am dealing with a similair problem as yours. (I have an arraylist holding the history of positions my player has gone and I want to use that to rewind the game.) Instead of simply increasing x and y position with 1 you can:

我正在处理和你一样的问题。(我有一个 arraylist 保存了我的玩家已经离开的位置的历史记录,我想用它来倒带游戏。)而不是简单地用 1 增加 x 和 y 位置,你可以:

  1. Calculate the angle between the source postion and your destination position.
  2. Calculate the new direction using a variable which represents the speed
  3. Update your postion using calculated direction
  1. 计算源位置和目标位置之间的角度。
  2. 使用代表速度的变量计算新方向
  3. 使用计算的方向更新您的位置

I made a class of that. I hope it is usefull.

我做了一个类。我希望它有用。

import java.awt.geom.Point2D;

public class MyVelocityCalculator {

    public static void main(String[] args) {
        Point2D.Double currentPosition = new Point2D.Double();
        Point2D.Double destinationPosition = new Point2D.Double();
        currentPosition.setLocation(100, 100);
        destinationPosition.setLocation(50, 50);
        Double speed = 0.5;
        Point2D.Double nextPosition = MyVelocityCalculator.getVelocity(currentPosition, destinationPosition, speed); 

        System.out.println("player was initially at: "+currentPosition);
        System.out.println("player destination is at: "+destinationPosition);
        System.out.println("half seconds later player should be at: "+nextPosition);

    }

    public static final Point2D.Double getVelocity(Point2D.Double currentPosition, Point2D.Double destinationPosition, double speed){
        Point2D.Double nextPosition = new Point2D.Double();
        double angle = calcAngleBetweenPoints(currentPosition, destinationPosition);
        double distance = speed;
        Point2D.Double velocityPoint = getVelocity(angle, distance);
        nextPosition.x = currentPosition.x + velocityPoint.x;
        nextPosition.y = currentPosition.y + velocityPoint.y;
        return nextPosition;
    }

    public static final double calcAngleBetweenPoints(Point2D.Double p1, Point2D.Double p2)
    {
        return Math.toDegrees( Math.atan2( p2.getY()-p1.getY(), p2.getX()-p1.getX() ) );
    }

    public static final Point2D.Double getVelocity(double angle, double speed){
        double x = Math.cos(Math.toRadians(angle))*speed;
        double y = Math.sin(Math.toRadians(angle))*speed;
        return (new Point2D.Double(x, y));
    }
}

回答by Martijn Courteaux

Don't use integers. This is a very bad idea to work with ints. Use floats. The main concept is: define the number of steps you want to perform (s). Compute differences in X and Y (diffXand diffY). Don't take absolute values: Compute them this way

不要使用整数。使用整数是一个非常糟糕的主意。使用浮动。主要概念是:定义要执行的步骤数(s)。计算 X 和 Y (diffXdiffY) 的差异。不要取绝对值:以这种方式计算它们

float diffX = destX - currentX;

Then compute the xMove and yMove values by dividing diffXand diffYby s(number of steps).

然后通过除以diffXdiffY除以s(步数)来计算 xMove 和 yMove 值。

float moveX = diffX / s;
float moveY = diffY / s;

And now you have to add for each iteration the moveX and moveY values to the current position.

现在您必须为每次迭代将 moveX 和 moveY 值添加到当前位置。

And for drawing it, you should use Graphics2D, which supports floating points. If you don't want to use Graphics2D, you can round the floats to ints, using Math.round(float).

对于绘制它,您应该使用Graphics2D,它支持浮点数。如果您不想使用 Graphics2D,您可以使用Math.round(float).