简体   繁体   English

在线性路径中将对象从一个点移动到另一个点

[英]moving an object from point to point in a linear path

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 xy is == to the destination x ,y . 我试图在屏幕上直线移动一个精灵,朝着我触摸屏幕的位置,我做的是在每个循环中更新(),它检查当前精灵的位置xy = =到目的地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? 如果它没有精灵的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++;

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

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. 本文包含一个更好的通用算法,您应该看一下。

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 使用计算出的方向更新您的位置

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));
    }
}

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 ). 主要概念是:定义要执行(步数s )。 Compute differences in X and Y ( diffX and diffY ). 计算X和Y的差异( diffXdiffY )。 Don't take absolute values: Compute them this way 不要采用绝对值:以这种方式计算它们

float diffX = destX - currentX;

Then compute the xMove and yMove values by dividing diffX and diffY by 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. 为了绘制它,你应该使用支持浮点的Graphics2D If you don't want to use Graphics2D, you can round the floats to ints, using Math.round(float) . 如果您不想使用Graphics2D,可以使用Math.round(float)将浮点数舍入为整数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM