坦克大战java源码

mytank07.java文件
/**
 * 功能:坦克游戏的2.01
 * 1、画出我的坦克
 * 2、让我的坦克动起来
 * 3、让我的坦克按下空格(space)键发射子弹
 * 4、让我的坦克可以连发子弹(最多连发5颗子弹)
 * 5、打到敌人坦克,敌人坦克就消失
 * 6、加入坦克被击中爆炸的效果
 * 7、让敌人的坦克可以自由随机移动
 * 8、控制坦克在指定的MyPanel面板中移动,不可越界
 * 9、让敌人的坦克发射子弹
 * 10、当我的坦克被敌人子弹击中,我的坦克爆炸
 * 11、防止敌人坦克重叠运动
 * 12、可以分关--做一个开始的Panel,它是空的主要是提示关卡
 * 13、游戏可以暂停、继续--暂停时将子弹、坦克速度设为0,坦克方向不变
 * 14、可以记录玩家的成绩
 * 15、java如何操作声音文件
 */
package com.haiding.tank_7;
import java.awt.*; 
import java.awt.event.ActionEvent;//活动事件
import java.awt.event.ActionListener;//活动监听
import java.awt.event.KeyEvent;//键盘事件
import java.awt.event.KeyListener;//键盘监听
import java.io.File;//导入java.io包下的file类
import javax.imageio.ImageIO;//java图像处理
import javax.swing.*;
import java.util.*;//复杂的包
import javax.sound.sampled.*;//实现音频播放
public class MyTank07 extends JFrame implements ActionListener{   //定义mytank07这个子类,
	//定义组件
	MyPanel mp=null;    //都是java UI编程里的内容 31~45
	//定义一个开始面板
	MyStartPanel msp=null;
	//做出菜单
	JMenuBar jmb=null;
	//开始游戏
	JMenu jm1=null;
	JMenuItem jmi1=null;
	//退出游戏
	JMenuItem jmi2=null;
	//存盘退出
	JMenuItem jmi3=null;
	//接上局
	JMenuItem jmi4=null;
	
	public static void main(String[] args) {
		MyTank07 mt=new MyTank07(); //定义类的对象mt
	}
	//构造函数
	public MyTank07(){   //java子类构造器;其父类是JFrame
		//创建菜单及菜单选项
		jmb=new JMenuBar();
		jm1=new JMenu("游戏(G)");
		//设置快捷方式
		jm1.setMnemonic('G');
		jmi1=new JMenuItem("开始新游戏(N)");
		jmi1.setMnemonic('N');
		//对jmi1相应
		jmi1.addActionListener(this);//this是指向调用对象本身的引用名;this在java GUI中的作用?
		jmi1.setActionCommand("newgame");//作用就是另外设置一个字符串来判断你究竟选择的是哪一个组件,还是不懂啊
		
		jmi2=new JMenuItem("退出游戏(E)");
		jmi2.setMnemonic('E');
		jmi2.addActionListener(this);
		jmi2.setActionCommand("exit");
		
		jmi3=new JMenuItem("存盘退出(S)");
		jmi3.setMnemonic('S');
		jmi3.addActionListener(this);
		jmi3.setActionCommand("save");
		
		jmi4=new JMenuItem("继续游戏(C)");
		jmi4.setMnemonic('C');
		jmi4.addActionListener(this);
		jmi4.setActionCommand("congame");
		
		jm1.add(jmi1);
		jm1.add(jmi2);
		jm1.add(jmi3);  //  add()作用:在不同类间相互静态调用,类名.add()  //或则add()起到加入作用
		jm1.add(jmi4);
		jmb.add(jm1);
		this.setJMenuBar(jmb);
		
		//构建组件
		msp=new MyStartPanel();
		Thread t=new Thread(msp);
		t.start();
		this.add(msp);
		
		//设置JFrame窗体
		this.setTitle("坦克大战");//JFrame标题
		this.setSize(600, 500);//JFrame窗体大小
		this.setLocationRelativeTo(null);//在屏幕中心显示
		this.setVisible(true);//显示
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//退出并关闭JFrame
	}

	public void actionPerformed(ActionEvent e) {
		//对用户不同的点击,做出不同的处理
		if(e.getActionCommand().equals("newgame")){
			//创建战场面板
			mp=new MyPanel("newgame");
			//启动mp线程
			Thread ta=new Thread(mp);
			ta.start();
			//先删除旧的开始面板
			this.remove(msp);
			//加入组件
			this.add(mp);
			//监听
			this.addKeyListener(mp);  //键盘监听
			//显示,刷新JFrame
			this.setVisible(true);
		}else if(e.getActionCommand().equals("exit")){
			//用户点击了退出菜单
			//保存用户游戏记录数据
			Recorder.keepRecording();
			System.exit(0);
		}else if(e.getActionCommand().equals("save")){
			//用户点击保存菜单
			//保存击毁敌人的数量和敌人的坐标
			Recorder.setEts(mp.ets);
			Recorder.keepRecAndEnemyTank();
			System.exit(0);
		}else if(e.getActionCommand().equals("congame")){
			//继续上次游戏
			//创建战场面板
			mp=new MyPanel("congame");
			
			//启动mp线程
			Thread ta=new Thread(mp);
			ta.start();
			//先删除旧的开始面板
			this.remove(msp);
			//加入组件
			this.add(mp);
			//监听
			this.addKeyListener(mp);
			//显示,刷新JFrame
			this.setVisible(true);
		}
	}
}
//开始面板--起提示作用
class MyStartPanel extends JPanel implements Runnable{
	int times=0;
	public void paint(Graphics g){
		super.paint(g);
		g.setColor(Color.black);
		g.fillRect(0, 0, 400, 300);
		//提示信息
		if(times%2==0){
			g.setColor(Color.yellow);
			//开关信息的字体
			Font myFont=new Font("华文新魏", Font.BOLD, 30);
			g.setFont(myFont);
			g.drawString("Stage: 1", 150, 150);
		}	
	}

	public void run() {
		while(true){
			//休眠
			try {
				Thread.sleep(500);
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			times++;
			//重画
			this.repaint();
		}
	}
}

//我的面板Panel
class MyPanel extends JPanel implements KeyListener,Runnable{//MyPanel继承Jpanel面板,创建KeyListener键盘接口和Runnable线程接口
	//定义一个我的坦克
	Hero hero=null;
	//定义声音播放
	AePlayWave apw=null;

	//定义敌人的坦克组
	Vector ets=new Vector();
	Vector nodes=new Vector();
	
	//定义炸弹集合
	Vector bombs=new Vector();
	
	int enSize=3;//初始敌人坦克数量
	
	//定义爆炸图片
	Image image1=null;
	Image image2=null;
	Image image3=null;
		
	//构造函数
	public MyPanel(String flag){
		hero=new Hero(200, 270);//我的坦克初始位置
		//恢复游戏记录
		Recorder.getRecoring();
		if(flag.equals("newgame")){
			//播放开战声音
			apw=new AePlayWave("/Users/a1/eclipse-workspace/MyTank07/Monody.wav");
			apw.start();
			//初始化敌人的坦克
			for(int i=0;i6){
				g.drawImage(image1, b.x, b.y, 30, 30, this);
			}else if(b.life>3){
				g.drawImage(image2, b.x, b.y, 30, 30, this);
			}else {
				g.drawImage(image3, b.x, b.y, 30, 30, this);
			}
			//让b的生命值减少
			b.lifeDown();
			//如果炸弹生命值为0,就把该炸弹从bombs向量中去掉
			if(b.life==0){
				bombs.remove(b);
			}
		}
		
		//画出敌人的坦克
		for(int i=0;iet.x&&s.xet.y&&s.yet.x&&s.xet.y&&s.y

members.java文件

package com.haiding.tank_7;

import java.util.Vector;//Vector 可实现自动增长的对象数组。java.util.vector提供了向量类(vector)以实现类似动态数组的功能
import java.io.*;//导入java.io包
import javax.sound.sampled.*;//

//播放声音的类
class AePlayWave extends Thread {
	private String filename;
	public AePlayWave(String wavfile) {
		filename = wavfile;
	}

	public void run() {
		File soundFile = new File(filename);//导入音频文件
		AudioInputStream audioInputStream = null;
		try {
			audioInputStream = AudioSystem.getAudioInputStream(soundFile);
		} catch (Exception e1) {
			e1.printStackTrace();
			return;
		}

		AudioFormat format = audioInputStream.getFormat();
		SourceDataLine auline = null;
		DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);

		try {
			auline = (SourceDataLine) AudioSystem.getLine(info);
			auline.open(format);
		} catch (Exception e) {
			e.printStackTrace();
			return;
		}

		auline.start();
		int nBytesRead = 0;
		//这是缓冲
		byte[] abData = new byte[2048];

		try {
			while (nBytesRead != -1) {
				nBytesRead = audioInputStream.read(abData, 0, abData.length);
				if (nBytesRead >= 0)
					auline.write(abData, 0, nBytesRead);
			}
		} catch (IOException e) {
			e.printStackTrace();
			return;
		} finally {
			auline.drain();
			auline.close();
		}
	}
}

//记录恢复点
class Node{
	int x,y,direct;
	public Node(int x,int y,int direct){
		this.x=x;
		this.y=y;
		this.direct=direct;
	}
}

//记录类,同时也可以保存玩家的设置
class Recorder{
	//记录每关有多少敌人
	private static int enNum=20;
	//设置我有多少可用的人
	private static int myLife=3;
	//记录总共消灭了多少敌人的坦克
	private static int allEnNum=0;
	//从文件中恢复记录点
	private static Vector nodes=new Vector();
	
	private static FileWriter fw=null;
	private static BufferedWriter bw=null;
	private static FileReader fr=null;
	private static BufferedReader br=null;
	private static Vector ets=new Vector();
	
	//完成读取任务点任务
	public static Vector getNodesAndEnNums(){
		try {
			fr=new FileReader("e:\\tankgame\\tanksave.txt");   //放到其他其他下,可能无法读取点任务文件
			br=new BufferedReader(fr);
			String n="";
			//先读一行
			n=br.readLine();
			allEnNum=Integer.parseInt(n);		
			while((n=br.readLine())!=null){
				String []Recovery=n.split(" ");//split方法可以按一行字符中有多少个空间来返回数组
				Node node=new Node(Integer.parseInt(Recovery[0]),Integer.parseInt(Recovery[1]),Integer.parseInt(Recovery[2]));
				nodes.add(node);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}finally{
			try {
				br.close();
				fr.close();
			} catch (Exception e2) {
				e2.printStackTrace();
			}
		}
		return nodes;
	}
	
	//保存击毁敌人的数量和敌人坦克坐标、方向
	public static void keepRecAndEnemyTank(){
		try {
			//创建
			fw=new FileWriter("e:\\tankgame\\tanksave.txt");
			bw=new BufferedWriter(fw);
			bw.write(allEnNum+"\r\n");
			
			//保存当前还活着的敌人坦克坐标、方向
			for(int i=0;i getEts() {
		return ets;
	}

	public static void setEts(Vector ets) {
		Recorder.ets = ets;
	}
	
	//敌人坦克死亡就减少坦克数
	public static void reduceEnNum(){
		enNum--;
	}
	//当消灭敌人的时候
	public static void addEnNumRec(){
		allEnNum++;
	}
}

//炸弹类
class Bomb{
	//定义炸弹的坐标
	int x,y;
	int life=9;//炸弹的生命
	boolean isLive=true;
	public Bomb(int x,int y){
		this.x=x;
		this.y=y;
	}
	//减少炸弹生命值
	public void lifeDown(){
		if(life>0){
			life--;
		}else{
			this.isLive=false;
		}
	}
}

//子弹类
class Shot implements Runnable{
	int x,y,direct,speed=3;//初始子弹x,y坐标,direct子弹方向,speed子弹速度

	//子弹是否还活着
	boolean isLive=true;//默认为活着
	
	public Shot(int x,int y,int direct){
		this.x=x;
		this.y=y;
		this.direct=direct;
	}
	
	public void run(){
		while(true){
			try {
				Thread.sleep(50);//让子弹休息50毫秒,防止快速消费内存
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			switch(direct){
				case 0://向上
					y-=speed;
					break;
				case 1://向下
					y+=speed;
					break;
				case 2://向 左
					x-=speed;
					break;
				case 3://向右
					x+=speed;
					break;
			}
			//子弹何时死亡
			//判断该子弹是否碰到MyPanel面板的边缘
			if(x<0||x>400||y<0||y>300){
				this.isLive=false;
				break;
			}
		}
	}
}

//定义坦克类
class Tank{
	//表示坦克的X横坐标Y纵坐标
	int x=0,y=0;
	//direct坦克方向,0向上、1向下、2向左、3向右
	int direct=0;
	//坦克的速度
	int speed=1;
	//坦克颜色
	int color;
	
	boolean isLive=true;

	public Tank(int x,int y){
		this.x=x;
		this.y=y;
	}
	public int getX() {
		return x;
	}
	public void setX(int x) {
		this.x = x;
	}
	public int getY() {
		return y;
	}
	public void setY(int y) {
		this.y = y;
	}
	public int getDirect() {
		return direct;
	}
	public void setDirect(int direct) {
		this.direct = direct;
	}
	public int getSpeed() {
		return speed;
	}
	public void setSpeed(int speed) {
		this.speed = speed;
	}
	public int getColor() {
		return color;
	}
	public void setColor(int color) {
		this.color = color;
	}
}

//敌人坦克,把敌人坦克做成线程类
class EnemyTank extends Tank implements Runnable{
	int move=30;//敌人坦克移动步长(区域)
	int times=0;
	
	//定义一个向量,可以访问到MyPanel上所有敌人坦克
	Vector ets=new Vector();
	//定义一个向量,可以存放敌人的子弹
	Vector ss=new Vector();
	//敌人添加子弹,应在创建坦克和敌人的坦克子弹死亡后
	public EnemyTank(int x,int y){
		super(x,y);
	}
	//得到MyPanel的敌人坦克向量
	public void setEts(Vector tank){
		this.ets=tank;
	}
	
	//判断敌人坦克是否重叠
	public boolean isTouchOtherEnemy(){
		boolean b=false;

		switch(this.direct){
		case 0://敌人当前坦克向上
			//取出所有敌人坦克
			for(int i=0;i=et.x&&this.x<=et.x+20&&this.y>=et.y&&this.y<=et.y+30){
							return true;
						}
						if(this.x+20>=et.x&&this.x+20<=et.x+20&&this.y>=et.y&&this.y<=et.y+30){
							return true;
						}
					}
					//如果敌人同伴的坦克向左或向右
					if(et.direct==2||et.direct==3){
						//判断敌人当前坦克右轮与同伴坦克(向左或向右)的位置比较
						if(this.x>=et.x&&this.x<=et.x+30&&this.y>=et.y&&this.y<=et.y+20){
							return true;
						}
						if(this.x+20>=et.x&&this.x+20<=et.x+30&&this.y>=et.y&&this.y<=et.y+20){
							return true;
						}
					}
				}
			}
			break;
		case 1://敌人当前坦克向下
			for(int i=0;i=et.x&&this.x<=et.x+20&&this.y+30>=et.y&&this.y+30<=et.y+30){
							return true;
						}
						if(this.x+20>=et.x&&this.x+20<=et.x+20&&this.y+30>=et.y&&this.y+30<=et.y+30){
							return true;
						}
					}
					if(et.direct==2||et.direct==3){
						if(this.x>=et.x&&this.x<=et.x+30&&this.y+30>=et.y&&this.y+30<=et.y+20){
							return true;
						}
						if(this.x+20>=et.x&&this.x+20<=et.x+30&&this.y+30>=et.y&&this.y+30<=et.y+20){
							return true;
						}
					}
				}
			}
			break;
		case 2://敌人当前坦克向左
			for(int i=0;i=et.x&&this.x<=et.x+20&&this.y>=et.y&&this.y<=et.y+30){
							return true;
						}
						if(this.x>=et.x&&this.x<=et.x+20&&this.y+20>=et.y&&this.y+20<=et.y+30){
							return true;
						}
					}
					if(et.direct==2||et.direct==3){
						if(this.x>=et.x&&this.x<=et.x+30&&this.y>=et.y&&this.y<=et.y+20){
							return true;
						}
						if(this.x>=et.x&&this.x<=et.x+30&&this.y+20>=et.y&&this.y+20<=et.y+20){
							return true;
						}
					}
				}
			}
			break;
		case 3://敌人当前坦克向右
			for(int i=0;i=et.x&&this.x+30<=et.x+20&&this.y>=et.y&&this.y<=et.y+30){
							return true;
						}
						if(this.x+30>=et.x&&this.x+30<=et.x+20&&this.y+20>=et.y&&this.y+20<=et.y+30){
							return true;
						}
					}
					if(et.direct==2||et.direct==3){
						if(this.x+30>=et.x&&this.x+30<=et.x+30&&this.y>=et.y&&this.y<=et.y+20){
							return true;
						}
						if(this.x+30>=et.x&&this.x+30<=et.x+30&&this.y+20>=et.y&&this.y+20<=et.y+20){
							return true;
						}
					}
				}
			}
			break;
		}
		return b;
	}

	//重写run()函数
	public void run() {
		while(true){
			switch(this.direct){
			case 0://坦克正在向上移动
				for(int i=0;i0&&!this.isTouchOtherEnemy()){//判断敌人坦克向上走不会越界
						y-=speed;
					}
					try {
						Thread.sleep(50);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				break;
			case 1://向下移动
				for(int i=0;i0&&!this.isTouchOtherEnemy()){//判断敌人坦克向左走不会越界
						x-=speed;
					}
					try {
						Thread.sleep(50);
					} catch (Exception e) {
						e.printStackTrace();
					}
				}
				break;
			case 3://向右移动
				for(int i=0;i ss=new Vector();//Vector线程安全的集合类
	Shot s=null;
	
	public Hero(int x,int y){
		super(x,y);
	}
	//坦克开火
	public void shotEnemy(){

		switch(this.direct){//判断坦克方向来对应子弹运行方向
		case 0://向上
			//创建一颗子弹
			s=new Shot(x+10, y, 0);
			//将子弹加入到向量集中
			ss.add(s);
			break;
		case 1://向下
			s=new Shot(x+10, y+29, 1);
			ss.add(s);
			break;
		case 2://向左
			s=new Shot(x, y+10, 2);
			ss.add(s);
			break;
		case 3://向右
			s=new Shot(x+29, y+10, 3);
			ss.add(s);
			break;
		}
		//启动子弹线程
		Thread t=new Thread(s);
		t.start();
	}
	
	//坦克向上移动
	public void moveUp(){
		y-=speed*10;
	}
	//坦克向右移动
	public void moveRight(){
		x+=speed*10;
	}
	//坦克向下移动
	public void moveDown(){
		y+=speed*10;
	}
	//坦克向左移动
	public void moveLeft(){
		x-=speed*10;
	}
}
本人使用的是eclipse软件,代码中的图片文件、音频文件都丢失,固执行后可能没有爆炸效果,没有音频效果。忘谅解!

使用者可以替换掉其中的音频文件、图片文件。


你可能感兴趣的:(java)