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

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

具体实现:

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);

}

}

}

}

java用线程做小球碰撞_多线程之碰撞小球相关推荐

  1. java并行流 阻塞主线程_多线程入门案例与java8的并行流

    java8 实例请移步https://www.cnblogs.com/ngLee/p/14021859.html 进程与线程 进程是所有线程的集合,每一个线程是进程中的一条执行路径. 多线程的创建方式 ...

  2. java当线程离开临界区时_第2章 - 作业部落 Cmd Markdown 编辑阅读器

    第2章 translation 同步 线程交互通常是通过共享变量完成的,当线程之间没有交互,开发多线程的应用程序会变得简单许多.一旦交互发生了,很多诱发线程不安全(在多线程环境下不正确)的因素就会暴露 ...

  3. java中线程死锁及避免_如何避免Java线程中的死锁?

    java中线程死锁及避免 如何避免Java中的死锁? 是Java面试中最受欢迎的问题之一,也是本季多线程的风格,主要是在高层提出,并带有很多后续问题. 尽管问题看起来很基础,但是一旦您开始深入研究,大 ...

  4. java 线程间变量共享_多线程:(五)多个线程之间共享数据

    简单的总结一下多线程共享数据的方式.其实,最重要的,是一个思想,一个面向对象的编程思想的建立. 说两点: 一.如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中 ...

  5. java实现线程三种方式_详解三种java实现多线程的方式

    java中实现多线程的方法有两种:继承Thread类和实现runnable接口. 1.继承Thread类,重写父类run()方法 public class thread1 extends Thread ...

  6. java线程 cpu占用率_多线程程序 怎样查看每个线程的cpu占用

    可以用下面的命令将 cpu 占用率高的线程找出来: ps H -eo user,pid,ppid,tid,time,%cpu,cmd --sort=%cpu 这个命令首先指定参数'H',显示线程相关的 ...

  7. java线程中的常用方法_[多线程] 线程中的常用方法-最详细

    线程中常用的方法 1.public void start() 使该线程开始执行:Java 虚拟机调用该线程的 run 方法. 2.public void run() 如果该线程是使用独立的 Runna ...

  8. java线程池读文件_多线程读取Java文件

    我正在创建线程以读取Java中的文件.当我创建2个线程时,每个线程都读取整个文件,而我希望它们读取文件的不同部分.我尝试放入sleep(),join(),yield(),但是在包含它们之后,这只会减慢 ...

  9. java 线程访问控件_多线程下访问控件的方式

    前言 在很多情况下,我们都会使用到多线程,在使用多线程的时候,我们很多时候又会去访问控件,这里面就会出现很多问题!!!我以一个最常见的,我们经常会用到的例子来讲讲,在提高自己水平的同时,希望能给大家带 ...

  10. java线程模拟银行取款_多线程模拟银行取款

    packagetestsynchrozied;/*** 功能:多个用户同时对一个账户取款 * 使用线程的同步 * * 1.设计一个账户类 余额,取款,显示余额 * 2.取款的线程 * 3.用户同时取款 ...

最新文章

  1. 中国CIO最关心的八大问题(上)
  2. websocket获取httpsession报NullPointerException解决办法
  3. Php基础数学运算篇
  4. 我们在面临种种不良的飞鸽传书2012
  5. Java基础篇(04):日期与时间API用法详解
  6. Cookie工具类-cookieUtil.js
  7. 运筹优化(四)--线性规划之对偶问题和灵敏度分析
  8. 二十六、K8s系统强化2-seccomp与sysdig
  9. 24.root, alias
  10. C#两种创建快捷方式的方法
  11. 解决maven中ojdbc14:11.2.0.1.0错误
  12. 2个阶乘什么意思_两个阶乘号是什么意思,-双阶乘-数学-滕诓芳同学
  13. ECharts柱状图常见效果
  14. 柯美smb扫描出现服务器连接错误_柯尼卡美能达smb扫描设置方法是什么
  15. iOS App上架遇到的错误(ERRORITMS-90096: )
  16. 查找数组中重复的数字
  17. Google怎么了?
  18. java 文件 base64 转换
  19. 盛世危局下的短视频:抖音们正遭遇优酷、腾讯、爱奇艺们包抄
  20. 爬虫之 爬取京东计算机书籍

热门文章

  1. vagrant共享目录出现“mount:unknown filesystem type ‘vboxsf‘”错误解决方法(亲测可行)
  2. vue @cliick.stop @click.prevent @click.self
  3. Vue组件中关于@click.native.prevent事件
  4. 推特 我们目前不能注册此邮箱地址_安卓版推特App存在隐私漏洞,官方发信敦促用户更新...
  5. 赶不上春天,无法同其它植物竞相开放
  6. TCP三次握手中SYN,ACK,Seq三者的关系
  7. 深度技术官网linux,深度系统
  8. Spring Framework究竟是什么? [关闭]
  9. html表格填充空白单元格,快速填充数据表格中的空白单元格
  10. 模糊提取器(Fuzzy Extractor)