java用线程做小球碰撞_多线程之碰撞小球

本文介绍了一个使用Java实现的多线程弹球碰撞游戏。游戏通过继承Thread类创建小球类,实现小球的绘制、移动、碰撞检测等功能。用户可以通过按钮随机添加、移除小球及暂停小球运动,展示了Java在多线程控制和图形界面交互上的应用。
摘要由CSDN通过智能技术生成

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

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

bee384af080f4bca9e9e137bc56c9584.png

具体实现:

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

public class BallFrame extendsJFrame {public static voidmain(String[] args) {

BallFrame bf= newBallFrame();

bf.initUI();

}

public voidinitUI(){

//设置界面属性,包括按钮背景,添加监听

}

}

//创建一个链表存储小球private ArrayList list = new ArrayList();

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

public class Ball extendsThread {

//需要设置的属性有:

private int x, y;// 小球圆心坐标

private Graphics2D g;

Random rand = new Random();

private ArrayList list;//存贮每个小球

int r = 12;//小球半径

int green,red,blue;//小球的颜色

}

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

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

public voiddrawNew(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(newColor(green,red,blue));

g.fillOval(x- r / 2 - i / 2, y - r / 2 - i / 2, i * 2, i * 2);

}

}

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

public voidmove() {

x+=xspeed;

y= y+yspeed;

}

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

public voiddraw(Graphics2D g) {//擦除上一次绘制的小球

g.setColor(Color.black);

g.fillOval(x- r - 1, y - r - 1, r * 2 + 2, r * 2 + 2);

}

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

public voidcollide() {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

xspeed= -xspeed;if (y + r > centerPanel.getHeight() || y

yspeed= -yspeed;

}

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

public voidrun() {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);

}elseSystem.out.println("没有可移除的小球!");

}

(3)、暂停小球。

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

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

public voidrun() {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);

}

}

完整代码:

importjava.awt.BorderLayout;importjava.awt.Color;importjavax.swing.JButton;importjavax.swing.JFrame;importjavax.swing.JPanel;public class BallFrame extendsJFrame {private static final long serialVersionUID = 1L;public static voidmain(String[] args) {//线程

BallFrame bf = newBallFrame();

bf.initUI();

}public voidinitUI(){this.setTitle("弹球");this.setSize(400, 500);this.setDefaultCloseOperation(3);this.setLocationRelativeTo(null);this.setResizable(false);/***********北边************/JPanel northPanel= newJPanel();

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= newJPanel();

centerPanel.setBackground(Color.black);this.add(centerPanel,BorderLayout.CENTER);this.setVisible(true);//事件处理类

BallListener bl = newBallListener(centerPanel);//给事件源添加动作监听方法,指定事件处理类的对象bl

butAdd.addActionListener(bl);

butRemove.addActionListener(bl);

butPause.addActionListener(bl);

}

}

importjava.awt.Color;importjava.awt.Graphics2D;importjava.awt.RenderingHints;importjava.util.ArrayList;importjava.util.Random;importjavax.swing.JPanel;/*** 小球类*/

public class Ball extendsThread {private int x, y;//小球圆心坐标

privateGraphics2D g;

Random rand= newRandom();privateJPanel centerPanel;private ArrayListlist;int r = 12;intgreen,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 list, int x, inty, 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(booleanflag) {this.flag =flag;

}public booleangetFlag() {returnflag;

}public voiddraw(Graphics2D g) {//擦除上一次绘制的小球

g.setColor(Color.black);

g.fillOval(x- r - 1, y - r - 1, r * 2 + 2, r * 2 + 2);

}public voiddrawNew(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(newColor(green,red,blue));

g.fillOval(x- r / 2 - i / 2, y - r / 2 - i / 2, i * 2, i * 2);

}

}public voidmove() {

x+=xspeed;

y= (int)(y+yspeed);

}public voidcollide() {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

xspeed= -xspeed;if (y + r > centerPanel.getHeight() || y

yspeed= -yspeed;

}public voidrun() {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();

}

}

}

}

}

packagestudy0528ball;importjava.awt.Graphics2D;importjava.awt.RenderingHints;importjava.awt.event.ActionEvent;importjava.awt.event.ActionListener;importjava.util.ArrayList;importjava.util.Random;importjavax.swing.JPanel;public class BallListener implementsActionListener {privateJPanel centerPanel;privateGraphics2D g;private ArrayList list = new ArrayList();private booleanflag;private Random rand = newRandom();public booleanisFlag() {returnflag;

}publicBallListener(JPanel centerPanel) {this.centerPanel =centerPanel;

g= (Graphics2D) centerPanel.getGraphics();//强制转型//设置取表画笔的锯齿状

g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

RenderingHints.VALUE_ANTIALIAS_ON);

}

@SuppressWarnings("deprecation")

@Overridepublic voidactionPerformed(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);

}elseSystem.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);

}

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值