[英]Using the thread.sleep method in painting
我有一个工作代码,基本上可以在屏幕上绘制15个矩形,您可以在其中拖动。 我这样做是为了使矩形随着时间的流逝落在屏幕的底部。 当我使用thread.sleep方法时,可以使用较大的数字(例如500),但是当矩形掉落时,我仍然可以在屏幕上拖动矩形,没有问题。 但是随着我开始将thread.sleep方法减少到较小的数字(例如50),突然出现了问题。 诸如此类的问题,例如,我只能将最多2个矩形拖到矩形上,然后再开始将其拖回我没有拖动它们的地方。 有时,我最多只能拖动一个矩形,一旦选择了该矩形,便无法选择其他任何矩形进行拖动。 我知道我的代码绝对正确,因为它可以在thread.sleep方法使用较大数字时起作用,所以我的问题是:当我将thread.sleep设置为较小数字时,为什么它会开始出现毛刺? 这是我的代码的一部分。
while (true) {
for (int i = 0; i < 15; i++) {
P.fY[i]++;
}
Thread.sleep(500);
frame.repaint();
} //the 15 stands for 15 rectangles, and the P.fY stands for the position of y.
因此,根据您的评论,您似乎真的需要帮助弄清楚如何根据时间来计算距离。
通过每帧增加1
个循环,您实际上是在说每个方块的速度是1 pixel / 1 frame
。
取而代之的是,您应该利用时间并通过时间的函数来更新距离,以使其为1 pixel / unit of time
。 这意味着方格的速度将独立于每秒的帧数。
我整理了一个代码示例。 重要的方法是Square#doUpdate()
方法。 这恰好与您要查找的内容有关。
它遵循的过程是:
- 计算上一次更新的时间,并将其存储在
delta
。- 将上次更新的时间更新为当前时间
- 计算
deltaX
,即deltaX = delta * velocityX
- 计算
deltaY
,即deltaY = delta * velocityY
- 将
deltaX
添加到x
这将更新x
坐标- 向
y
添加deltaY
这将更新y
坐标
代码如下:
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.WindowConstants;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.LinkedList;
/**
* @author Obicere
*/
public class MovingSquare {
private volatile int viewportWidth;
private volatile int viewportHeight;
private final LinkedList<Square> squares = new LinkedList<>();
public MovingSquare() {
final JFrame frame = new JFrame("Moving Square");
final JPanel displayPanel = new JPanel() {
@Override
protected void paintComponent(final Graphics g) {
synchronized (squares) {
for (final Square square : squares) {
// Update the square's locations, ideally this will
// be separate of the painting thread
square.doUpdate();
final int x = (int) square.getX();
final int y = (int) square.getY();
g.setColor(square.getColor());
g.drawRect(x, y, square.squareSize, square.squareSize);
}
}
}
};
displayPanel.addMouseListener(new MouseAdapter() {
@Override
public void mouseReleased(final MouseEvent e) {
final Color nextColor = Color.getHSBColor((float) Math.random(), 1, 0.5f);
final float speedX = (float) Math.random();
final float speedY = (float) Math.random();
synchronized (squares) {
final Square newSquare = new Square(nextColor, speedX, speedY);
squares.add(newSquare);
newSquare.x = e.getX();
newSquare.y = e.getY();
}
}
});
displayPanel.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
viewportWidth = displayPanel.getWidth();
viewportHeight = displayPanel.getHeight();
}
});
final Timer repaintTimer = new Timer(20, null);
repaintTimer.addActionListener(e -> {
if (!frame.isVisible()) {
repaintTimer.stop();
return;
}
frame.repaint();
});
repaintTimer.start();
displayPanel.setPreferredSize(new Dimension(200, 200)); // Sorry MadProgrammer
frame.add(displayPanel);
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(final String[] args) {
SwingUtilities.invokeLater(MovingSquare::new);
}
private class Square {
private final int squareSize = 25;
private volatile float x;
private volatile float y;
private volatile long lastUpdateTime;
private volatile boolean negateX;
private volatile boolean negateY;
private final float speedX;
private final float speedY;
private final Color color;
public Square(final Color color, final float speedX, final float speedY) {
this.color = color;
this.speedX = speedX;
this.speedY = speedY;
lastUpdateTime = System.currentTimeMillis();
}
/**
* Important method here!!
* <p>
* This updates the location of the squares based off of a set
* velocity and the difference in times between updates.
*/
public void doUpdate() {
// Gets the change in time from last update
final long currentTime = System.currentTimeMillis();
final long delta = currentTime - lastUpdateTime;
if (delta == 0) {
return;
}
// be sure to update the last time it was updated
lastUpdateTime = currentTime;
// Calculate the speed based off of the change in time
final float deltaX = getSpeedX(delta);
final float deltaY = getSpeedY(delta);
// Move each square by the change of distance, calculated from
// the change in time and the velocity.
final float nextX = x + deltaX;
final float nextY = y + deltaY;
handleBouncing(nextX, nextY);
}
private void handleBouncing(final float nextX, final float nextY) {
if (nextX < 0) {
x = 0;
flipX();
} else if (nextX + squareSize >= viewportWidth) {
x = viewportWidth - squareSize;
flipX();
} else {
x = nextX;
}
if (nextY < 0) {
y = 0;
flipY();
} else if (nextY + squareSize >= viewportHeight) {
y = viewportHeight - squareSize;
flipY();
} else {
y = nextY;
}
}
private float getSpeedX(final long delta) {
return (negateX ? -1 : 1) * delta * speedX;
}
private float getSpeedY(final long delta) {
return (negateY ? -1 : 1) * delta * speedY;
}
protected void flipX() {
negateX = !negateX;
}
protected void flipY() {
negateY = !negateY;
}
public float getX() {
return x;
}
public float getY() {
return y;
}
public Color getColor() {
return color;
}
}
}
它的作用:
这似乎有点令人不知所措。 逐步执行,更改一些内容。 发疯,看看结果如何。
也有一些网站可以帮助提高速度以及如何计算这样的事情。 如果您需要进一步的帮助,只需在下面添加评论,我会做什么。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.