Java 以固定速度将正方形从起点移动到鼠标单击的位置
当我点击时,我试图将一个正方形从它的原始位置移动到我鼠标的坐标。我的代码有些有用,但是方块不能直接点击鼠标。如图所示,它沿对角线移动一点,然后点击鼠标。我试着让它成为一条笔直的运动路线,但我想不出一个办法。我很确定这个错误与下面的第一个方法有关Java 以固定速度将正方形从起点移动到鼠标单击的位置,java,Java,当我点击时,我试图将一个正方形从它的原始位置移动到我鼠标的坐标。我的代码有些有用,但是方块不能直接点击鼠标。如图所示,它沿对角线移动一点,然后点击鼠标。我试着让它成为一条笔直的运动路线,但我想不出一个办法。我很确定这个错误与下面的第一个方法有关 ________X ← the mouse click / / ↑ / ← = movement path / / _____/
________X ← the mouse click
/
/ ↑
/ ← = movement path
/
/
_____/
| | ← character
|___|
以下是迄今为止涉及的3种方法
(请不要过分批评我的代码)
第二个
//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;
}
嗨,暴乱游戏,请不要起诉我,反正我太年轻了当我面临问题时,我倾向于回到基本面,我知道怎么做 我知道我可以:
- 计算两点之间的距离
- 在给定的持续时间内将对象移动一长行
- 起点
- 终点
double distance = Math.sqrt(
(startX - targetX) * (startX - targetX)
+ (startY - targetY) * (startY - targetY));
有了这个,我们可以根据期望的速度计算在两点之间行驶所需的时间
time = distance / speed
其中speed
是一个常数(0.1
在我的示例中,将其变小以使其变慢)
有了这些信息,我们知道我们必须旅行多长时间,我们可以根据开始(单击鼠标时)和现在之间的差异来计算路线/路径上的进度
假设startTime
是我们开始移动的时间,runningTime
是我们为了保持恒定速度而需要运行的时间量
然后我们可以用类似于
long duration = System.currentTimeMillis() - startTime;
double progress = duration / runTime;
由此,我们可以根据当前持续时间计算沿线位置
double x = (int) (startX + ((targetX - startX) * progress));
double y = (int) (startY + ((targetY - startY) * progress));
作为概念的证明。抱歉,您没有提到您使用的框架;)
使用毕达哥拉斯定理,我们可以计算距离die sqrt((targetx startx)^2+(target starty)^2) 用你的速度变量(我称之为V),我们可以计算时间变量T作为D/V,即速度上的距离 然后我们可以得到单独的x和y速度xdistance/T 和Y距离/T或(targetx startx)/T和(targety startat)/T (请注意,必须实现if T==0的异常以避免错误) 使用时间片段来计算x和y速度,使总速度保持不变,这在计算上是不必要的,唯一的好处是我们避免了除以零,但同样,这很容易用一个if语句(if(T!=0.0))解决
使用这种或类似的方法将使您的程序运行得更快,因为需要的计算更少。节省的时间太少,现代计算机无法察觉,但它使代码更干净。祝你的项目好运。考虑提供一份能证明你的问题的报告。这不是一个代码转储,而是您正在做的一个示例,它突出了您所遇到的问题。这将减少混乱和更好的响应“从我的头顶”-您需要计算在您想要移动的时间内您需要进行的垂直/水平移动量,并通过这些增量更新位置。为什么要将角度从rad转换为deg,反之亦然?它是关于
180
和Math.PI
你不认为你应该一次移动k个空格吗?。。。我想一定有一个循环。与距离相比,k的范围可能从1到任何一个非常小的数字。好的,下次我会做一个可运行的例子,谢谢你的建议。我只是好奇你是如何从swing窗口生成gif文件的?谢谢:)@Trickster我用的是跨平台和免费的;)-我很高兴它起作用了,因为我的数学理论糟透了;)
long duration = System.currentTimeMillis() - startTime;
double progress = duration / runTime;
double x = (int) (startX + ((targetX - startX) * progress));
double y = (int) (startY + ((targetY - startY) * progress));
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;
}
}
}
}