Java弹跳球

我正在尝试编写一个Java应用程序,它可以在屏幕边缘popup多个球。 我可以成功地画一个球。 但是当我join第二个球时,它会覆盖我画出的最初的球。 代码是:

import java.awt.*; import javax.swing.*; import java.util.ArrayList; import java.util.List; public class Ball extends JPanel implements Runnable { List<Ball> balls = new ArrayList<Ball>(); Color color; int diameter; long delay; private int x; private int y; private int vx; private int vy; public Ball(String ballcolor, int xvelocity, int yvelocity) { if(ballcolor == "red") { color = Color.red; } else if(ballcolor == "blue") { color = Color.blue; } else if(ballcolor == "black") { color = Color.black; } else if(ballcolor == "cyan") { color = Color.cyan; } else if(ballcolor == "darkGray") { color = Color.darkGray; } else if(ballcolor == "gray") { color = Color.gray; } else if(ballcolor == "green") { color = Color.green; } else if(ballcolor == "yellow") { color = Color.yellow; } else if(ballcolor == "lightGray") { color = Color.lightGray; } else if(ballcolor == "magenta") { color = Color.magenta; } else if(ballcolor == "orange") { color = Color.orange; } else if(ballcolor == "pink") { color = Color.pink; } else if(ballcolor == "white") { color = Color.white; } diameter = 30; delay = 40; x = 1; y = 1; vx = xvelocity; vy = yvelocity; } protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(color); g.fillOval(x,y,30,30); //adds color to circle g.setColor(Color.black); g2.drawOval(x,y,30,30); //draws circle } public void run() { while(isVisible()) { try { Thread.sleep(delay); } catch(InterruptedException e) { System.out.println("interrupted"); } move(); repaint(); } } public void move() { if(x + vx < 0 || x + diameter + vx > getWidth()) { vx *= -1; } if(y + vy < 0 || y + diameter + vy > getHeight()) { vy *= -1; } x += vx; y += vy; } private void start() { while(!isVisible()) { try { Thread.sleep(25); } catch(InterruptedException e) { System.exit(1); } } Thread thread = new Thread(this); thread.setPriority(Thread.NORM_PRIORITY); thread.start(); } public static void main(String[] args) { Ball ball1 = new Ball("red",3,2); Ball ball2 = new Ball("blue",6,2); JFrame f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.getContentPane().add(ball1); f.getContentPane().add(ball2); f.setSize(400,400); f.setLocation(200,200); f.setVisible(true); new Thread(ball1).start(); new Thread(ball2).start(); } } 

我想创build一个球列表,然后循环绘制每个球,但我仍然无法将两个球添加到内容窗格。

感谢您的帮助。

用你目前的方法…

  • 我可以看到的主要问题是,您将两个不透明的组件放在另一个上面…实际上,您可能会发现您正在绕过其中的一个…
  • 你应该使用一个null布局pipe理器,否则它会接pipe和布局你的球,因为它认为合适。
  • 您需要确保您正在控制球窗的大小和位置。 这意味着你已经接pipe了布局经理的angular色
  • 你需要随机化球的速度和位置,以减less在相同的位置开始并在相同的位置移动的机会…
  • 只在EDT的情况下更新Ball
  • 你并不需要X / Y值,你可以使用面板。

 public class AnimatedBalls { public static void main(String[] args) { new AnimatedBalls(); } public AnimatedBalls() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException ex) { } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); frame.add(new Balls()); frame.setSize(400, 400); frame.setVisible(true); } }); } public class Balls extends JPanel { public Balls() { setLayout(null); // Randomize the speed and direction... add(new Ball("red", 10 - (int) Math.round((Math.random() * 20)), 10 - (int) Math.round((Math.random() * 20)))); add(new Ball("blue", 10 - (int) Math.round((Math.random() * 20)), 10 - (int) Math.round((Math.random() * 20)))); } } public class Ball extends JPanel implements Runnable { Color color; int diameter; long delay; private int vx; private int vy; public Ball(String ballcolor, int xvelocity, int yvelocity) { if (ballcolor == "red") { color = Color.red; } else if (ballcolor == "blue") { color = Color.blue; } else if (ballcolor == "black") { color = Color.black; } else if (ballcolor == "cyan") { color = Color.cyan; } else if (ballcolor == "darkGray") { color = Color.darkGray; } else if (ballcolor == "gray") { color = Color.gray; } else if (ballcolor == "green") { color = Color.green; } else if (ballcolor == "yellow") { color = Color.yellow; } else if (ballcolor == "lightGray") { color = Color.lightGray; } else if (ballcolor == "magenta") { color = Color.magenta; } else if (ballcolor == "orange") { color = Color.orange; } else if (ballcolor == "pink") { color = Color.pink; } else if (ballcolor == "white") { color = Color.white; } diameter = 30; delay = 100; vx = xvelocity; vy = yvelocity; new Thread(this).start(); } protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D) g; int x = getX(); int y = getY(); g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(color); g.fillOval(0, 0, 30, 30); //adds color to circle g.setColor(Color.black); g2.drawOval(0, 0, 30, 30); //draws circle } @Override public Dimension getPreferredSize() { return new Dimension(30, 30); } public void run() { try { // Randamize the location... SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { int x = (int) (Math.round(Math.random() * getParent().getWidth())); int y = (int) (Math.round(Math.random() * getParent().getHeight())); setLocation(x, y); } }); } catch (InterruptedException exp) { exp.printStackTrace(); } catch (InvocationTargetException exp) { exp.printStackTrace(); } while (isVisible()) { try { Thread.sleep(delay); } catch (InterruptedException e) { System.out.println("interrupted"); } try { SwingUtilities.invokeAndWait(new Runnable() { @Override public void run() { move(); repaint(); } }); } catch (InterruptedException exp) { exp.printStackTrace(); } catch (InvocationTargetException exp) { exp.printStackTrace(); } } } public void move() { int x = getX(); int y = getY(); if (x + vx < 0 || x + diameter + vx > getParent().getWidth()) { vx *= -1; } if (y + vy < 0 || y + diameter + vy > getParent().getHeight()) { vy *= -1; } x += vx; y += vy; // Update the size and location... setSize(getPreferredSize()); setLocation(x, y); } } } 

这个方法的“主要”问题是每个Ball都有自己的Thread 。 当你缩放球的数量时,这将快速地进入你的系统资源。

一种不同的方法

如同气垫船一样,你最好创造一个容纳球的容器,这些容器不是球的组成部分,而是球的“虚拟”概念,包含足够的信息以使其能够从墙上反弹。 ..

在这里输入图像描述

 public class SimpleBalls { public static void main(String[] args) { new SimpleBalls(); } public SimpleBalls() { EventQueue.invokeLater(new Runnable() { @Override public void run() { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException ex) { } catch (InstantiationException ex) { } catch (IllegalAccessException ex) { } catch (UnsupportedLookAndFeelException ex) { } JFrame frame = new JFrame("Spot"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setLayout(new BorderLayout()); Balls balls = new Balls(); frame.add(balls); frame.setSize(400, 400); frame.setVisible(true); new Thread(new BounceEngine(balls)).start(); } }); } public static int random(int maxRange) { return (int) Math.round((Math.random() * maxRange)); } public class Balls extends JPanel { private List<Ball> ballsUp; public Balls() { ballsUp = new ArrayList<Ball>(25); for (int index = 0; index < 10 + random(90); index++) { ballsUp.add(new Ball(new Color(random(255), random(255), random(255)))); } } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); for (Ball ball : ballsUp) { ball.paint(g2d); } g2d.dispose(); } public List<Ball> getBalls() { return ballsUp; } } public class BounceEngine implements Runnable { private Balls parent; public BounceEngine(Balls parent) { this.parent = parent; } @Override public void run() { int width = getParent().getWidth(); int height = getParent().getHeight(); // Randomize the starting position... for (Ball ball : getParent().getBalls()) { int x = random(width); int y = random(height); Dimension size = ball.getSize(); if (x + size.width > width) { x = width - size.width; } if (y + size.height > height) { y = height - size.height; } ball.setLocation(new Point(x, y)); } while (getParent().isVisible()) { // Repaint the balls pen... SwingUtilities.invokeLater(new Runnable() { @Override public void run() { getParent().repaint(); } }); // This is a little dangrous, as it's possible // for a repaint to occur while we're updating... for (Ball ball : getParent().getBalls()) { move(ball); } // Some small delay... try { Thread.sleep(100); } catch (InterruptedException ex) { } } } public Balls getParent() { return parent; } public void move(Ball ball) { Point p = ball.getLocation(); Point speed = ball.getSpeed(); Dimension size = ball.getSize(); int vx = speed.x; int vy = speed.y; int x = px; int y = py; if (x + vx < 0 || x + size.width + vx > getParent().getWidth()) { vx *= -1; } if (y + vy < 0 || y + size.height + vy > getParent().getHeight()) { vy *= -1; } x += vx; y += vy; ball.setSpeed(new Point(vx, vy)); ball.setLocation(new Point(x, y)); } } public class Ball { private Color color; private Point location; private Dimension size; private Point speed; public Ball(Color color) { setColor(color); speed = new Point(10 - random(20), 10 - random(20)); size = new Dimension(30, 30); } public Dimension getSize() { return size; } public void setColor(Color color) { this.color = color; } public void setLocation(Point location) { this.location = location; } public Color getColor() { return color; } public Point getLocation() { return location; } public Point getSpeed() { return speed; } public void setSpeed(Point speed) { this.speed = speed; } protected void paint(Graphics2D g2d) { Point p = getLocation(); if (p != null) { g2d.setColor(getColor()); Dimension size = getSize(); g2d.fillOval(px, py, size.width, size.height); } } } } 

因为这是由单个线程驱动的,所以它更具可扩展性。

你也可以查看图像是不是加载这是一个类似的问题;)

您需要在这里使用两个完全不同的类 – 一个用于扩展JPanel的BallContainer,一个用于绘制球的组件,另一个用于Ball,它不扩展任何东西,而是保存球的坐标和颜色。 BallContainer应该放置一个List<Ball> ,当它移动它们并且绘制它们的时候它会迭代它。

你需要做的是扩大你的paintComponent方法。

而不是只画一个球,你需要遍历它们,并且每个都是原始的。

例:

 protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2 = (Graphics2D)g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); for (Ball b: balls) { g.setColor(color); g.fillOval(x,y,30,30); //adds color to circle g.setColor(Color.black); g2.drawOval(x,y,30,30); //draws circle } } 
 package BouncingBallApp.src.copy; import java.awt.*; public class Ball { private Point location; private int radius; private Color color; private int dx, dy; //private Color[] ballArr; public Ball(Point l, int r, Color c){ location = l; radius = r; color = c; } public Ball(Point l, int r){ location = l; radius = r; color = Color.RED; } public Point getLocation() { return location; } public void setLocation(Point location) { this.location = location; } public int getRadius() { return radius; } public void setRadius(int radius) { this.radius = radius; } public Color getColor() { return color; } public void setColor(Color color) { this.color = color; } public void setMotion(int dx, int dy){ this.dx = dx; this.dy = dy; } public void move(){ location.translate(dx, dy); } public void moveTo(int x, int y){ location.move(x, y); } public void paint (Graphics g) { g.setColor (color); g.fillOval (location.x-radius, location.y-radius, 2*radius, 2*radius); } public void reclectHoriz() { dy = -dy; } public void reclectVert() { dx = -dx; } } package BouncingBallApp.src.copy; public class MyApp { public static void main(String[] args) { MyFrame frm = new MyFrame(10); frm.setVisible(true); for (int i=0; i<1000; i++){ frm.stepTheBall(); } } } package BouncingBallApp.src.copy; import java.awt.Color; import java.awt.Graphics; import java.awt.Point; import java.util.Random; import javax.swing.JFrame; public class MyFrame extends JFrame { public final int FRAMEWIDTH = 600; public final int FRAMEHEIGHT = 400; private Ball[] ballArr; private Random random =new Random (); private Color[] colors={Color.RED,Color.blue,Color.yellow}; private int ballCnt; public MyFrame(int ballCnt){ super(); setSize(FRAMEWIDTH, FRAMEHEIGHT); setTitle("My Bouncing Ball Application"); ballArr = new Ball[ballCnt]; this.ballCnt = ballCnt; int c; for (int i=0; i < ballCnt; i++){ int bcn =random.nextInt(colors.length); Color ballcolor=colors[bcn]; ballArr[i] = new Ball(new Point(50,50),c=(int) (Math.random()*10+3)%8,ballcolor); int ddx = (int) (Math.random()*10+2)%8; int ddy = (int) (Math.random()*10+2)%8; ballArr[i].setMotion(ddx, ddy); //c++; } } public void paint(Graphics g){ super.paint(g); for (int i=0; i < ballCnt; i++){ ballArr[i].paint(g); } } public void stepTheBall(){ for (int i=0; i < ballCnt; i++){ ballArr[i].move(); Point loc = ballArr[i].getLocation(); if (loc.x < ballArr[i].getRadius() || loc.x > FRAMEWIDTH-ballArr[i].getRadius()){ ballArr[i].reclectVert(); } if (loc.y < ballArr[i].getRadius() || loc.y > FRAMEHEIGHT-ballArr[i].getRadius()){ ballArr[i].reclectHoriz(); } } repaint(); try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } } }