java用线程做小球碰撞_多线程之碰撞小球
弹球游戏是一款模拟多线程运行的游戏,利用继承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用线程做小球碰撞_多线程之碰撞小球相关推荐
- java并行流 阻塞主线程_多线程入门案例与java8的并行流
java8 实例请移步https://www.cnblogs.com/ngLee/p/14021859.html 进程与线程 进程是所有线程的集合,每一个线程是进程中的一条执行路径. 多线程的创建方式 ...
- java当线程离开临界区时_第2章 - 作业部落 Cmd Markdown 编辑阅读器
第2章 translation 同步 线程交互通常是通过共享变量完成的,当线程之间没有交互,开发多线程的应用程序会变得简单许多.一旦交互发生了,很多诱发线程不安全(在多线程环境下不正确)的因素就会暴露 ...
- java中线程死锁及避免_如何避免Java线程中的死锁?
java中线程死锁及避免 如何避免Java中的死锁? 是Java面试中最受欢迎的问题之一,也是本季多线程的风格,主要是在高层提出,并带有很多后续问题. 尽管问题看起来很基础,但是一旦您开始深入研究,大 ...
- java 线程间变量共享_多线程:(五)多个线程之间共享数据
简单的总结一下多线程共享数据的方式.其实,最重要的,是一个思想,一个面向对象的编程思想的建立. 说两点: 一.如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中 ...
- java实现线程三种方式_详解三种java实现多线程的方式
java中实现多线程的方法有两种:继承Thread类和实现runnable接口. 1.继承Thread类,重写父类run()方法 public class thread1 extends Thread ...
- java线程 cpu占用率_多线程程序 怎样查看每个线程的cpu占用
可以用下面的命令将 cpu 占用率高的线程找出来: ps H -eo user,pid,ppid,tid,time,%cpu,cmd --sort=%cpu 这个命令首先指定参数'H',显示线程相关的 ...
- java线程中的常用方法_[多线程] 线程中的常用方法-最详细
线程中常用的方法 1.public void start() 使该线程开始执行:Java 虚拟机调用该线程的 run 方法. 2.public void run() 如果该线程是使用独立的 Runna ...
- java线程池读文件_多线程读取Java文件
我正在创建线程以读取Java中的文件.当我创建2个线程时,每个线程都读取整个文件,而我希望它们读取文件的不同部分.我尝试放入sleep(),join(),yield(),但是在包含它们之后,这只会减慢 ...
- java 线程访问控件_多线程下访问控件的方式
前言 在很多情况下,我们都会使用到多线程,在使用多线程的时候,我们很多时候又会去访问控件,这里面就会出现很多问题!!!我以一个最常见的,我们经常会用到的例子来讲讲,在提高自己水平的同时,希望能给大家带 ...
- java线程模拟银行取款_多线程模拟银行取款
packagetestsynchrozied;/*** 功能:多个用户同时对一个账户取款 * 使用线程的同步 * * 1.设计一个账户类 余额,取款,显示余额 * 2.取款的线程 * 3.用户同时取款 ...
最新文章
- 中国CIO最关心的八大问题(上)
- websocket获取httpsession报NullPointerException解决办法
- Php基础数学运算篇
- 我们在面临种种不良的飞鸽传书2012
- Java基础篇(04):日期与时间API用法详解
- Cookie工具类-cookieUtil.js
- 运筹优化(四)--线性规划之对偶问题和灵敏度分析
- 二十六、K8s系统强化2-seccomp与sysdig
- 24.root, alias
- C#两种创建快捷方式的方法
- 解决maven中ojdbc14:11.2.0.1.0错误
- 2个阶乘什么意思_两个阶乘号是什么意思,-双阶乘-数学-滕诓芳同学
- ECharts柱状图常见效果
- 柯美smb扫描出现服务器连接错误_柯尼卡美能达smb扫描设置方法是什么
- iOS App上架遇到的错误(ERRORITMS-90096: )
- 查找数组中重复的数字
- Google怎么了?
- java 文件 base64 转换
- 盛世危局下的短视频:抖音们正遭遇优酷、腾讯、爱奇艺们包抄
- 爬虫之 爬取京东计算机书籍
热门文章
- vagrant共享目录出现“mount:unknown filesystem type ‘vboxsf‘”错误解决方法(亲测可行)
- vue @cliick.stop @click.prevent @click.self
- Vue组件中关于@click.native.prevent事件
- 推特 我们目前不能注册此邮箱地址_安卓版推特App存在隐私漏洞,官方发信敦促用户更新...
- 赶不上春天,无法同其它植物竞相开放
- TCP三次握手中SYN,ACK,Seq三者的关系
- 深度技术官网linux,深度系统
- Spring Framework究竟是什么? [关闭]
- html表格填充空白单元格,快速填充数据表格中的空白单元格
- 模糊提取器(Fuzzy Extractor)