Java多线程游戏仿真实例分享
这是一篇学习分享博客,这篇博客将会介绍以下几项内容:
1、如何让一个程序同时做多件事?(多线程的创建、多线程的应用)
2、如何让小球在画面中真实地动起来?(赋予小球匀速直线、自由落体、上抛等向量运动)
3、多线程游戏仿真实例分享(飞机大战、接豆人、双线挑战三个游戏实例)
- 涉及的知识点有:多线程的应用、双缓冲绘图、小球的向量运动、游戏的逻辑判断、键盘监听器的使用、二维数组的使用、添加音乐效果等
游戏效果:
怎么样?如果觉得还不错的话就请继续看下去吧!
热身
第一步:创建画布
- 心急吃不了热豆腐,我们先从最简单的创建画布开始。
首先我们创建一个窗体,然后设置一些参数,从窗体中取得画笔,尝试在画布中心画一个图形,以下是参考代码:
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;import javax.swing.JButton;
import javax.swing.JFrame;public class Frame {//声明画布对象public Graphics g;//主函数public static void main(String[] args) {//创建Frame类,然后运行showFrame函数Frame fr=new Frame();fr.showFrame();}//编写窗体显示的函数public void showFrame(){//创建窗体JFrame jf=new JFrame();jf.setTitle("小球演示");//设置窗体标题jf.setSize(900,900);//设置窗体大小jf.setDefaultCloseOperation(3);//设置点击窗体右上角的叉叉后做什么操作,这里的3代表点击叉叉后关闭程序jf.setLocationRelativeTo(null);//设置窗体居中显示FlowLayout flow=new FlowLayout();//设置窗体布局为流式布局jf.setLayout(flow);Mouse mou=new Mouse();//创建监听器对象JButton jbu=new JButton("START");//创建按钮,按下按钮后可以在画布中间画一个圆jbu.addActionListener(mou);//为按钮添加事件监听器jf.add(jbu);//设置窗体可见jf.setVisible(true);//从窗体获取画布g=jf.getGraphics();}//创建内部类监听器(也可以重新创建一个文件编写该类)class Mouse implements ActionListener{//重写按钮监听方法public void actionPerformed(ActionEvent e){//按下按钮后会执行这里的代码,下面这条代码指的是在画布中心画一个圆g.fillOval(300,300,300,300);}}
}
- 我们可以试着运行一下,出现以下图片所示效果第一步就成功了。
第二步:让小球动起来
- 用一段循环代码重复地画小球,每次循环让小球偏移一点距离
我们在上述代码中的监听器类Mouse的按钮监听器方法actionPerformed(ActionEvent e)下加这样一段代码
//重复画100次小球,每次横纵坐标分别加1
for(int i=0;i<100;i++){g.fillOval(300+i,300+i,30,30);/*下面这段代码的意思是每执行一次循环,系统暂停30毫秒,否则画的太快我们就观察不到小球在动了*/try{Thread.sleep(30);}catch(Exception ef){}
}
- 运行程序并点击START按键后,我们可以看到一个圆往右下角方向缓缓移动了一段距离,并且留下了痕迹。同时我们还可以发现,每次点击START键后,START键会保持被按下的状态,直至整个绘制小球的循环代码执行结束后才会弹起。这是因为我们现在写的程序只有一个线程在运行,所以只有当前任务执行完后按钮才能重新接收响应。想要解决这一点,可以利用下面将要讲到的多线程的原理。
那么,热身结束,下面让我们一起进入多线程的世界吧!
一、如何让一个程序同时做多件事情?
创建线程对象
- 创建线程对象我们需要用到Thread类,该类是java.lang包下的一个类,所以调用时不需要导入包。下面我们先创建一个新的子类来继承Thread类,然后通过重写run()方法(将需要同时进行的任务写进run()方法内),来达到让程序同时做多件事情的目的。
import java.awt.Graphics;
import java.util.Random;public class ThreadClass extends Thread{public Graphics g;//用构造器传参的办法将画布传入ThreadClass类中public ThreadClass(Graphics g){this.g=g;}public void run(){//获取随机的x,y坐标作为小球的坐标Random ran=new Random();int x=ran.nextInt(900);int y=ran.nextInt(900);for(int i=0;i<100;i++){g.fillOval(x+i,y+i,30,30);try{Thread.sleep(30);}catch(Exception ef){}}}
}
- 然后我们在主类的按钮事件监听器这边插入这样一段代码,即每按一次按钮则生成一个ThreadClass对象
public void actionPerformed(ActionEvent e){ThreadClass thc=new ThreadClass(g);thc.start();
}
- 在这里我们生成ThreadClass对象并调用start()函数后,线程被创建并进入准备状态,每个线程对象都可以同时独立执行run()方法中的函数,当run()方法中的代码执行完毕时线程自动停止。
接下来我们试着运行一下吧!
加入清屏功能,让小球真正的动起来
- 从上面的画图示范我们可以看出,小球在移动过程中是留下了轨迹的,那如果我只想看到小球的运动,不想看到小球的轨迹怎么办?
- 很简单,我们只需要每次画新的小球之前先给整个画布画上一个大的背景色矩形,把原来的图案覆盖即可。
让我们试着把run()方法中的代码改为下面这样:
public void run(){//获取一个随机数对象Random ran=new Random();//生成一对随机的x,y坐标设为小球的坐标,范围都在0-399int x=ran.nextInt(400);int y=ran.nextInt(400);for(int i=0;i<100;i++){//画一个能够覆盖画面中一块区域的白色矩形来清屏(把原来的笔迹都覆盖掉)g.setColor(Color.white);g.fillRect(300,300,300,300);g.setColor(Color.black);g.fillOval(200+x+i,200+y+i,30,30);try{Thread.sleep(30);}catch(Exception ef){}}
}
让我们试着运行一下
- 我们运行后发现,小球确实在中间的白色矩形区域内实现了不留轨迹的运动,但是小球闪烁的非常厉害。这其中的原因有两个,一个是多个线程对象同时运行会产生冲突,另一个是IO设备使用频率过高。后者我们在稍后的部分讲到用双缓冲绘图去解决,前者则通过下面的方法解决。
- 我们只在主类中创建一次ThreadClass对象。然后再创建一个列表,每次按按钮时将一组坐标存到这个列表中,最后通过run()方法中依次读出这个列表中的每一项并画出。
在主类中创建ThreadClass对象并运行(主类的showFrame方法中插入以下代码)
先创建坐标类
public class Location {public int x;public int y;public Location(int x,int y){this.x=x;this.y=y;}
}
然后在主类和ThreadClass类中创建列表
public ArrayList<Location> locs=new ArrayList<Location>();
然后在按钮监听器的方法下写入这段代码
public void actionPerformed(ActionEvent e){Random ran=new Random();int x=ran.nextInt(400);int y=ran.nextInt(400);Location loc=new Location(x,y);locs.add(loc);System.out.println(locs.size());
}
然后将画布g和列表locs传入创建的线程对象中,在主类的showFrame方法插入以下代码。
ThreadClass thc=new ThreadClass(g,locs);
thc.start();
重载Thread Class的run()方法
public void run(){while(true){g.setColor(Color.white);g.fillRect(300,300,300,300);for(int i=0;i<locs.size();i++){g.setColor(Color.black);//每次给小球坐标偏移一下int x=locs.get(i).x++;int y=locs.get(i).y++;g.fillOval(200+x,200+y,30,30);}try{Thread.sleep(30);}catch(Exception ef){}}
}
让我们再来试一下!
这下小球就没有闪烁的那么厉害了。
二、如何让小球在画面中真实地动起来?
- 众所周知,要想描述物体的运动状态,需要知道物体的三个物理量——位置、速度和加速度。我们只需要找到方法描述这三个物理量,便可以很好的模拟真实小球的运动。
在这里我们可以创建一个Vector类来描述位置、速度和加速度这三个物理量
public class Vector {public int x;public int y;public Vector(int x,int y){this.x=x;this.y=y;}//向量的加和运算public void add(Vector vec){this.x+=vec.x;this.y+=vec.y;}
}
然后我们再创建一个Ball类来代表小球(move函数是本部分的关键)
public class Ball {public Vector location;//位置public Vector speed;//速度public Vector acce;//加速度//构造器传参,设定小球的基本参数public Ball(Vector location,Vector speed,Vector acce){this.location=location;this.speed=speed;this.acce=acce;}//小球移动,这是整个部分的关键!!!每画完一次小球就调用一次move函数,让小球依据速度和加速度来改变一次位置public void move(){this.speed.x+=acce.x;//每调用一次move函数小球的速度就和加速度做一次加法this.speed.y+=acce.y;this.location.x+=speed.x;//每调用一次move函数小球的位置坐标就和速度做一次加法this.location.y+=speed.y;}
}
有了这两个类,我们就可以表示任意二维的向量运动了
- 比如说从原点出发,向右速度为5,向下加速度为10的平抛运动可以表示为
Vector location=new Vector(0,0);
Vector speed=new Vector(5,0);
Vector acce=new Vector(10,0);
- 从原点出发,向右速度为5,向上速度为10,向下加速度为10的上抛运动可以表示为
Vector location=new Vector(0,0);
Vector speed=new Vector(5,10);
Vector acce=new Vector(10,0);
- 利用这个原理,我们已经可以做出一点好玩的东西了!
试想一下,我们可以先给窗体添加一个鼠标监听器,然后获取鼠标按下和松开的点的坐标,然后沿着按下和松开的点连成的直线方向丢出一个小球,这样是不是就可以做一个投篮游戏了呢。 - 具体操作:给窗体加上鼠标监听器
Java多线程游戏仿真实例分享相关推荐
- java 代码压缩javascript_通过Java压缩JavaScript代码实例分享
通过移除空行和注释来压缩 javascript 代码 /** * this file is part of the echo web application framework (hereinafte ...
- iPhone游戏编程实例:分享成功游戏开发人员的锦囊妙计
iPhone游戏编程实例:分享成功游戏开发人员的锦囊妙计 基本信息 原书名: iPhone Games Projects 原出版社: Apress 作者: (美)Dave Mark PJ Cab ...
- Java多线程游戏实例分享2-雷火(手把手教你做个超炫酷的星际争霸)
观前提示: 本文涉及的小成果特别多,即使你不需要写一个和我完全相同的游戏,也可以按照需要查看某些特定功能的实现过程,说不定能够给您的程序开发带来一点小小的启发!PS:结合源代码阅读此博客更加高效. 本 ...
- 基于Java多线程操作文件案例分享
场景描述:某文件夹下有很多文件和文件夹,要求读取出该文件夹下的所有文件,并将文本打印输出. 案例分析:假设该文件夹下有10个文件,那么我们将所有的文件遍历一遍打印输出就可以了.但如果有100个, 10 ...
- java多线程 游戏_java利用多线程和Socket实现猜拳游戏
本文实例为大家分享了利用多线程和Socket实现猜拳游戏的具体代码,供大家参考,具体内容如下 实例:猜拳游戏 猜拳游戏是指小时候玩的石头.剪刀.布的游戏.客户端与服务器的"较量", ...
- java多线程游戏设计-弹球游戏(包含全部代码)
目录 需求分析 3 1.1目的 3 1.2背景 3 系统设计 3 2.1 项目结构 3 2.2游戏初始化界面设计 4 2.3游戏开始界面设计 5 2.4游戏结束界面设计 5 系统实现 6 3.1 游戏 ...
- Java多线程编程系列-实例变量和线程安全
导语 上面说到了多线程的简单实现,编写了几个入门的小例子,这里我们来研究一下关于实例变量和线程安全的问题.在自定义的线程类中的实例变量针对其他线程可以有共享和不共享之分,下多个线程之间进行交互的时 ...
- java多线程买票实例
3个窗口同时买票 * * 同步: * 1:同步代码块 * synchronized(锁对象(唯一)){ * * -需要被同步的代码 * * } * 2:同步方法 * 修饰符 synchronized ...
- Java多线程之间访问实例变量
自定义线程类中的实例变量针对其他线程可以有共享与不共享之分,这在多个线程之间进行交互时是很重要的一个技术点. 图 1 所示为不共享数据的示例,图 2 所示为共享数据的示例. 例 1 如图 1 所示,在 ...
最新文章
- docker删除已经停止的容器
- Navicat使用Instant Client创建连接到Oracle数据库的正确姿势
- 【信息抽取】NLP中关系抽取的概念,发展及其展望
- sql语句的一些细节东西学起来还是很费劲的,希望以后注意下。算是经验吧
- Emoji表情符号兼容方案(适用ios,android,wp等平台)
- Linux中Shell脚本函数库的笔记
- 【Vue】v-bind v-model指令的使用(实现计算器效果)
- 打脸!《陈情令》付费资源遭泄漏 腾讯视频说好的技术保障呢?
- 读《富爸爸,穷爸爸》后感(四)
- 常见网站底部友情链接代码示例
- C语言文件重定向---“系统找不到指定的文件”
- 46 同位语和同位语从句(以及) to/at/for/with 用法搭配
- 小饶学编程之JAVA SE第二部分——Web 前端基础:09CSS3
- iOS模拟器运行报错Unable to install /xxx/build/ios/iphonesimulator/Runner.app
- 【Python免费网站】2021学习python 5个绝佳的网站,新手小白再也不怕学不会!
- 图片视频毛玻璃效果实现
- 无限地图生成的制作,一直跑酷一直爽!
- oracle定时清理aud$
- vue+element实现滚动公告栏效果
- Sentinel 2 MSI 波段组合
热门文章
- java 代码压缩javascript_通过Java压缩JavaScript代码实例分享