线程---简单弹球
一般的程序,就是从头至尾地执行代码,完成了一个方法,接下来完成后面紧接着的方法,但是,一般解决实际问题不会单纯地按顺序操作,很有可能在同一时间执行多种方法,就像一个人,在某一个时刻不会只做一件事,他可能一边听歌,一边写总结•••那么这样就需要用到多线程操作。
实现线程有两种方式,一种是继承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
分享到:
相关推荐
Java弹球小游戏是一款基于Java编程语言开发的简单游戏,它运用了多线程技术来实现游戏的流畅运行。在这个游戏中,通常会有至少两个线程在同时工作:一个是控制游戏主循环,另一个则处理用户输入或其他特定的游戏逻辑...
标题中的“多线程实例:桌面智能弹球小游戏”表明这是一个使用多线程技术开发的桌面应用程序,旨在提供一个互动的弹球游戏体验。在这个游戏中,小球具有一定的智能性,能够根据规则自行决策,而不仅仅是简单的物理...
MFC弹球游戏是利用MFC框架实现的一款简单但有趣的桌面游戏,它通过多线程技术提升游戏体验,使其运行更加流畅。 在MFC中,多线程编程是一项关键技能,尤其在需要同时处理多个任务或不希望主界面因后台处理而卡顿时...
Java弹球程序是一个基于Swing框架的简单图形用户界面(GUI)应用,它模拟了一个弹球在窗口内反弹的过程。该程序利用了Java AWT 和 Swing 的组件以及线程来实现动态效果。 ### 关键类介绍 #### 1. **`TanQiu` 类** ...
Java弹球项目是一种基于Swing库的简单游戏开发实例,非常适合初学者理解Swing框架以及基本的游戏编程概念。Swing是Java的一个图形用户界面(GUI)工具包,它提供了丰富的组件和功能,用于构建桌面应用程序。 在Java...
这个项目展示了如何使用Java语言来开发一个简单的2D游戏,涵盖了后端逻辑处理、图形用户界面(GUI)设计以及游戏规则的实现。以下是这个项目涉及的一些关键知识点: 1. **Java基础**:首先,你需要掌握Java的基础...
本Java程序是一个简单的弹球游戏实现,旨在帮助初学者理解Java编程中的基本概念和技术,尤其是线程的应用以及图形界面编程的基本方法。通过该程序,我们可以学习到如何在Java中创建动画效果、处理线程同步问题、使用...
【标题】"世上最简单的C#弹球游戏"是一个基于C#编程语言开发的简易游戏项目,它旨在介绍和实践线程基础、委托以及事件等关键概念。在C#编程中,这些是构建多任务应用程序和响应式用户界面的基础。 【描述】中提到的...
对于简单的矩形或圆形,可以使用轴对齐边界框(AABB)或圆心距离判断,更复杂的情况下则可能需要使用更精确的算法如分离轴定理(SAT)。 3. **砖块消除**:当弹球击中砖块时,砖块需要被消除。这个过程涉及状态管理...
Java弹球游戏是一款基于Java编程语言开发的简单游戏,它主要展示了如何利用Java Swing或JavaFX库创建图形用户界面(GUI)以及如何处理线程来实现动态的游戏效果。在这个游戏中,一个小球会在屏幕内弹来弹去,碰到...
Java 程序设计实验报告之弹球游戏实现 本实验报告的目的是掌握 ...本实验报告实现了一个完整的弹球游戏,掌握了 Java 语言的图形用户界面编程、事件处理、多线程编程等技术,并培养了独立查找资料、解决问题的能力。
"弹球程序"就是一个很好的例子,它展示了Java在实现简单但引人入胜的休闲游戏方面的潜力。 "打砖块"是一款经典的街机游戏,其基本玩法是控制一个板子来反弹弹球,避免球掉到底部,同时通过弹球击碎屏幕上排列的砖块...
Java桌面弹球游戏是一款基于Java编程语言开发的简单娱乐应用,它模拟了经典的弹球游戏,用户可以在计算机桌面上操作一个或多个弹球,通过控制挡板防止弹球落下。这款程序展示了Java在图形用户界面(GUI)设计和事件...
Java桌面弹球游戏是一款基于Java编程语言开发的简单游戏,它展现了Java在图形用户界面(GUI)编程中的应用。这个游戏通常包含以下关键知识点: 1. **Java基础**:首先,理解Java编程的基础至关重要,包括变量、数据...
【Android 弹球小游戏】是一款基于安卓平台的简单游戏,主要设计用于开发者进行技术实践,尤其是对于初学者,它提供了一个学习和理解Android开发中关键概念的实例。这款游戏的实现涉及了多个Android开发的重要知识点...
- 游戏中的状态管理(如小球是否开始运动,挡板是否吃到道具等)是通过布尔变量来控制的,这种状态管理方式简单易懂,但也需要注意避免状态冲突。 以上是根据标题、描述和部分内容分析出的桌面弹球游戏代码的主要...
Java弹球游戏是一种基于Java编程语言开发的简单游戏,它通常包括一个主界面,一个弹球,以及一些障碍物。这款游戏的设计目标是让初学者能够理解如何在Java中实现基本的游戏逻辑,同时也能吸引对编程感兴趣的玩家进行...
【Android Studio小游戏:弹球小游戏】是基于Android开发平台,使用Android Studio集成开发环境创建的一款简单而有趣的休闲游戏。这个游戏通常包含一个弹球和多个障碍物,玩家通过控制挡板来反射弹球,避免弹球掉落...
本次课程通过弹球游戏来学习Java中的多线程及图形界面知识,让初学JAVA编程的朋友,对多线程及图形界面有一个初步的了解。本次课程是JAVA基础系列课程中的一节。通过简单有趣的内容来完成JAVA的学习,是本课程追求的...
【标题】"无聊写的java弹球游戏"是一个Java编程项目,开发者通过编写代码实现了一个简单的弹球游戏。这个游戏可能是为了娱乐或学习Java编程而创建的。在Java编程中,这样的弹球游戏通常会涉及到基本的图形用户界面...