Java中的线程及(简单飞机大战)实现
在讲到线程之前我们先聊一下程序,进程,线程这三者的概念:
程序是指为了实现特定目标或解决特定问题而用计算机语言编写的命令序列的集合。
程序存储在磁盘上,由一系列的文件+数据组成。
进程:程序运行起来之后就是一个进程
进程存在系统分配的内存里,并且进程之间可以进行通信。
而我们这里需要讲到的线程是进程中的一个独立运行的单位,是CPU执行的最小单位。
我们在使用记事本写程序时需要先执行Javac命令编译,将java程序编译成一个字节码class文件,然后再执行Java命令时JVM(Java虚拟机)就会启动线程,让线程调用main函数,线程根据main函数中的代码的顺序逐行执行。
那么同样的线程在哪里执行呢?
线程在cpu中执行,线程执行时所涉及到对象的属性和方法等数据都在内存中,电脑使用缓存存储线程所需要执行的数据。线程只会改变缓存中的数据而不会改变内存中的数据。
线程与进程不同,每个进程系统都会分配一定的内存空间,线程都是共享存储空间。
多线程就显而易见了就是指一个进程中有多个线程,能同时做多件事。
那么Java中如何实现线程呢?
1.实现Runnable接口
run();线程执行的方法
2.Thread类实现Runnable接口
run();线程执行的方法
start();方法线程的启动方法
接下来我们来讲一些简单的飞机大战的实现:
一、界面的实现
首先呢还是需要一个相对简单的界面
public class MainFrame extends JFrame implements Planeinte{
public static void main(String[] args) {
MainFrame mf=new MainFrame();
mf.initUI();
}
public void initUI(){
//设置窗体属性
this.setTitle("飞机大战V1.0");
this.setSize(600, 800);
this.setDefaultCloseOperation(3);
this.setLocationRelativeTo(null);
this.setVisible(true);
首先我们需要定义一个飞行物的类,用来定义它们的属性和方法
因为敌机和子弹都需要自动产生及运动,所以我们在这里需要三个线程,一个自动产生飞机,一个自动产生子弹,还有一个自动画子弹和飞机的类。
产生的飞机和子弹分别用数组队列来存储
线程一(自动产生飞机):
public void run(){
while(true){
if(true){
int x=rand.nextInt(mf.getWidth());
int y=0;
int speedX=rand.nextInt(5)+1;
int speedY=rand.nextInt(5)+1;
int blood=10;
boolean flag=false;
ImageIcon icon=new ImageIcon(this.getClass().getResource("敌机1.png"));
Plane plane=new Plane(x, y, speedX, speedY, blood, flag,icon);
list.add(plane);
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程二(自动产生子弹):
public void run(){
while(stopflag){
if(true){
int x=myplane.getX();
int y=myplane.getY();
int speedX=0;
int speedY=-40;
int blood=1;
boolean flag=true;
ImageIcon icon=new ImageIcon(this.getClass().getResource("bullet13.png"));
Plane bullet=new Plane(x, y, speedX, speedY, blood, flag,icon);
listb.add(bullet);
for(int i=1;i<list.size();i++){
Plane plane=list.get(i);
x=plane.getX();
y=plane.getY();
speedX=0;
speedY=20;
blood=1;
flag=false;
icon=new ImageIcon(this.getClass().getResource("bullet14.png"));
Plane bulletb=new Plane(x, y, speedX, speedY, blood, flag,icon);
listb.add(bulletb);
}
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
线程三(自动画飞机和子弹):
public void run(){
while(true){
if(g==null)
g=mf.getGraphics();
if(true&&g!=null){
if(y==0){
y=mf.getHeight()-icon.getIconHeight();
}
ig.drawImage(icon.getImage(), 0, y, mf);
y+=5;
for(int i=0;i<list.size();i++){
Plane plane=list.get(i);
plane.drawPlane(ig);
plane.movePlane(mf);
}
for(int j=0;j<listb.size();j++){
Plane bullet=listb.get(j);
bullet.drawPlane(ig);
bullet.bulletcrash();
}
mf.getGraphics().drawImage(img, 0, 0, mf);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
在这里如果我们直接画在JFrame窗体上,会导致有闪屏以及有残影的出现,为了解决这个问题,在这里我们采用双缓冲技术,就是我们不直接将对象画在窗体上,而是在这之前先创建一块次画布先依次在线程里将对象画在次画布上之后,再将整个次画布画在窗体上。
//创建次画布
Image img =mf.createImage(mf.getWidth(), mf.getHeight());
Graphics ig=img.getGraphics();
ImageIcon icon=new ImageIcon(this.getClass().getResource("背景0.jpg"));
int y=mf.getHeight()-icon.getIconHeight();
在得到所有飞机之后,我们在窗体主函数出先将我们要控制的飞机存入,并且给窗体加上监听以鼠标的拖动来控制我方飞机,也就是list.get(0);
ImageIcon icon=new ImageIcon(this.getClass().getResource("飞机1.png"));
Plane myplane=new Plane(300, 750, 0, 0, 100, true,icon);
list.add(myplane);
启动线程并添加监听:
PlaneAI pAI=new PlaneAI(this);
PlaneMoveDraw pmd=new PlaneMoveDraw(this);
pAI.start();
pmd.start();
PlaneListener pl=new PlaneListener();
this.addMouseListener(pl);
this.addMouseMotionListener(pl);