java 雷霆战机游戏 飞机大战 全过程教学+免费素材(附全部源代码)

这个游戏已是我第二次编写了,之前写过一个简易版的飞机大战类似demo。这次在上一次基础上添加了许多元素,增添了可玩性。 游戏效果图如下:

 

java 雷霆战机游戏 飞机大战 全过程教学+免费素材(附全部源代码)_第1张图片

java 雷霆战机游戏 飞机大战 全过程教学+免费素材(附全部源代码)_第2张图片

java 雷霆战机游戏 飞机大战 全过程教学+免费素材(附全部源代码)_第3张图片

游戏是有背景音乐和打击音效的,十分炫酷。那么接下来,我将编写此游戏的全过程做一遍详细介绍,解释部分核心效果实现代码,只要读者此时具备基础的java语法知识,我相信一定可以非常轻松的编写出一款属于自己的雷霆战机游戏。(大神可跳过,直接看源代码)

话不多说,我们直接开始:

一、首先理清编写思路,利用javaOOP面对对象思想分析游戏:

 游戏界面组成部分无非是:玩家飞机、敌方飞机、子弹、背景、爆炸效果等。利用OOP思想创建 Class

java 雷霆战机游戏 飞机大战 全过程教学+免费素材(附全部源代码)_第4张图片【如此图,这是我创建的对象类。】

二、需要将对象一一添加到面板中:

首先将背景图片绘制到面板中:代码如下

package com.my.plane;

import java.awt.Graphics;
import java.awt.image.BufferedImage;

import util.ImageUtil;

public class Background {
	BufferedImage bg=ImageUtil.img.get("bg.jpg");
	BufferedImage bg1=ImageUtil.img.get("bg_meitu_1.jpg");
	int by=0;
	public void drawbg(Graphics g) {
		if(GameJPanel.gameover) {
		g.drawImage(bg1,0,0,null);
		
		}
		else {
		g.drawImage(bg,0,by,null);
		g.drawImage(bg,0,by-ImageUtil.img.get("bg.jpg").getHeight(),null);
	}
	}
	public void move() {	
		this.by+=2;
		if(by>=ImageUtil.img.get("bg.jpg").getHeight())
			by=0;
		
	}
}

【每次重绘将背景图片向下移动2个像素,即可实现飞机移动效果,绘制两张,以免出现面板空白】

重写JPanel  paint()方法将各个元素添加到面板中   核心代码如下:

public void paint(Graphics g) {
		
		bgck.drawbg(g);//绘制背景
		plane.drawplane(g);//绘制玩家飞机
		
		for(int i=0;i

【希望读者编写程序时,也将代码注释标写清楚,否则在程序出错时没有头绪将是很糟糕的事情,本人初期就深受其害】

paint()方法中创建元素对象,并调用对象类中的绘制方法实现 将元素添加到面板中。我以玩家飞机类为例,介绍元素对象类的编写:

我这里玩家飞机类为Plane

定义对象类十分简单且易于理解:  只需要定义 Plane 的 x,y坐标,并通过drawImage将对象元素绘制到面板中即可,代码如下:

package com.my.plane;

import java.awt.Graphics;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.util.LinkedList;

import util.ImageUtil;

public class Plane {
      int px;
      int py;
	  int pw;
	  int ph;
	  int count=0;
	 
	  
	  BufferedImage []pimage= {ImageUtil.img.get("success.png"),ImageUtil.img.get("success1.png")};
	  Plane() {
		
		this.pw=pimage[0].getWidth();
		this.ph=pimage[0].getHeight();	
		this.px=GameJFrame.jx/2-pw/2;//飞机的坐标定义面板的正下方
		this.py=GameJFrame.jy-ph+50;
		
	}
	  public void drawplane(Graphics g) {
		  if(GameJPanel.gameover) { //这里我是用来判断游戏结束时绘制死亡效果的 ,读者可以暂时忽略
				g.drawImage(ImageUtil.img.get("die2.png"),px,py,null);}
			else {
		 
		  g.drawImage(pimage[count], px, py, null);
		  count++;
		  if(count>1) count=0;
	 }
}
}

 

 

【我这里定义了一个ImageUtil类,此类作为API工具类将所有需要使用的图片读取到内存中,方便读取,提高游戏性能,代码如下:】

package util;

import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.imageio.ImageIO;

public final class ImageUtil {
	
	public static Mapimg=new HashMap();//BufferedImage:内存中的图片对象
	
	static{
		File file=new File("img");
		File [] fs=file.listFiles();
		for(File f:fs) {
			//通过当前的文件名作为HashMap的key
			String s=f.getName();
			//将读取到的文件对象 作为BufferedImage存储
			try {
				BufferedImage i=ImageIO.read(f);
				img.put(s, i);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	

 

 你可能注意到,Plane 类中元素的图片有两张,这两张图片在线程中反复重绘,可使飞机更加立体生动。若你有更好的方法实现这个效果,可以忽略。或可忽略立体效果,即只认定飞机元素只有一张图片,将图片绘制于面板中即可。

 

至于 Enemy(敌方飞机) Boom  Bullet 等 类实现方法大同小异,基本一致,代码如下:

Enemy类

package com.my.plane;

import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.util.Random;

import util.ImageUtil;

public class Enemy {
	int []ex=new int[4];
	int []ey=new int[4];
	int []ew=new int[4];
	int []eh=new int[4];
	
	int count=0;
	BufferedImage []enemy=   {ImageUtil.img.get("s2_1.png"),
			                 ImageUtil.img.get("s2_2.png"),
			                 ImageUtil.img.get("s2_2.png"),ImageUtil.img.get("airplane.png")};
	Enemy(int x,int x1,int x2,int x3,int y,int y1,int y2,int y3){
		this.ex[0]=x;
		this.ex[1]=x1;
		this.ex[2]=x2;
		this.ex[3]=x3;
		this.ey[0]=y;	
		this.ey[1]=y1;
		this.ey[2]=y2;
		this.ey[3]=y2;
		this.ew[0]=ImageUtil.img.get("s2_1.png").getWidth();
		this.ew[1]=ImageUtil.img.get("s2_2.png").getWidth();
		this.ew[2]=ImageUtil.img.get("s2_2.png").getWidth();
		this.ew[3]=ImageUtil.img.get("airplane.png").getWidth();
		this.eh[0]=ImageUtil.img.get("s2_1.png").getHeight();
		this.eh[1]=ImageUtil.img.get("s2_2.png").getHeight();
		this.eh[2]=ImageUtil.img.get("s2_1.png").getHeight();
		this.eh[3]=ImageUtil.img.get("airplane.png").getHeight();
		
		
								
			
	}

	public void drawEnemy(Graphics g) {
		if(GameJPanel.gameover) {for(int i=0;i<4;i++) {
			g.drawImage(ImageUtil.img.get("07.png"),ex[i],ey[i],null);}}
		else {
	for(int i=0;i<4;i++)
		g.drawImage(enemy[i],ex[i],ey[i],null);
		
	}
		}
	public void move(int y,int y1,int y2,int y3) {
		
		this.ey[0]=y;
		this.ey[1]=y1;
		this.ey[2]=y2;
		this.ey[3]=y3;
	}
}

Bullet类

package com.my.plane;

import java.awt.Graphics;
import java.awt.image.BufferedImage;

import util.ImageUtil;

public class Bullet {
	int []bx=new int[2];
	int []by=new int[2];
	int []bw=new int[2];
	int []bh=new int[2];
    boolean bullet1=false; //这里我设置一个bullet1绑定到键盘事件中,当按下“J”键可切换子弹
    boolean bullet2=false;
	BufferedImage []bullet={ImageUtil.img.get("myb_3.png"),
            ImageUtil.img.get("feidan.png")};
	Bullet(int x,int x1,int y,int y1){
		this.bx[0]=x;
		this.bx[1]=x1;
		this.by[0]=y;
		this.by[1]=y1;
		
	}
	public void drawBullet(Graphics g) {
		 if(bullet1) g.drawImage(bullet[1],bx[0],by[0],null);
		 else  g.drawImage(bullet[0],bx[1],by[1],null);
	}
	public void  move() {
		by[0]-=5;
		by[1]-=5;
	}
}

Boom 类

package com.my.plane;

import java.awt.Graphics;
import java.awt.image.BufferedImage;

import util.ImageUtil;

public class Boom {
	int ox;
	int oy;
	int count=0;
	
	BufferedImage [] boom= {ImageUtil.img.get("01.png"),ImageUtil.img.get("02.png"),ImageUtil.img.get("03.png"),
			ImageUtil.img.get("04.png"),ImageUtil.img.get("05.png"),
			ImageUtil.img.get("06.png"),ImageUtil.img.get("07.png")};
	
	
	Boom(int x,int y){
		this.ox=x;
		this.oy=y;
	}
	public void drawBoom(Graphics g) {
	
		
		g.drawImage(boom[count], ox, oy, null);
		count++;
		if(count>7) count=0;
	
		
	}
	

}

【boom 类定义了七张图片,这七张图片反复重绘即可实现动态的爆炸视觉效果】

Music类  代码如下

package com.my.plane;

import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;

public class Music {
	File file1=new File("music\\game_music.wav");
	File file2=new File("music\\bullet.wav");
	File file3=new File("music\\enemy1_down.wav");
	AudioClip bgmusic=null;
	AudioClip bulletmusic=null;
	AudioClip boommusic=null;
	Music(){
		
		
		try {
			bgmusic=Applet.newAudioClip(file1.toURI().toURL());
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			bulletmusic=Applet.newAudioClip(file2.toURI().toURL());
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		try {
			boommusic=Applet.newAudioClip(file3.toURI().toURL());
		} catch (MalformedURLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}

这里我设置了三种音乐,分别为背景音乐,子弹发射音效,爆炸音效。

3、设置调用线程,完成所有对象类元素的重绘,实现动态效果画面

我这里直接用面板实现Runnable接口, 在面板中添加线程。

面板类的全部代码如下: 

package com.my.plane;

import java.awt.Graphics;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.image.BufferedImage;
import java.util.LinkedList;
import java.util.Random;

import javax.swing.JPanel;


import util.ImageUtil;

public class GameJPanel extends JPanel implements Runnable,KeyListener{
	Plane plane=new Plane();//这是玩家飞机
	Background bgck=new Background();
	Music music=new Music();
	
	LinkedList allEnemy=new LinkedList();//这是敌方飞机
	LinkedList allBoss=new LinkedList();
	LinkedList allBullet=new LinkedList();
	LinkedList allBoom=new LinkedList();
	//用这个四个bool类型来判断 plane(我方飞机)是否移动
	boolean left=false;
	boolean right=false;
	boolean up=false;
	boolean down=false;
	boolean bullet1=false;//用来选择子弹
	public static boolean gameover=false;
	
	
	//*******************
	
	int count=0; //计数器
	int count1=0;
	int count2=0;
	int over=0;
	
	Random rand=new Random();//用来产生随机数
	GameJPanel(){
		this.setFocusable(true);
		this.addKeyListener(this);
		music.bgmusic.loop();
		
		
	}
	public void paint(Graphics g) {
		
		bgck.drawbg(g);//绘制背景
		plane.drawplane(g);//绘制玩家飞机
		
		for(int i=0;i= GameJFrame.jx)  plane.px=20;
		if(plane.px<=0) plane.px=GameJFrame.jx;
		if(plane.py>=GameJFrame.jy-55) plane.py=GameJFrame.jy-55;
		if(plane.py<=0) plane.py=0;
	//***************玩家飞机设置到此结束***************************
		
    //***************************下面是增加敌方的飞机**********
		if(count>=20) {
			allEnemy.add(new Enemy(rand.nextInt(GameJFrame.jx-20),
					rand.nextInt(GameJFrame.jx-20),
					rand.nextInt(GameJFrame.jx-20),rand.nextInt(GameJFrame.jx-20),
					-40,-10,-15,-400));
			
			count=0;
		}
	//********************************************

	//*******************设置敌方飞机的移动**********
		for(int i=0;iGameJFrame.jy&&now.eh[1]>GameJFrame.jy&&now.eh[2]>GameJFrame.jy&&
					now.eh[3]>GameJFrame.jy) {
				allEnemy.remove(i);
			}
				
		}
				
  //********************敌方飞机设置到此结束*************
		
//**********************下方是添加boss**********
		if(count1>=400) {
			allBoss.add(new Boss(rand.nextInt(GameJFrame.jx-500),-20));
			count1=0;}
	//********************************************
			for(int i=0;iGameJFrame.jy) {
					allBoss.remove(i);
	//*****************************BOSS类设置到此结束************		
				}
			}
			//*****************************BOSS类设置到此结束************	
		
		//*********下面是子弹类设置*****	
			int v=90;
		   if(bullet1) {
			   v=20;
		   
		   }
			if(count2>=v) {
				allBullet.add(new Bullet(plane.px+plane.pimage[0].getWidth()/2-10,
						                 plane.px+plane.pimage[0].getWidth()/2-45,
						                 plane.py, plane.py  ));
				music.bulletmusic.play();
				count2=0;
			}
			for(int i=0;i=7) {
				allBoom.remove(i);
				
			}
			}		
			over++;
			//这里当敌方飞机与玩家飞机相撞则宣布 gameover
		if(over>500) {	for(int i=0;ir2x+r2w||r1x+r1wr2y+r2h||r1y+r1h

【面板中无非实现两个效果一:使用线程改变各类对象元素的坐标,调用repaint实现元素坐标重绘,二:将飞机类 X Y 坐标的移动绑定到键盘事件上,实现键盘 wasd 控制上下左右。 代码虽长,但很容易理解。】

此时只需要创建一个窗口类将面板添加进去即可,窗口代码如下

package com.my.plane;

import java.applet.Applet;
import java.applet.AudioClip;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;

import javax.swing.JFrame;

import util.ImageUtil;

public class GameJFrame extends JFrame{
		GameJPanel gamePanelnew =new GameJPanel();
		Thread move=new Thread(gamePanelnew);
		
		
		public static int jx=ImageUtil.img.get("bg.jpg").getWidth();
		public static int jy=ImageUtil.img.get("bg.jpg").getHeight();
	@SuppressWarnings("deprecation")
	GameJFrame(){
		this.setTitle("--雷霆战机--(自写原创源码,作者See:QQ:3492625357)");
		this.setSize(jx, jy+90);
		this.setLocationRelativeTo(null);	
		this.setVisible(true);
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	  this.add(gamePanelnew);		
	  
	}

	}

  这时候随便创建一个游戏入口类即主类,创建这个窗口即可

package com.my.plane;

import javax.swing.JFrame;

import util.ImageUtil;

public class Game_Main {
	public static void main(String[] args) {
		JFrame game=new GameJFrame();
				
	}

}

 到这里,所有的项目就大功告成了!!这时候运行你的主类,就可以玩属于你自己雷霆战机啦!是不是有 原来如此的感受呢。

看似华丽的背后,仅仅只是一行行简单的代码实现的。加油!!!

最后我已经将有所有源代码和游戏所需要的素材全部打包了,这些素材是我在网络上找了很多的素材的合集,内容非常丰富,如果有需要的,可以添加我的  QQ3492625357 

原创不易,你阅读我文章亦如你与我交谈一般,交谈即为交友,朋友,离别之际请给予你的朋友一个赞,好吗! 后会有期!

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(java 雷霆战机游戏 飞机大战 全过程教学+免费素材(附全部源代码))