将一个正方形从起点移动到以固定速度点击鼠标的位置 [英] Moving a square from a starting point to the position of a mouse click at a fixed speed

查看:117
本文介绍了将一个正方形从起点移动到以固定速度点击鼠标的位置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我点击时,我正试图将一个正方形从它的原始位置移动到我的鼠标坐标。我有点工作的代码,但广场不直接鼠标点击。它对角线有点偏离,然后进入鼠标点击,如图所示。我试图让它成为一条直线运动路径,但我想不出办法。我很确定错误与下面的第一种方法有关。

I'm trying to move a square from it's original position to the coordinates of my mouse when I click. The code I have somewhat works, but the square does not go directly to the mouse click. It goes diagonally a bit off, then it goes to the mouse click, as shown in the picture. I tried to make it a straight movement path but I could not think of a way to do so. I'm pretty sure the error is something to do with the 1st method below.

           ________X ← the mouse click
          /        
         /   ↑
        / ←  = movement path
       /
      /
_____/
|   | ← character
|___|

以下是迄今为止涉及的3种方法
(请不要批评我的代码太多)

Here are the 3 methods involved so far (pls dont criticize my code too much)

 //int x and int y are the positions of the mouse, champion = the character

public static Champion calculateChampionMovement(int x, int y, Champion champion) {

    if (x != champion.x || y != champion.y) {

         //x and y dist = the distance between the character and the cursor
        int xDist = x - champion.x;
        int yDist = y - champion.y;

         //the angle
        plrAngle = Math.atan2(yDist, xDist) * 180 / Math.PI;

         //the speed of the character on the x and y axis
         //(character diagonally moves at the speed of "champion.speed")
        plrXSpeed = champion.speed * Math.cos(plrAngle * Math.PI / 180);
        plrYSpeed = champion.speed * Math.sin(plrAngle * Math.PI / 180);

         //calls the method below that actually moves the character
        playerMain.champion = (Champion) Entity.moveChampions(x, y, champion, champion.speed, plrXSpeed, plrYSpeed);

        champion.moving = true;
    }
    return playerMain.champion;
}

第二个......

 //called by the method above
public static Entity moveChampions(int x, int y, Champion champion, float speed, double xSpeed, double ySpeed) {

     //if the distance between the character on the x and y axis is not
     //exactly divisible by "speed", then this helps the character stop.
    if (Math.abs(x - champion.x) <= speed) {
        champion.x = x;
    }
    if (Math.abs(y - champion.y) <= speed) {
        champion.y = y;
    }
     //stops the character
    if (x == champion.x && y == champion.y) {
        champion.moving = false;
    }
     //moves the character
    if (champion.moving) {
        champion.x += xSpeed;
        champion.y += ySpeed;
    }
    return champion;
}

最后一个方法调用calculateChampionMovement和moveChampions,它移动了移动为真的字符

The last method calls "calculateChampionMovement" and "moveChampions", and it moves the character while "moving" is true

public static void buttonTest() {
    if (RIGHTCLICK == true) {

         //mouse x and y positions
        cursorClickX = (int) (mapX + MOUSE_X);
        cursorClickY = (int) (mapY + MOUSE_Y);

         //first method (setup the x and y speed)
        playerMain.champion = PlayerMain.testMainChampionMove(cursorClickX, cursorClickY, playerMain.champion);

     // if character is already moving
    } else if (playerMain.champion.moving == true) {
         //move the character
        playerMain.champion = (Champion) Entity.moveChampions(cursorClickX, cursorClickY, playerMain.champion, champAsdf.speed, plrXSpeed, plrYSpeed);
    }
}

嗨暴乱游戏请不要起诉我太年轻了

hi riot games pls dont sue me im too young anyways

推荐答案

当遇到问题时,我倾向于回归基础知识,我该怎么做?

When faced with a problem, I tend to go back to basics, what do I know how to do?

我知道我可以:


  • 计算两点之间的距离

  • 在给定的持续时间内移动一个长一行的对象。

所以我们知道:


  • 起点

  • 终点

从这里我们可以计算两点之间的距离。

From this we can calculate the distance between the two points.

double distance = Math.sqrt(
                    (startX - targetX) * (startX - targetX)
                    + (startY - targetY) * (startY - targetY));

有了这个,我们可以根据所需的速度计算在两点之间行驶所需的时间

With this, we can calculate the time needed to travel between the two points based on the desired speed

time = distance / speed

其中 speed 是一个常量( 0.1 在我的示例中,使其变小以使其成为慢一点)

where speed is a constant (0.1 in my example, make it smaller to make it slower)

有了这些信息,我们知道我们必须走多长时间,我们可以根据我们开始时的差异计算沿线/路径的进度(当点击鼠标)现在。

With this information, we know how long we must travel for and we can calculate the progress along the line/path based on the difference between when we started (when the mouse was clicked) and now.

假设 startTime 是我们开始移动的时间, runningTime 是我们为了保持恒定速度而需要运行的时间

Assuming the startTime is the time that we started moving, runningTime is the amount of time we need to run for in order to maintain a constant speed

然后我们可以计算当前进度使用类似的东西......

Then we can calculate our current progress using something like...

long duration = System.currentTimeMillis() - startTime;
double progress = duration / runTime;

从此我们可以根据当前持续时间计算沿线的位置......

From this we can calculate the position along the line based on the current duration...

double x = (int) (startX + ((targetX - startX) * progress));
double y = (int) (startY + ((targetY - startY) * progress));

作为概念证明。对不起,您没有提到您正在使用的框架;)

As a proof of concept. Sorry, you didn't mention what framework your were using ;)

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class TestMove {

    public static void main(String[] args) {
        new TestMove();
    }

    public TestMove() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                    ex.printStackTrace();
                }

                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        private Rectangle champion;
        private Line2D path;

        private double speed = 0.1;

        private Timer timer;
        private Long startTime;

        private double targetX, targetY;
        private double startX, startY;
        private double runTime;

        public TestPane() {
            champion = new Rectangle(95, 95, 10, 10);

            addMouseListener(new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    timer.stop();
                    calculateChampionMovement(e.getX(), e.getY(), champion);
                    startTime = System.currentTimeMillis();
                    timer.start();
                }
            });

            timer = new Timer(40, new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    if (targetX == champion.getCenterX() && targetY == champion.getCenterY()) {
                        System.out.println("Stopped as same");
                        timer.stop();
                    }

                    long duration = System.currentTimeMillis() - startTime;
                    double progress = duration / runTime;

                    if (progress >= 1.0) {
                        System.out.println("Stopped out of time");
                        progress = 1.0;
                        timer.stop();
                    }

                    double x = (int) (startX + ((targetX - startX) * progress));
                    double y = (int) (startY + ((targetY - startY) * progress));

                    // x/y are the center points, need to adjust them so the shape
                    // moves about the center point
                    champion.setRect(x - 5, y - 5, 10, 10);

                    repaint();
                }
            });
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(200, 200);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.draw(champion);
            if (path != null) {
                g2d.setColor(Color.RED);
                g2d.draw(path);
            }
            g2d.dispose();
        }

        public void calculateChampionMovement(double x, double y, Rectangle champion) {

            if (x != champion.getCenterX() || y != champion.getCenterY()) {

                targetX = x;
                targetY = y;

                startX = champion.getCenterX();
                startY = champion.getCenterY();

                path = new Line2D.Double(
                                champion.getCenterX(),
                                champion.getCenterY(),
                                x, y);

                double distance = Math.sqrt(
                                (startX - targetX) * (startX - targetX)
                                + (startY - targetY) * (startY - targetY));

                runTime = distance / (double)speed;

            }
        }
    }

}

这篇关于将一个正方形从起点移动到以固定速度点击鼠标的位置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆