码迷,mamicode.com
首页 > 编程语言 > 详细

多线程之碰撞小球

时间:2015-06-12 00:36:19      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:

弹球游戏是一款模拟多线程运行的游戏,利用继承Thread实现多线程。

效果图:小球之间会相互碰撞并交换速度在弹开。按钮能实现随机添加、移除小球并暂停小球移动。

技术分享

 

具体实现:

1、创建界面(包含主函数)。

public class BallFrame extends JFrame {
public static void main(String[] args) { BallFrame bf = new BallFrame(); bf.initUI(); } public void initUI(){ //设置界面属性,包括按钮背景,添加监听 } }
//创建一个链表存储小球
       private ArrayList<Ball> list = new ArrayList<Ball>();

2、创建小球类,继承Thread类。这个类包含以下内容。

public class Ball extends Thread { 
//需要设置的属性有:
private int x, y;// 小球圆心坐标
    private Graphics2D g;
    Random rand = new Random();
    private ArrayList<Ball> list;//存贮每个小球
    int r = 12;//小球半径
    int green,red,blue;//小球的颜色 }

(1)、重写构造方法,主要用来传递参数,包括画笔,面板等。

(2)、画一个小球的方法。

public void drawNew(Graphics2D g) {
        // 绘制新的小球
        for (int i = r; i > 0; i--) {
//设置颜色使小球看起来具有立体感。
if(green<235)green=G + 8*(r-i) ; if(red<235)red=R + 8*(r-i) ; if(blue<235)blue=B + 8*(r-i) ; g.setColor(new Color(green,red,blue)); g.fillOval(x - r / 2 - i / 2, y - r / 2 - i / 2, i * 2, i * 2); } }

(3)、小球的移动方法。

public void move() {
        x += xspeed;
        y = y+yspeed;
    }

(4)、擦除小球的方法,画出新的小球之前要把上一个小球擦出,不然画不出小球的动态效果。

public void draw(Graphics2D g) {

        // 擦除上一次绘制的小球
        g.setColor(Color.black);
        g.fillOval(x - r - 1, y - r - 1, r * 2 + 2, r * 2 + 2);
    }

(5)、判断小球碰撞的方法,判断这个小球是否与链表内其他的小球存在碰撞,同时也判断是否与边界发生碰撞。

public void collide() {
        int index=list.indexOf(this);
                for (int i =index; i < list.size(); i++) {
            Ball ball = list.get(i);
            // 判断是否发生碰撞
            if (ball != this) {
                // 计算两个小球的距离
                int d = (int) Math.sqrt((this.x - ball.x) * (this.x - ball.x)
                        + (this.y - ball.y) * (this.y - ball.y));
                if (d < (this.r + ball.r+2)) {
                    int m = this.xspeed;
                    this.xspeed = ball.xspeed;
                    ball.xspeed = m;
                    m = this.yspeed;
                    this.yspeed = ball.yspeed;
                    ball.yspeed = m;
                }
            }
        }
//判断是否与边界发生碰撞
if (x + r > centerPanel.getWidth() || x < r) xspeed = -xspeed; if (y + r > centerPanel.getHeight() || y < r) yspeed = -yspeed; }

(6)、线程运行的方法。

    public void run() {
        while (true) {
            this.draw(g);
            this.move();
            this.collide();
            this.drawNew(g);
            try {
//每40ms循环一次模拟小球的动态效果 Thread.sleep(
40); } catch (InterruptedException e) { e.printStackTrace(); } } }

3、事件的处理(添加、删除、暂停),主要通过鼠标实现。

(1)、添加小球。在随机位置产生一个小球,初始速度也随机。

if (e.getActionCommand().equals("添加")) {
//随机设置小球的初始位置
int x = rand.nextInt(centerPanel.getWidth() - 24) + 12; int y = rand.nextInt(centerPanel.getHeight() - 24) + 12; // 创建小球对象 Ball ball = new Ball(list, x, y, centerPanel, this); ball.start();//启动线程 list.add(ball);//将小球存入链表 System.out.println(list.size()); flag = true; }

(2)、删除小球,随机删除界面中一个小球。

 if (e.getActionCommand().equals("移除")) {
            // 随机移除小球
            if (list.size() > 0) {
                int index = rand.nextInt(list.size());
                Ball ball = list.remove(index);
                ball.draw(g);//清除被移除的小球
                ball.stop();
                System.out.println(ball);
            } else
                System.out.println("没有可移除的小球!");
        } 

(3)、暂停小球。

Thread中有可以让线程等待的方法,但是时间不具有灵活性,这里考虑用sleep方法来实现。

在run()方法中插入sleep,手动改变sleep的条件。

public void run() {
        while (true) {
            this.draw(g);
            this.move();
            this.collide();
            this.drawNew(g);
            try {
                Thread.sleep(40);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

//以下是插入的代码
            while(flag){  //flag就是控制暂停的条件
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

//监听中的方法
if (e.getActionCommand().equals("暂停")) {
            if (flag == false) {
                flag = true;
            } else if (flag == true) {
                flag = false;
            }    
            for (int i = 0; i < list.size(); i++) {
                    Ball ball = list.get(i);
                    ball.setFlag(flag);
                }
        }

完整代码:

import java.awt.BorderLayout;
import java.awt.Color;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class BallFrame extends JFrame {

    private static final long serialVersionUID = 1L;

    public static void main(String[] args) {
        //线程
        BallFrame bf = new BallFrame();
        bf.initUI();
    }
    
    public void initUI(){
        this.setTitle("弹球");
        this.setSize(400, 500);
        this.setDefaultCloseOperation(3);
        this.setLocationRelativeTo(null);
        this.setResizable(false);
        
        /***********北边************/
        JPanel northPanel = new JPanel();
        northPanel.setBackground(Color.black);
        JButton butAdd = new JButton("添加");
        JButton butRemove = new JButton("移除");
        JButton butPause = new JButton("暂停");
        
        northPanel.add(butAdd);
        northPanel.add(butRemove);
        northPanel.add(butPause);
        this.add(northPanel,BorderLayout.NORTH);
        
        
        /***********中间************/
        JPanel centerPanel = new JPanel();
        centerPanel.setBackground(Color.black);
        this.add(centerPanel,BorderLayout.CENTER);
        this.setVisible(true);

        //事件处理类
        BallListener bl = new BallListener(centerPanel);
        //给事件源添加动作监听方法,指定事件处理类的对象bl
        butAdd.addActionListener(bl);
        butRemove.addActionListener(bl);
        butPause.addActionListener(bl);
    }

}
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.JPanel;

/**
 * 小球类
 */
public class Ball extends Thread {

    private int x, y;// 小球圆心坐标
    private Graphics2D g;
    Random rand = new Random();
    private JPanel centerPanel;
    private ArrayList<Ball> list;
    int r = 12;
    int green,red,blue;
    int G = rand.nextInt(155);
    int R = rand.nextInt(155);
    int B = rand.nextInt(155);
    int xspeed =  3;
    int yspeed =  3;
    BallListener bl;

    public Ball(ArrayList<Ball> list, int x, int y, JPanel centerPanel,
            BallListener bl) {
        this.x = x;
        this.y = y;
        this.list = list;
        this.centerPanel = centerPanel;
        this.g = (Graphics2D) centerPanel.getGraphics();
        this.bl = bl;
        // 设置取表画笔的锯齿状
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
    }

    private boolean flag = true;

    public void setFlag(boolean flag) {
        this.flag = flag;
    }

    public boolean getFlag() {
        return flag;
    }

    public void draw(Graphics2D g) {

        // 擦除上一次绘制的小球
        g.setColor(Color.black);
        g.fillOval(x - r - 1, y - r - 1, r * 2 + 2, r * 2 + 2);
    }

    public void drawNew(Graphics2D g) {
        // 绘制新的小球
        for (int i = r; i > 0; i--) {
            if(green<235)green=G +  8*(r-i) ;
            if(red<235)red=R +  8*(r-i) ;
            if(blue<235)blue=B +  8*(r-i) ;
            g.setColor(new Color(green,red,blue));
            g.fillOval(x - r / 2 - i / 2, y - r / 2 - i / 2, i * 2, i * 2);
        }
    }

    public void move() {
        x += xspeed;
        y = (int)(y+yspeed);
    }

    public void collide() {
        int index=list.indexOf(this);
                for (int i =index; i < list.size(); i++) {
            Ball ball = list.get(i);
            // 判断是否发生碰撞
            if (ball != this) {
                // 计算两个小球的距离
                int d = (int) Math.sqrt((this.x - ball.x) * (this.x - ball.x)
                        + (this.y - ball.y) * (this.y - ball.y));
                if (d < (this.r + ball.r+2)) {
                    int m = this.xspeed;
                    this.xspeed = ball.xspeed;
                    ball.xspeed = m;
                    m = this.yspeed;
                    this.yspeed = ball.yspeed;
                    ball.yspeed = m;
                }
            }
        }
                if (x + r > centerPanel.getWidth() || x < r)
                    xspeed = -xspeed;
                if (y + r > centerPanel.getHeight() || y < r)
                    yspeed = -yspeed;
    }

    public void run() {
        while (true) {
            this.draw(g);
            this.move();
            this.collide();
            this.drawNew(g);
            try {
                Thread.sleep(40);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            while(flag^true){
                try {
                    Thread.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
package study0528ball;

import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Random;

import javax.swing.JPanel;

public class BallListener implements ActionListener {

    private JPanel centerPanel;
    private Graphics2D g;
    private ArrayList<Ball> list = new ArrayList<Ball>();
    private boolean flag;
    private Random rand = new Random();

    public boolean isFlag() {
        return flag;

    }

    public BallListener(JPanel centerPanel) {
        this.centerPanel = centerPanel;
        g = (Graphics2D) centerPanel.getGraphics();// 强制转型
        // 设置取表画笔的锯齿状
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
    }

    @SuppressWarnings("deprecation")
    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getActionCommand().equals("添加")) {
            int x = rand.nextInt(centerPanel.getWidth() - 24) + 12;
            int y = rand.nextInt(centerPanel.getHeight() - 24) + 12;
            // 创建小球对象
            Ball ball = new Ball(list, x, y, centerPanel, this);
            ball.start();
            list.add(ball);
            System.out.println(list.size());
            flag = true;
        }

        else if (e.getActionCommand().equals("移除")) {
            // 随机溢出小球
            if (list.size() > 0) {
                int index = rand.nextInt(list.size());
                Ball ball = list.remove(index);
                ball.draw(g);
                ball.stop();
                System.out.println(ball);
            } else
                System.out.println("没有可移除的小球!");
        } else if (e.getActionCommand().equals("暂停")) {
            if (flag == false) {
                flag = true;
            } else if (flag == true) {
                flag = false;
            }    
            for (int i = 0; i < list.size(); i++) {
                    Ball ball = list.get(i);
                    ball.setFlag(flag);
                }
        }
    }

}

 

多线程之碰撞小球

标签:

原文地址:http://www.cnblogs.com/xiao-v/p/4570564.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!