前几天用多线程实现了创建小球并移动,想到大鱼吃小鱼,便突发奇想要写一个大球吃小球。首先第一步自然是先把界面弄好啦
1 public class BallUI extends JPanel { 2 3 private ArrayList<Ball> li = new ArrayList<Ball>(); 4 5 public static void main(String[] args) { 6 BallUI bu = new BallUI(); 7 bu.UI(); 8 } 9 10 public void UI() { 11 JFrame jf = new JFrame(); 12 jf.setLocationRelativeTo(null); 13 jf.setResizable(false); 14 jf.setSize(700, 700); 15 this.setSize(jf.getWidth(),jf.getHeight()); 16 jf.setTitle("大球吃小球"); 17 18 this.setPreferredSize(new Dimension(jf.getWidth(), jf.getHeight())); 19 jf.add(this); 20 21 22 23 jf.setVisible(true); 24 } 25 26 27 }
界面写好后想想要怎么做呢?既然是大球吃小球还利用线程,那肯定需要一个队列,然后呢?既然要队列,那队列里存什么?肯定存小球啊,那自然要创建一个小球类了,那小球有什么属性呢?坐标、移动速度、大小、颜色,除了这些在创建时还需不需要传些什么参数呢?既然传了颜色,那肯定需要画小球,我们在哪画?是调用方法还是在线程中获取小球属性然后画?我觉得调用方法会更好,所以我们要在这里传入一个画布。同样在后面我们还需要检测小球是否碰撞,因此我们还需要传入一个队列。下面便是Ball类的构造了
public class Ball { private int size; private int x; private int y; private int speedX; private int speedY; private Color c; private JPanel jf; private ArrayList<Ball> li; public Ball(int size, int x, int y, int speedX, int speedY, Color c, JPanel jf, ArrayList<Ball> li) { this.size = size; this.x = x; this.y = y; this.speedX = speedX; this.speedY = speedY; this.c = c; this.jf = jf; this.li = li; } //画球 public void draw(Graphics g) { } //移动球 public void move() { } //清除上次留下的痕迹 public void clear(Graphics g) { } //碰撞检测 public void crash(Graphics g) { } }
创建好小球类后,我们便需要线程来创建小球、改变小球,那这里也有一个问题,我们是用一个线程还是两个还是多个?这样看,如果只用一个线程,那么我们每次改变小球得在创建了一个小球后进行,如果小球数量少还没问题,但是当小球数量多了之后,每便利一次就会用上一段时间,那么肯定会有延时,所以我们需要把这里分成两个线程,一个线程创建小球,一个线程改变小球。这里其实就利用了生产者消费者模型: 生产者负责生产数据并存入缓冲区,消费者从缓冲区中取出数据并且处理并输出。
1 public class ThreadBall extends Thread { 2 3 private ArrayList<Ball> li; 4 private JPanel jp; 5 private Graphics g; 6 7 public ThreadBall(ArrayList<Ball> li,JPanel jp) { 8 this.li = li; 9 this.jp=jp; 10 } 11 12 public void run() { 13 g=jp.getGraphics(); 14 while(true) { 15 for(int i=0;i<li.size();i++) { 16 Ball ball=li.get(i); 17 ball.clear(g); 18 ball.crash(g); 19 ball.move(); 20 ball.draw(g); 21 } 22 try { 23 Thread.sleep(100); 24 } catch (InterruptedException e) { 25 e.printStackTrace(); 26 } 27 } 28 } 29 30 }
public class BallLis extends Thread { private ArrayList<Ball> li = new ArrayList<Ball>(); private JPanel jp; public BallLis(ArrayList<Ball> li,JPanel jp) { this.li = li; this.jp = jp; } public void run() { while (true) { int size = new Random().nextInt(30) + 10; int x = new Random().nextInt(jp.getWidth()); int y = 0; int speedX = new Random().nextInt(10) + 10; int speedY = new Random().nextInt(10) + 5; Color c=new Color(new Random().nextInt(256),new Random().nextInt(256),new Random().nextInt(256)); Ball bl=new Ball(size,x,y,speedX,speedY,c,jp,li); li.add(bl); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } } } }
创建好线程后肯定需要在BallUI类中创建对象啦
BallLis ball = new BallLis(li,this); ball.start(); ThreadBall tb=new ThreadBall(li,this); tb.start();
那么,剩下的任务就是实现小球类中的方法了,就留给你们去实现了。
注:代码已上传至github:https://github.com/leo6033/Java_Project