在线性路径上将物体从一点移动到另一点

发布于 2024-12-05 01:12:37 字数 1265 浏览 1 评论 0原文

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

我当前的精灵对象的伪代码

             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++;

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?

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++;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

旧梦荧光笔 2024-12-12 01:12:37

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

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

摘自文章:

  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

这是最原始的版本。本文包含您应该查看的更好的通用算法。

Check out: 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.

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.

雨后彩虹 2024-12-12 01:12:37

我正在处理与你类似的问题。 (我有一个数组列表,保存我的玩家所走位置的历史记录,我想用它来倒带游戏。)
而不是简单地将 x 和 y 位置增加 1

  1. 您可以:计算源位置和目的地之间的角度,
    位置。
  2. 使用变量计算新方向
    代表速度
  3. 使用计算出的方向更新你的位置

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

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

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:

  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));
    }
}
梦在夏天 2024-12-12 01:12:37

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

float diffX = destX - currentX;

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

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

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

为了绘制它,您应该使用支持浮点的Graphics2D。如果您不想使用 Graphics2D,则可以使用 Math.round(float) 将浮点数舍入为整数。

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 (diffX and diffY). 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).

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.

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).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文