如何在 Java 中绘制以不同速度移动的多个对象?
Posted
技术标签:
【中文标题】如何在 Java 中绘制以不同速度移动的多个对象?【英文标题】:How do I paint multiple objetcs that move at different speeds in Java? 【发布时间】:2017-07-10 13:07:19 【问题描述】:我正在为课堂做作业,但已经很晚了,因为尽管我正在做所有的研究,但我似乎无法理解这些材料。我是初学者,对java的方式了解不多。另外,这是我的第一篇文章,所以请您在阅读本文时见谅。
我正在基于我的教科书的源代码进行构建,我最近为过去的作业进行了更新,但现在我正在尝试生成一个类,该类可以绘制多个正方形并以不同的速度独立移动这些对象。他们都需要从墙上反弹。我按照说明创建了两个数组,它们将随机 x 和 y 值保存在 1 到 10 之间。但是,我在处理数组时遇到了困难,而且我确信我没有正确地做到这一点。所以,我希望得到一些反馈,看看我的设置是否正确。
我有一个 jpanel 向上拉并绘图,只要有 1 个正方形,它就可以很好地从墙上弹起,但是当我绘制多个时情况会发生变化。它们不独立移动,它们也共享相同的速度。有些甚至不时消失。这真的让我失望了。感谢您的帮助!
简而言之,我正在尝试绘制新的正方形,它们都以不同的方向和不同的速度行进。根据说明,我们假设创建并使用两个数组来处理 x 和 y 值。
这是我目前所拥有的:
public class DotsPanel extends JPanel
private int delay = 15;
private final int SIZE = 7, IMAGE_SIZE = 3; // radius of each dot
private Timer timer;
private int x, y, i;
private ArrayList<Point> pointList;
static int [] xarray = new int [1000];
static int [] yarray = new int [1000];
Random rand = new Random();
//-----------------------------------------------------------------
// Constructor: Sets up this panel to listen for mouse events.
//-----------------------------------------------------------------
public DotsPanel()
pointList = new ArrayList<Point>();
int [] xarray = new int [1000];
int [] yarray = new int [1000];
timer = new Timer(delay, new ReboundListener());
addMouseListener (new DotsListener());
addMouseMotionListener (new DotsListener());
setBackground(Color.gray);
setPreferredSize(new Dimension(700, 500));
for(int i = 0; i < xarray.length; i++)
xarray[i] = rand.nextInt(7);
yarray[i] = rand.nextInt(7);
timer.start();
//-----------------------------------------------------------------
// Draws all of the dots stored in the list.
//-----------------------------------------------------------------
public void paintComponent(Graphics page)
super.paintComponent(page);
page.setColor(Color.BLUE);
for (Point spot : pointList)
page.fillRect(spot.x-SIZE, spot.y-SIZE, 25, 25);
page.drawString("Count: " + pointList.size(), 5, 15);
//*****************************************************************
// Represents the listener for mouse events.
//*****************************************************************
private class DotsListener implements MouseListener, MouseMotionListener
//--------------------------------------------------------------
// Adds the current point to the list of points and redraws
// the panel whenever the mouse button is pressed.
//--------------------------------------------------------------
public void mousePressed(MouseEvent event)
pointList.add(event.getPoint());
repaint();
public void mouseDragged(MouseEvent event)
// initially I had two xarray and yarray in here just like in
// mouseClicked
// but it did not change anything when removed
//--------------------------------------------------------------
// Provide empty definitions for unused event methods.
//--------------------------------------------------------------
public void mouseClicked(MouseEvent event)
xarray[i] = rand.nextInt(7);
yarray[i] = rand.nextInt(7);
public void mouseReleased(MouseEvent event)
public void mouseEntered(MouseEvent event)
public void mouseExited(MouseEvent event)
public void mouseMoved(MouseEvent e)
private class ReboundListener implements ActionListener
//--------------------------------------------------------------
// Updates the position of the image and possibly the direction
// of movement whenever the timer fires an action event.
//--------------------------------------------------------------
public void actionPerformed(ActionEvent event)
for (Point spot : pointList)
spot.x += xarray[i];
spot.y += yarray[i];
if (spot.x <= 0 || spot.x >= 700)
xarray[i] = xarray[i] * -1;
if (spot.y <= 0 || spot.y >= 500)
yarray[i] = yarray[i] * -1;
repaint();
【问题讨论】:
【参考方案1】:但是,我在数组方面遇到了困难,并且我确信我没有正确地做到这一点。
我不会使用数组。
相反,让Ball
对象管理自己的状态。然后你可以为每个Ball
设置不同的颜色、速度、大小等。然后当Timer
触发时,您只需计算新位置并重新绘制Ball
。
下面是一个帮助您入门的示例:
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.util.*;
import javax.swing.*;
import javax.swing.Timer;
public class BallAnimation4
private static void createAndShowUI()
BallPanel panel = new BallPanel();
JFrame frame = new JFrame("BallAnimation4");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add( panel );
frame.setSize(800, 600);
frame.setLocationRelativeTo( null );
//frame.setExtendedState(JFrame.MAXIMIZED_BOTH);
frame.setVisible( true );
panel.addBalls(5);
panel.startAnimation();
public static void main(String[] args)
EventQueue.invokeLater(new Runnable()
public void run()
createAndShowUI();
);
class BallPanel extends JPanel implements ActionListener
private ArrayList<Ball> balls = new ArrayList<Ball>();
public BallPanel()
setLayout( null );
setBackground( Color.BLACK );
public void addBalls(int ballCount)
Random random = new Random();
for (int i = 0; i < ballCount; i++)
Ball ball = new Ball();
ball.setRandomColor(true);
ball.setLocation(random.nextInt(getWidth()), random.nextInt(getHeight()));
ball.setMoveRate(32, 32, 1, 1, true);
// ball.setMoveRate(16, 16, 1, 1, true);
ball.setSize(32, 32);
balls.add( ball );
@Override
public void paintComponent(Graphics g)
super.paintComponent(g);
for (Ball ball: balls)
ball.draw(g);
public void startAnimation()
Timer timer = new Timer(75, this);
timer.start();
public void actionPerformed(ActionEvent e)
move();
repaint();
private void move()
for (Ball ball : balls)
ball.move(this);
class Ball
public Color color = Color.BLACK;
public int x = 0;
public int y = 0;
public int width = 1;
public int height = 1;
private int moveX = 1;
private int moveY = 1;
private int directionX = 1;
private int directionY = 1;
private int xScale = moveX;
private int yScale = moveY;
private boolean randomMove = false;
private boolean randomColor = false;
private Random myRand = null;
public Ball()
myRand = new Random();
setRandomColor(randomColor);
public void move(JPanel parent)
int iRight = parent.getSize().width;
int iBottom = parent.getSize().height;
x += 5 + (xScale * directionX);
y += 5 + (yScale * directionY);
if (x <= 0)
x = 0;
directionX *= (-1);
xScale = randomMove ? myRand.nextInt(moveX) : moveX;
if (randomColor) setRandomColor(randomColor);
if (x >= iRight - width)
x = iRight - width;
directionX *= (-1);
xScale = randomMove ? myRand.nextInt(moveX) : moveX;
if (randomColor) setRandomColor(randomColor);
if (y <= 0)
y = 0;
directionY *= (-1);
yScale = randomMove ? myRand.nextInt(moveY) : moveY;
if (randomColor) setRandomColor(randomColor);
if (y >= iBottom - height)
y = iBottom - height;
directionY *= (-1);
yScale = randomMove ? myRand.nextInt(moveY) : moveY;
if (randomColor) setRandomColor(randomColor);
public void draw(Graphics g)
g.setColor(color);
g.fillOval(x, y, width, height);
public void setColor(Color c)
color = c;
public void setLocation(int x, int y)
this.x = x;
this.y = y;
public void setMoveRate(int xMove, int yMove, int xDir, int yDir, boolean randMove)
this.moveX = xMove;
this.moveY = yMove;
directionX = xDir;
directionY = yDir;
randomMove = randMove;
public void setRandomColor(boolean randomColor)
this.randomColor = randomColor;
switch (myRand.nextInt(3))
case 0: color = Color.BLUE;
break;
case 1: color = Color.GREEN;
break;
case 2: color = Color.RED;
break;
default: color = Color.BLACK;
break;
public void setSize(int width, int height)
this.width = width;
this.height = height;
由于您的数组仅包含您要绘制的点,因此您没有任何关于每个点应移动的速度的信息。您可以做的最好的事情是创建一个随机量,每次更改其位置时都应移动每个点。这会产生不稳定的运动,因为每次移动一个点时,距离都是随机的。
如果你想要更恒定的速度,那么你需要创建第二个数组来包含每个点每次应该移动的距离。
每次你想要一个新属性对于你想要绘制的对象来说是唯一的,创建一个新数组就会变得很麻烦。这就是创建具有多个属性的自定义对象的方法更易于管理的原因。
【讨论】:
感谢您的帮助!您的代码肯定比我在说明中被要求做的更合乎逻辑。但是,如果我不遵守指南,我担心我可能会在材料上落后。此外,还没有为将来可能涉及本作业相同材料的项目做好准备。我应该再创建两个数组来处理 x 和 y 运动的速度吗?或者,我可以生成一个数组来处理每个绘制的正方形吗?再次感谢您的帮助! @Jfwhyte8,我无法回答您的问题,因为我不了解您的指导方针或示例试图教什么。 感谢您的帮助,很抱歉,我现在才回复您。至少可以说,生活一直很忙碌。我的目标是使用 Timer 添加动画,以便正方形在绘制时全部移动。我需要让每个方块以随机速度(在 x 和 y 方向)移动,并且我需要让方块在屏幕的所有四个边上适当地“反弹”。另外,我的老师说我们应该使用 2 个大小为 1000 的数组来保存 X 运动和 Y 运动的 1 到 10 之间的随机值。这应该允许矩形具有独立的移动速度。 我把它修好了。事实证明,使用数组并不难。当我不需要时,我正在重新填充它们,并且我需要一个局部变量来在 actionListener 方法中递增。感谢您的帮助!以上是关于如何在 Java 中绘制以不同速度移动的多个对象?的主要内容,如果未能解决你的问题,请参考以下文章