【问题标题】:Moving an object at a consistent speed from point A to B以恒定的速度将物体从 A 点移动到 B 点
【发布时间】:2019-07-31 14:48:58
【问题描述】:

我正在尝试创建自己的基于原始 2D 图形的游戏引擎。游戏的核心部分是向敌人发射不同的弹丸。我需要先让这个组件工作,然后才能继续工作。

现在我的弹丸沿着穿过起点 (x, y) 和目标点 (x1, x2) 的线移动。我利用线性函数y = mx + b。问题是我如何更新弹丸的位置会导致速度不一致,具体取决于线的斜率。 (更大的坡度会使其移动得更快)。

这是我正在运行的游戏循环的核心结构:

    private void executeGameLoop() 
    {

        long nextFrameStart = System.nanoTime();
        while(panel.getRunning()) 
        {
            do 
            {
                panel.update();
                nextFrameStart += FRAME_PERIOD;
            } while(nextFrameStart < System.nanoTime());

            long remaining = nextFrameStart - System.nanoTime();
            panel.repaint();

            if (remaining > 0) 
            {
                try 
                {
                    Thread.sleep(remaining / 1000000);
                } 
                catch(Throwable e) 
                {
                System.out.println(e.getMessage()); 
                }
            }
        }
    }

这只是更新结构和图形的机制。每次调用panel.update 时,弹丸都会在特定情况下更新其位置。以下是更新弹丸的方法:

这告诉射弹它有一个目标并设置有关线的信息。

public void setHasTarget(boolean hasTargetIn)
    {
        if(hasTargetIn)
        {
            deltaX = getTargetX() - getX();
            deltaY = getTargetY() - getY();
            slope = deltaY / deltaX;
            intercept = getY();
            System.out.println("y = " + slope + "x + " + intercept); //line the projectile will follow
        }
        hasTarget = hasTargetIn;
    }

此 next 方法将位置设置为行上的下一步。 (X 由速度更新,y 由 x 更新)

public void setNext()
        {
            float temp = (slope) * (getX() + velocity) + intercept;
            System.out.println("Slope: " + (slope) * (getX() + velocity));
            System.out.println("Current: (" + getX() + ", " + getY() + ")");
            System.out.println("Next: (" + (getX() + velocity)  + ", " + (getY() + temp) + ")");
            setX(getX() + velocity);
            setY(temp);
        }

最后一个方法调用setNext(),由主循环调用。

public void update()
        {
            if(hasTarget)
                setNext();
        }

正如我所说,鉴于我当前的代码,我运行时的结果是弹丸在屏幕上以不一致​​的速度移动,具体速度取决于线的斜率。我希望能够更改我的代码,以便弹丸在屏幕上以一致的速度在任何轨迹上移动。提前感谢您的帮助。

【问题讨论】:

    标签: java game-physics


    【解决方案1】:

    一般来说,处理定向运动的最佳方法是使用三角函数。 为此,您的弹丸需要两件事:方向(以弧度为单位)和速度。

    你需要的三个三角函数是 sin、cos 和 arctan

    更新您的 X:setX(getX() + (speed * Math.cos(direction)));

    更新您的 Y:setY(getY() + (speed * Math.sin(direction)));

    用于计算方向:Math.atan(slope)

    您应该将字段 directionspeed 添加到您的类中,并将它们声明为双精度。

    public void setHasTarget(boolean hasTargetIn)
    {
        if (hasTargetIn)
        {
            deltaX = getTargetX() - getX();
            deltaY = getTargetY() - getY();
            direction = Math.atan(deltaY / deltaX); // Math.atan2(deltaY, deltaX) does the same thing but checks for deltaX being zero to prevent divide-by-zero exceptions
            speed = 5.0;
        }
        hasTarget = hasTargetIn;
    }
    
    public void setNext()
    {
        setX(getX() + (speed * Math.cos(direction)));
        setY(getY() + (speed * Math.sin(direction)));
    }
    

    【讨论】:

    • 谢谢你,这工作或多或少完美。由于缺乏经验,我不愿意使用 trig,但我明白为什么这种方法要好得多。
    • 没问题。请注意:如果 deltaX 为 0,它将崩溃。将 Math.arctan(deltaY/deltaX) 替换为 Math.arctan2(deltaY, deltaX) 将防止这种情况发生。
    • 这实际上是我注意到的第一件事。另请注意,也许它是一种较旧的格式,但Math.arctan 应该是Math.atan。我的代码是:(float)Math.atan2(deltaY, deltaX)
    • 好收获。显然我最近一直在做太多的物理。 =) 我会改变的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-27
    • 1970-01-01
    相关资源
    最近更新 更多