繁体   English   中英

在绘画中使用thread.sleep方法

[英]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()方法。 这恰好与您要查找的内容有关。

它遵循的过程是:

  1. 计算上一次更新的时间,并将其存储在delta
  2. 将上次更新的时间更新为当前时间
  3. 计算deltaX ,即deltaX = delta * velocityX
  4. 计算deltaY ,即deltaY = delta * velocityY
  5. deltaX添加到x这将更新x坐标
  6. 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;
        }

    }
}

它的作用:

抱歉,MadProgrammer,最初需要做首选尺寸

这似乎有点令人不知所措。 逐步执行,更改一些内容。 发疯,看看结果如何。

也有一些网站可以帮助提高速度以及如何计算这样的事情。 如果您需要进一步的帮助,只需在下面添加评论,我会做什么。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM