`

线程--简单弹球

    博客分类:
  • java
 
阅读更多
线程---简单弹球
一般的程序,就是从头至尾地执行代码,完成了一个方法,接下来完成后面紧接着的方法,但是,一般解决实际问题不会单纯地按顺序操作,很有可能在同一时间执行多种方法,就像一个人,在某一个时刻不会只做一件事,他可能一边听歌,一边写总结•••那么这样就需要用到多线程操作。
实现线程有两种方式,一种是继承Thread类,一种是实现Runnable接口,这里主要先研究第一种情况继承Thread类。
步骤如下:
1. 先定义一个新类继承Thread类,在该类中,重写父类的run()方法,实际上要完成的方法就是重写的run()方法。
2. 实例化一个上述类对象,调用其start()方法,线程即准备就绪(个人理解就是开始了)。
注意:一个上述类对象只能调用一次start()方法,如果调用多次,系统将报错;
当run()中的过程结束,这个线程即结束。(当然也可以用stop()方法强制结束线程)
public class DrawTest extends JFrame{
接下来,是利用线程,实现一个简单的弹球:

这里定义一个DrawTest类来继承JFrame,小球将在该类的窗体上运动:
public class DrawTest extends JFrame{
public static void main(String[] args){
DrawTest test =new DrawTest();
test.shower();
}
//构造一个画板
public void shower(){
this.setTitle("神奇小球");
this.setSize(600,600);
this.setLocationRelativeTo(null);
this.setDefaultCloseOperation(3);
this.setLayout(new FlowLayout());
//设置执行按钮
JButton jb1=new JButton("执行");
jb1.setActionCommand("执行");
jb1.setPreferredSize(new Dimension(100,50));
this.add(jb1);
//设置暂停按钮
JButton jb2=new JButton("暂停");
jb2.setActionCommand("暂停");
jb2.setPreferredSize(new Dimension(100,50));
this.add(jb2);
//设置开始按钮
JButton jb3=new JButton("开始");
jb3.setActionCommand("开始");
jb3.setPreferredSize(new Dimension(100,50));
this.add(jb3);
//设置删除按钮
JButton jb4=new JButton("删除");
jb4.setActionCommand("删除");
jb4.setPreferredSize(new Dimension(100,50));
this.add(jb4);
this.setVisible(true);
drawListener1 A=new drawListener1(this);//这里将整个窗体传入,是为了后面得到画布所需要,将在后面解释
//添加监听器
jb1.addActionListener(A);
jb2.addActionListener(A);
jb3.addActionListener(A);
jb4.addActionListener(A);
}
}
因为有四个按钮,实现的是四个不同的功能,按道理来说要设置四个不同的监听器加入才行,但是这样代码太过繁琐,下面是一个实现监听器的类,在此类中用if语句判断,从而达到一个监听器多用的作用。
实现监听器的代码如下:
public class drawListener1 implements ActionListener {
private JFrame jf;
// 用一个数组队列来存放线程对象
private List<drawThread> list = new ArrayList<drawThread>();
public drawListener1(JFrame jf) {
this.jf = jf;
}
public void actionPerformed(ActionEvent e) {
// 执行增加一个小球
if (e.getActionCommand().equals("执行")) {
System.out.println("执行了!");
drawThread threadA = new drawThread(this.jf.getGraphics());
threadA.setStart(true);
threadA.start();
list.add(threadA);
//这里用到了线程,每点击“执行”一次,将实例化一个线程对像,这样可以让多个方法同时进行(多个小球同时运动)
}
// 暂停当前画布上所有的小球的运动
if (e.getActionCommand().equals("暂停")) {
for (int i = 0; i < list.size(); i++) {
drawThread thread = list.get(i);
thread.setStart(false);
}
}
// 开始当前画布上所有的小球的运动
if (e.getActionCommand().equals("开始")) {
for (int i = 0; i < list.size(); i++) {
drawThread thread = list.get(i);
thread.setStart(true);
}
}
// 清楚最后一次执行的小球
if (e.getActionCommand().equals("删除")) {
if (list.size() > 0) {
drawThread thread = list.get(list.size() - 1);
thread.clear();
thread.stop();
list.remove(list.size() - 1);
System.out.println(list.size());
}
}
}
}
接下来是实现线程中的run()方法:
// 构造函数,传入画布
private Graphics g;
public drawThread(Graphics g) {
this.g = g;
}
// 定义一个开始的开关,当其为真时可以执行
private boolean start = false;
// 定义小球初始半径
private int radius = 30;
// 分别定义小球x,y方向上的速度
private int speedX = 2;
private int speedY = 3;
// 定义一个控制x方向上的运动方向(0表示向左,1表示向右)
private int directX = 1;
// 定义一个控制y方向上的运动方向(0表示向上,1表示向下)
private int directY = 1;
// 定义小球的初始位置
private int X = 0, Y = 50;
// 定义小球的颜色
private Color color;
// 定义随机数,保存颜色
private int t1, t2, t3;
// 设置开关
public void setStart(boolean start) {
this.start = start;
System.out.println(start);
}
// 得到开关当前值
public boolean getStart() {
return start;
}
// 得到当前的X Y值
public int getX() {
return X;
}
public int getY() {
return Y;
}
// 得到当前的半径值
public int getRadius() {
return radius;
}
// 得到当前的画布对象
public Graphics getGra() {
return g;
}

// 重写run方法
public void run() {
java.util.Random rd = new java.util.Random();
if (start) {
// 设置小球的颜色以及速度
color = new Color(t1 = rd.nextInt(220), t2 = rd.nextInt(220),
t3 = rd.nextInt(220));
speedX = rd.nextInt(6) + 2;
speedY = rd.nextInt(6) + 3;
while (true) {
// 得到小球当前的坐标
moveXY();
// 延时
try {
Thread.sleep(50);
} catch (Exception e) {
}
// 擦除上次画的小球,画出本次小球
clear();
fill();
// 暂停时重绘小球
repaint();
}
}
}
// 小球的运动的方向
public void moveXY() {
if (start) {
if (X <= radius) {
directX = 1;
} else if (X >= 600 - radius) {
directX = 0;
}
if (Y <= radius + 70) {
directY = 1;
} else if (Y >= 600 - radius) {
directY = 0;
}
// 确定小球x方向上的运动方向
switch (directX) {
case 0:
X -= speedX;
break;
case 1:
X += speedX;
}
// 确定小球y方向上的运动方向
switch (directY) {
case 0:
Y -= speedY;
break;
case 1:
Y += speedY;
}
}
}
// 擦除小球
public void clear() {
if (directX == 1 && directY == 1) {
g.clearRect(X - speedX - 1, Y - speedY - 1, radius, radius);
} else if (directX == 1 && directY == 0) {
g.clearRect(X - speedX - 1, Y + speedY + 1, radius, radius);
} else if (directX == 0 && directY == 1) {
g.clearRect(X + speedX + 1, Y - speedY - 1, radius, radius);
} else if (directX == 0 && directY == 0) {
g.clearRect(X + speedX + 1, Y + speedY + 1, radius, radius);
}
}
// 画小球
public void fill() {
int t = radius,temp=t1;
for (int i = 0; i < radius; i++) {
temp=temp+10;
if (temp < 256 && t2 < 256 && t3 < 256) {
g.setColor(new Color(temp, t2, t3));
g.fillOval(X + i, Y + i, t--, t--);
}
}
}
// 暂停时的重绘
public void repaint() {
if (!start) {
int t = radius,temp=t1;
for (int i = 0; i < radius; i++) {
temp=temp+10;
if (temp < 256 && t2 < 256 && t3 < 256) {
g.setColor(new Color(temp, t2, t3); g.fillOval(X + i, Y + i, t--, t--);
}
}
}
}
}
完成以上代码,一个简单的弹球项目就完成了,能实现的功能有:加入一个球在窗体内运动(如下加入三个球):



让窗体上所有的球静止
让窗体上所有的球开始运动
删除最后一次执行的小球(原本三个球只剩下了两个):




在开头曾经说到传画布的问题,在以前的项目里得出的经验是在窗体类中得到其画布,传入到监听器中,又将监听器中的画布传入到线程中。而本代码的思路却有所不同,是先将窗体随想传入到监听器中,再在监听器中通过drawThread(this.jf.getGraphics());语句使线程获得画布,这样有区别吗。答案是毫无疑问的,有!
大家可以试一试,如果使用传统方法,在执行多个小球运动时,会出现不和谐的印记(就像是没有擦干净,此处不再附图),而用本代码的方法将解决该问题。
这是为什么呢。
如果使用传统方法,将窗体的画布直接传入线程,那么多个线程对像将在同一个画布上执行方法,这样会出现线程中经常出现的资源共享的问题,但是,用本代码的方法,每次传入的画布是  窗体对象.getGraphics(),实际上,多次调用getGraphics()方法,得到的画布将不是同一个画布,这样就解决了资源共享的问题。
当然,该程序还有很多的不足,如代码不精炼,没有添加背景,区域大小不能随窗体的扩大而改变,没有球与球之间碰撞的效果,当然在后续时间我将完成这一任务。
  • 大小: 22.7 KB
  • 大小: 20.1 KB
分享到:
评论

相关推荐

    世上最简单的C#弹球游戏

    世上最简单的C#弹球游戏。线程基础,委托与事件。

    Java入门-系列游戏开发-弹球

    本次课程通过弹球游戏来学习Java中的多线程及图形界面知识,让初学JAVA编程的朋友,对多线程及图形界面有一个初步的了解。本次课程是JAVA基础系列课程中的一节。通过简单有趣的内容来完成JAVA的学习,是本课程追求的...

    JAVA大作业1——弹球小游戏.zip

    其中,简单对应一个球,速度设置为30,即对应线程暂停30/1000秒; 中等对应两个球,速度设置为40,即对应线程暂停40/1000秒; 困难对应两个球,速度设置为30,即对应线程暂停30/1000秒。 通过操作鼠标移动界面下方...

    疯狂Java讲义(第三版)-项目源代码

    ball: 第4章 桌面弹球 tetris: 第5章 俄罗斯方块 image: 第6章 仿Windows画图 linkgame: 第7章 单机连连看 editor: 第8章 简单Java IDE工具 book: 第9章 图书进存销系统 transaction: 第10章 ...

    疯狂java实战演义(pdf+codes)

    ball: 第4章 桌面弹球 tetris: 第5章 俄罗斯方块 image: 第6章 仿Windows画图 linkgame: 第7章 单机连连看 editor: 第8章 简单Java IDE工具 book: 第9章 图书进存销系统 transaction: 第10章 事务跟踪...

    java课程设计实战项目及课后练习

    ball: 第4章 桌面弹球 tetris: 第5章 俄罗斯方块 image: 第6章 仿Windows画图 linkgame: 第7章 单机连连看 editor: 第8章 简单Java IDE工具 book: 第9章 图书进存销系统 transaction: 第10章 ...

    疯狂Java实战演义 配书光盘

    ball: 第4章 桌面弹球 tetris: 第5章 俄罗斯方块 image: 第6章 仿Windows画图 linkgame: 第7章 单机连连看 editor: 第8章 简单Java IDE工具 book: 第9章 图书进存销系统 transaction: 第10章 ...

    疯狂Java实战演义 项目实战源码 全部源代码 共23个章节.rar

    ball: 第4章 桌面弹球 tetris: 第5章 俄罗斯方块 image: 第6章 仿Windows画图 linkgame: 第7章 单机连连看 editor: 第8章 简单Java IDE工具 book: 第9章 图书进存销系统 transaction: 第10章 ...

    疯狂java实战演义 光盘源码

    ball: 第4章 桌面弹球 tetris: 第5章 俄罗斯方块 image: 第6章 仿Windows画图 linkgame: 第7章 单机连连看 editor: 第8章 简单Java IDE工具 book: 第9章 图书进存销系统 transaction: 第10章 事务跟踪...

    疯狂Java讲义(第2版)光盘

    ball: 第4章 桌面弹球 tetris: 第5章 俄罗斯方块 image: 第6章 仿Windows画图 linkgame: 第7章 单机连连看 editor: 第8章 简单Java IDE工具 book: 第9章 图书进存销系统 transaction: 第10章 事务跟踪...

    java se部分,15小项目

    图片浏览器,桌面弹球,俄罗斯方块,仿windows画图,单机连连看,简单java ide工具,图书进销存系统,事物跟踪系统,多线程下载工具,邮件客户端,mysql管理器,自己开发的ioc容器,仿qq游戏大厅。

    javase实例源码(15个综合例子)

    第4章_桌面弹球 第5章 俄罗斯方块 第6章_仿Windows画图 第7章_单机连连看 第8章_简单Java_IDE工具 第9章_图书进存销系统 第10章_事务跟踪系统 第11章_多线程下载工具 第12章_邮件客户端 第13章_MySQL管理器 第14章_...

    Java项目实例

    4.桌面弹球;5.俄罗斯方块;6.仿 Windows 画图;7.单机连连看;8.简单 Java IDE 工具;9.图书进存销系统;10.事务跟踪系统;11.多线程下载工具;12.邮件客户端;13.MySQL 管理器;14.自己开发 IoC 容器;15.仿 QQ ...

    JAVA 范例大全 光盘 资源

    实例168 三维弹球游戏(Java 3D) 498 实例169 贪吃的小蛇 502 实例170 有趣的拼图游戏 510 实例171 滚动的文字 517 实例172 简单的GIF动画效果 519 实例173 简单的声音播放 522 实例174 多媒体播放器 526 ...

    疯狂java实战演义

    第4章_桌面弹球.doc 第5章_俄罗斯方块.doc 第6章_仿Windows画图.doc 第7章_单机连连看.doc 第8章_简单Java_IDE工具.doc 第9章_图书进存销系统.doc 第10章_事务跟踪系统.doc 第11章_多线程下载工具.doc 第12章_邮件...

    Java JDK实例宝典

    2 三维弹球 11. 3 贪吃蛇游戏 11. 4 Java声音处理 11. 5 媒体播放器 第12章 反射 12. 1 instanceof操作符 12. 2 获取类的信息 12. 3 动态调用类的方法 第13章 网络编程 13. 1 ...

    java jdk实列宝典 光盘源代码

    三维弹球,BouncingB.java; 贪吃蛇游戏SnakeModel.java; java的声音处理,介绍java中如何处理声音,包括实现响铃,播放wav,au等音频文件,以及控制声音的大小和音量,Beep.java; 媒体播放器,JMFMediaPlayer.java...

    java俄罗斯方块源码-javase.demo:javase示例子javase演示

    桌面弹球 tetris: 第5章 俄罗斯方块 image: 第6章 仿Windows画图 linkgame: 第7章 单机连连看 editor: 第8章 简单Java IDE工具 book: 第9章 图书进存销系统 transaction: 第10章 事务跟踪系统 flashget:...

    疯狂java讲义课后习题答案

    第四章 桌面弹球 第五章 俄罗斯方块 第六章 仿windows画图 第七章 单机连连看 第八章 简单java ide工具 第九章 图书进存销系统 第十章 事物跟踪系统 第十一章 多线程下载工具 第十二章 邮件客户端 第十三章 Mysql...

Global site tag (gtag.js) - Google Analytics