坦克大战游戏代码

坦克大战游戏

  • 主函数
  • 战场面板
  • 开始界面
  • 坦克父类
  • 敌方坦克
  • 我方坦克
  • 子弹
  • 爆炸效果
  • 数据存盘及恢复
  • 图片

主函数

package cn.wenxiao.release9;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;

public class GameMain extends JFrame implements ActionListener {
	// 战场面板
	WorldPanel mp = null;
	// 开始面板
	StartPanel sPanel = null;
	// 定义菜单栏
	JMenuBar jBar = null;
	// 定义菜单
	JMenu menu1 = null;
	// 定义菜单选项
	JMenuItem startMenuItem = null;
	// 保存退出游戏
	JMenuItem exitGaMenuItem = null;
	// 继续上局游戏
	JMenuItem continueGaMenuItem = null;
	// 退出而不保存
	JMenuItem exitWithoutSaveItem = null;

	public static void main(String[] args) {
		// TODO 主函数
		GameMain gameMain = new GameMain();
	}

	public GameMain() {
		// 创建开始页面的面板
		sPanel = new StartPanel();
		// 创建菜单栏
		jBar = new JMenuBar();
		// 创建菜单
		menu1 = new JMenu("游戏(G)");
		// 设置快捷方式
		menu1.setMnemonic('G');
		// 创建菜单项-开始新游戏
		startMenuItem = new JMenuItem("开始新游戏(N)");
		// 设置菜单项快捷方式
		startMenuItem.setMnemonic('N');
		// 创建菜单项继续上一局游戏
		continueGaMenuItem = new JMenuItem("继续上一局游戏(C)");
		continueGaMenuItem.setMnemonic('C');
		// 创建保存退出游戏菜单项
		exitGaMenuItem = new JMenuItem("保存并退出游戏(E)");
		// 设置保存退出项快捷方式
		exitGaMenuItem.setMnemonic('E');
		// 退出不保存
		exitWithoutSaveItem = new JMenuItem("退出不保存游戏(Q)");
		exitWithoutSaveItem.setActionCommand("quit");
		exitWithoutSaveItem.addActionListener(this);
		// 设置菜单项的监听
		startMenuItem.addActionListener(this);
		continueGaMenuItem.addActionListener(this);
		exitGaMenuItem.addActionListener(this);
		// 设置菜单项目的命令识别符
		startMenuItem.setActionCommand("new_game");
		continueGaMenuItem.setActionCommand("continue");
		exitGaMenuItem.setActionCommand("exit");
		// 将菜单项目添加至菜单中
		menu1.add(startMenuItem);
		menu1.add(continueGaMenuItem);
		menu1.add(exitGaMenuItem);
		menu1.add(exitWithoutSaveItem);
		// 将菜单添加至菜单栏中
		jBar.add(menu1);
		// 将面板添加至当前窗口
		this.add(sPanel);
		// 将开始页面的面板添加至新的线程中,并开启线程
		Thread starThread = new Thread(sPanel);
		starThread.start();
		// 将菜单栏添加至当前窗口上
		this.setJMenuBar(jBar);
		// 设置窗口大小
		this.setSize(800, 600);
		// 设置窗口可见
		this.setVisible(true);
		// 设置窗口关闭程序关闭
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		// TODO 重写菜单项目监听事件处理方式
		if (e.getActionCommand().equalsIgnoreCase("new_game")) {
			// 删除当前窗口显示的开始面板
			this.remove(sPanel);
			// 如果在战场运行过程中,玩家点击了开始新游戏,那么删除旧的游戏面板,开启新的面板
			if (mp != null) {
				this.remove(mp);
			}
			// 如果点击了“开始新游戏”的按钮,则创建战场面板
			mp = new WorldPanel();
			Recorder.setEnemyTankTotal(20);
			Recorder.setKilledNum(0);
			Recorder.setMyLife(3);
			// 开启战场面板的线程
			Thread mpThread = new Thread(mp);
			mpThread.start();
			// 将战场面板添加至当前窗口
			this.add(mp);
			// 注册战场面板的监听
			this.addKeyListener(mp);
			// 当前窗口刷新显示
			this.setVisible(true);
		} else if (e.getActionCommand().equals("exit")) {
			Recorder.saveData();
			System.exit(0);
		} else if (e.getActionCommand().equals("continue")) {
			Recorder.readData();
			// 删除当前窗口显示的开始面板
			this.remove(sPanel);
			// 如果在战场运行过程中,玩家点击了开始新游戏,那么删除旧的游戏面板,开启新的面板
			if (mp != null) {
				this.remove(mp);
			}
			// 如果点击了“开始新游戏”的按钮,则创建战场面板
			mp = new WorldPanel();
			// 开启战场面板的线程
			Thread mpThread = new Thread(mp);
			mpThread.start();
			// 将战场面板添加至当前窗口
			this.add(mp);
			// 注册战场面板的监听
			this.addKeyListener(mp);
			// 当前窗口刷新显示
			this.setVisible(true);
		}else if(e.getActionCommand().equals("quit")) {
			System.exit(0);
			
		}
	}
}

战场面板

package cn.wenxiao.release9;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Vector;

import javax.swing.JPanel;

public class WorldPanel extends JPanel implements KeyListener, Runnable {
	// 定义一个我的坦克
	MyTank myTank = null;
	int enemyTankbirth = 0;

	// 定义敌人的坦克集合
	Vector<EnemyTank> enemyTanks = new Vector<EnemyTank>();
	// 定义一个爆炸效果的集合
	Vector<Bomb> bombs = new Vector<Bomb>();
	Image image1 = null;
	Image image2 = null;
	Image image3 = null;

	int enemyCounts = 3;

	// 构造函数
	public WorldPanel() {
		myTank = new MyTank(260, 380, 0);
		// 初始化爆炸效果图片

		image1 = Toolkit.getDefaultToolkit().getImage(WorldPanel.class.getResource("/3.png"));
		image2 = Toolkit.getDefaultToolkit().getImage(WorldPanel.class.getResource("/2.png"));
		image3 = Toolkit.getDefaultToolkit().getImage(WorldPanel.class.getResource("/1.png"));

	}

	// 重画
	public void paint(Graphics graphics) {
		super.paint(graphics);
		graphics.fillRect(0, 0, 600, 400);
		// 绘制爆炸效果
		for (int i = 0; i < bombs.size(); i++) {

			Bomb curentBomb = bombs.get(i);

			if (curentBomb.life > 5) {
				graphics.drawImage(image1, curentBomb.x, curentBomb.y, 30, 30, this);

			} else if (bombs.get(i).life > 3) {
				graphics.drawImage(image2, curentBomb.x, curentBomb.y, 30, 30, this);
			} else {
				graphics.drawImage(image3, curentBomb.x, curentBomb.y, 30, 30, this);
			}
			curentBomb.lifeDown();
			if (curentBomb.life < 0) {
				bombs.remove(curentBomb);
			}
		}
		// 画出我方坦克
		if (myTank.isAlive) {
			this.drawTank(myTank.getX(), myTank.getY(), graphics, this.myTank.getDirect(), 0);
		}

		// 画出敌方坦克及敌人的子弹
		for (int i = 0; i < enemyTanks.size(); i++) {
			EnemyTank currentTank = enemyTanks.get(i);
			if (currentTank.isAlive) {
				this.drawTank(currentTank.getX(), currentTank.getY(), graphics, currentTank.direct, 1);
			}
			if (currentTank.isAlive == false) {
				enemyTanks.remove(i);
			}
			if (currentTank.bullets.size() > 0) {
				for (int j = 0; j < currentTank.bullets.size(); j++) {
					Bullet curBullet = currentTank.bullets.get(j);
					if (curBullet != null && curBullet.isAlive == true) {
						graphics.draw3DRect(curBullet.x, curBullet.y, 1, 1, false);
					}
					if (curBullet.isAlive == false) {
						currentTank.bullets.remove(curBullet);
					}
				}
			}
		}

		// 绘制子弹
		for (int i = 0; i < myTank.bullets.size(); i++) {
			Bullet currBullet = myTank.bullets.get(i);
			if (currBullet != null && currBullet.isAlive == true) {
				graphics.draw3DRect(currBullet.x, currBullet.y, 1, 1, false);
			}
			if (currBullet.isAlive == false) {
				myTank.bullets.remove(currBullet);
			}
		}
		this.paintInfo(graphics);
	}

	// 显示游戏信息的方法
	public void paintInfo(Graphics graphics) {
		this.drawTank(20, 430, graphics, 0, 1);
		this.drawTank(20, 480, graphics, 0, 0);
		graphics.setColor(Color.BLACK);
		Font font = new Font("微软雅黑", Font.BOLD, 20);
		graphics.setFont(font);
		graphics.drawString("剩余:" + Recorder.getEnemyTankTotal(), 40, 440);
		graphics.drawString("剩余:" + Recorder.getMyLife(), 40, 480);
		graphics.drawString("已击杀: " + Recorder.getKilledNum(), 610, 30);

	}

	// 判断是否被击中
	public void beHited(MyTank myTank, Vector<EnemyTank> enemyTanks) {
		// 判断我方坦克的方向
		// 取出敌方坦克
		for (int i = 0; i < this.enemyTanks.size(); i++) {
			EnemyTank enemyTank = enemyTanks.get(i);
			// 取出敌方坦克的每一颗子弹
			for (int j = 0; j < enemyTank.bullets.size(); j++) {
				Bullet currentBullet = enemyTank.bullets.get(j);
				switch (myTank.direct) {
				case 0:
				case 2:
					if (currentBullet.x > myTank.getX() - 10 && currentBullet.x < myTank.getX() + 10
							&& currentBullet.y > myTank.getY() - 15 && currentBullet.y < myTank.getY() + 15) {
						// 爆炸效果
						Bomb bomb = new Bomb(myTank.getX() - 15, myTank.getY() - 15);
						bombs.add(bomb);
						// 击中
						currentBullet.isAlive = false;
						myTank.isAlive = false;
						Recorder.myLifeDown();
					}
					break;
				case 1:
				case 3:
					if (currentBullet.x > myTank.getX() - 15 && currentBullet.x < myTank.getX() + 15
							&& currentBullet.y > myTank.getY() - 10 && currentBullet.y < myTank.getY() + 10) {
						// 爆炸效果
						Bomb bomb = new Bomb(myTank.getX() - 5, myTank.getY() - 5);
						bombs.add(bomb);
						// 击中
						currentBullet.isAlive = false;
						myTank.isAlive = false;
						Recorder.myLifeDown();
					}
					break;
				}

			}
		}

	}

	// 判断击中与否的方法
	public void hited(Bullet bullet, EnemyTank enemyTank) {
		// 判断敌机的方向
		switch (enemyTank.direct) {
		case 0:
		case 2:
			if (bullet.x > enemyTank.getX() - 10 && bullet.x < enemyTank.getX() + 10 && bullet.y > enemyTank.getY() - 15
					&& bullet.y < enemyTank.getY() + 15) {
				// 爆炸效果
				Bomb bomb = new Bomb(enemyTank.getX() - 15, enemyTank.getY() - 15);
				bombs.add(bomb);
				// 击中
				bullet.isAlive = false;
				enemyTank.isAlive = false;
				Recorder.enemyTankTotalDown();
				Recorder.killedNumUp();

			}
			break;
		case 1:
		case 3:
			if (bullet.x > enemyTank.getX() - 15 && bullet.x < enemyTank.getX() + 15 && bullet.y > enemyTank.getY() - 10
					&& bullet.y < enemyTank.getY() + 10) {
				// 爆炸效果
				Bomb bomb = new Bomb(enemyTank.getX() - 5, enemyTank.getY() - 5);
				bombs.add(bomb);
				// 击中
				bullet.isAlive = false;
				enemyTank.isAlive = false;
				Recorder.enemyTankTotalDown();
				Recorder.killedNumUp();

			}
			break;
		}
	}

	// 画出坦克的函数
	public void drawTank(int x, int y, Graphics graphics, int direct, int type) {
		// 判断需要画的坦克的类型
		switch (type) {
		case 0:
			graphics.setColor(Color.CYAN);
			break;
		case 1:
			graphics.setColor(Color.YELLOW);
			break;
		}
		// 判断方向
		switch (direct) {
		case 0:
			graphics.fill3DRect(x - 10, y - 15, 5, 30, false);
			graphics.fill3DRect(x + 5, y - 15, 5, 30, false);
			graphics.fill3DRect(x - 5, y - 10, 10, 20, false);
			graphics.fillOval(x - 5, y - 5, 10, 10);
			graphics.drawLine(x, y - 15, x, y);
			break;
		case 1:
			graphics.fill3DRect(x - 15, y - 10, 30, 5, false);
			graphics.fill3DRect(x - 15, y + 5, 30, 5, false);
			graphics.fill3DRect(x - 10, y - 5, 20, 10, false);
			graphics.fillOval(x - 5, y - 5, 10, 10);
			graphics.drawLine(x, y, x + 15, y);
			break;
		case 2:
			graphics.fill3DRect(x - 10, y - 15, 5, 30, false);
			graphics.fill3DRect(x + 5, y - 15, 5, 30, false);
			graphics.fill3DRect(x - 5, y - 10, 10, 20, false);
			graphics.fillOval(x - 5, y - 5, 10, 10);
			graphics.drawLine(x, y, x, y + 15);
			break;
		case 3:
			graphics.fill3DRect(x - 15, y - 10, 30, 5, false);
			graphics.fill3DRect(x - 15, y + 5, 30, 5, false);
			graphics.fill3DRect(x - 10, y - 5, 20, 10, false);
			graphics.fillOval(x - 5, y - 5, 10, 10);
			graphics.drawLine(x - 15, y, x, y);
			break;
		}
	}

	// 重写监听事件
	@Override
	public void keyTyped(KeyEvent e) {
		// TODO Auto-generated method stub

	}

	@Override
	public void keyPressed(KeyEvent e) {
		// TODO Auto-generated method stub
		if (e.getKeyCode() == KeyEvent.VK_W) {
			// 向上
			// 设置我的坦克的方向
			this.myTank.setDirect(0);
			this.myTank.moveUp();
		} else if (e.getKeyCode() == KeyEvent.VK_D) {
			// 向右
			this.myTank.setDirect(1);
			this.myTank.moveRight();
		} else if (e.getKeyCode() == KeyEvent.VK_S) {
			// 向下
			this.myTank.setDirect(2);
			this.myTank.moveDown();
		} else if (e.getKeyCode() == KeyEvent.VK_A) {
			// 向左
			this.myTank.setDirect(3);
			this.myTank.moveLeft();
		}
		if (e.getKeyCode() == KeyEvent.VK_J) {
			// 判断玩家按下了发射键
			if (myTank.bullets.size() < 5) {
				this.myTank.Shot();
			}
		}
		// 暂停游戏
//		boolean isPaused = false;
//		if(e.getKeyCode() == KeyEvent.VK_P) {
//			if(isPaused == true) {
//				System.out.println("继续");
//				myTank.speed=2;
//				for(int i=0;i<enemyTanks.size();i++) {
//					enemyTanks.get(i).speed=2;
//					for(int j=0;j<enemyTanks.get(i).bullets.size();j++) {
//						enemyTanks.get(i).bullets.get(j).speed=10;
//					}
//				}
//				isPaused = false;
//			}else if(isPaused==false) {
//				System.out.println("暂停");
//				myTank.speed=0;
//				for(int i=0;i<enemyTanks.size();i++) {
//					enemyTanks.get(i).speed=0;
//					for(int j=0;j<enemyTanks.get(i).bullets.size();j++) {
//						enemyTanks.get(i).bullets.get(j).speed=0;
//					}
//				}
//				isPaused=true;
//			}
//		
//		}

	}

	@Override
	public void keyReleased(KeyEvent e) {
		// TODO Auto-generated method stub
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		while (true) {
			try {
				Thread.sleep(50);
			} catch (Exception e) {
				// TODO: handle exception
			}

			// 判断子弹是否击中,击中的时候,敌人的坦克就消失
			for (int i = 0; i < myTank.bullets.size(); i++) {
				Bullet curentBullet = myTank.bullets.get(i);
				if (curentBullet.isAlive) {
					for (int j = 0; j < enemyTanks.size(); j++) {
						EnemyTank curEnemyTank = enemyTanks.get(j);
						if (curEnemyTank.isAlive) {
							hited(curentBullet, curEnemyTank);
						}
					}

				}
			}
			// 判断是否是恢复游戏
			if(Recorder.isContinue()) {
				// 敌方坦克上场
				if (enemyTanks.size() < 3 && (Recorder.getEnemyTankTotal() - 2) > 0) {
					for(int i=0;i<Recorder.getEnemyTanks().size();i++) {
						EnemyTank addTank = Recorder.getEnemyTanks().get(i);
						Thread enemyThread = new Thread(addTank);
						enemyThread.start();
						enemyTanks.add(addTank);
						addTank.setEnemyTanks(enemyTanks);
						enemyTankbirth++;
						if (enemyTankbirth >= 3) {
							enemyTankbirth = 0;
						}
					}
					Recorder.setContinue(false);
					Recorder.setEnemyTanks(enemyTanks);
				}else if(Recorder.getEnemyTankTotal()==1) {
					EnemyTank addTank = Recorder.getEnemyTanks().get(0);
					Thread enemyThread = new Thread(addTank);
					enemyThread.start();
					enemyTanks.add(addTank);
					addTank.setEnemyTanks(enemyTanks);
					enemyTankbirth++;
					if (enemyTankbirth >= 3) {
						enemyTankbirth = 0;
					}
				}
				Recorder.setContinue(false);
				Recorder.setEnemyTanks(enemyTanks);
				
			}else {
				// 敌方坦克上场
				if (enemyTanks.size() < 3 && (Recorder.getEnemyTankTotal() - 2) > 0) {
					EnemyTank addTank = new EnemyTank(enemyTankbirth * 250 + 50, 20, 2);
					Thread enemyThread = new Thread(addTank);
					enemyThread.start();
					enemyTanks.add(addTank);
					addTank.setEnemyTanks(enemyTanks);
					enemyTankbirth++;
					if (enemyTankbirth >= 3) {
						enemyTankbirth = 0;
					}
					Recorder.setEnemyTanks(enemyTanks);
				}
			}
			

			// 判断敌人的坦克是否击中我的坦克
			if (myTank.isAlive) {
				beHited(myTank, enemyTanks);
			}

			// 复活
			if (Recorder.getMyLife() > 0) {
				if (myTank.isAlive == false) {
					myTank = new MyTank(260, 380, 0);
				}
			}
			this.repaint();
		}
	}
}

开始界面

package cn.wenxiao.release9;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;

import javax.swing.JPanel;

public class StartPanel extends JPanel implements Runnable{
	// 控制字体闪烁
	int times=0;
	// 在面板上显示关卡信息
	public void paint(Graphics graphics) {
		super.paint(graphics);
		graphics.fillRect(0, 0, 600, 400);
		graphics.setColor(Color.YELLOW);
		Font myFont = new Font("微软雅黑",Font.BOLD,50);
		graphics.setFont(myFont);
		if(times%2==0) {
			graphics.drawString("第一关", 230, 210);
		}
		
	}

	@Override
	public void run() {
		// TODO 线程,用于显示关卡数闪烁
		while(true) {
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			this.repaint();
			times++;
			if(times>10000) {
				times=0;
			}
		}
	}
}

坦克父类

package cn.wenxiao.release9;



public class Tanks {

	// 表示坦克的横坐标
	int x = 0;
	// 表示坦克的纵坐标
	int y = 0;
	// 坦克的方向
	// 0表示上 1表示右 2表示下 3表示左
	int direct = 0;
	// 坦克的颜色
	int color;
	public int getColor() {
		return color;
	}

	public void setColor(int color) {
		this.color = color;
	}

	public int getSpeed() {
		return speed;
	}

	public void setSpeed(int speed) {
		this.speed = speed;
	}

	// 坦克的速度
	int speed = 2;

	public Tanks(int x, int y, int direct) {
		this.x = x;
		this.y = y;
		this.direct = direct;
	}

	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;
	}
}

敌方坦克

package cn.wenxiao.release9;

import java.util.Vector;
/*
 * 敌人坦克对象
 */
public class EnemyTank extends Tanks implements Runnable {
	// 敌人坦克的生命状态
	boolean isAlive = true;
	// 敌人坦克的默认方向向下
	//int direct = (int) (Math.random() * 4);
	int direct = 2;
	// 定义敌人坦克的子弹
	Bullet bullet = null;
	// 定义敌人坦克的弹夹
	Vector<Bullet> bullets = new Vector<Bullet>();
	// 定义每个敌人坦克可以看到的友军坦克信息的集合
	Vector<EnemyTank> enemyTanks = new Vector<EnemyTank>();
	// 获取友军坦克信息的方法
	public Vector<EnemyTank> getEnemyTanks() {
		return enemyTanks;
	}
	// 从战场获取友军坦克信息的方法
	public void setEnemyTanks(Vector<EnemyTank> enemyTanks) {
		this.enemyTanks = enemyTanks;
	}
	// 构造函数
	public EnemyTank(int x, int y, int direct) {
		super(x, y, direct);
	}

	@Override
	public String toString() {
		return "EnemyTank [isAlive=" + isAlive + ", direct=" + direct + "]";
	}
	// 判断坦克是否重叠的方法
	public boolean isOverlapped() {
		// 默认不重叠
		boolean status = false;
		// 根据当前坦克的方向,判断与之相遇的坦克是否重叠
		switch(this.direct) {
		case 0:
			for(int i=0;i<enemyTanks.size();i++) {
				// 取出一个坦克做判断
				EnemyTank thEnemyTank = enemyTanks.get(i);
				if(thEnemyTank!=this) {
					if(thEnemyTank.direct==0 || thEnemyTank.direct==2) {
						if((this.x-10)>=(thEnemyTank.x-10) && (this.x-10)<=(thEnemyTank.x+10) && (this.y-15) >= (thEnemyTank.y-15) && (this.y-15)<=(thEnemyTank.y+15)) {
							return true;
						}
						if((this.x+10)>=(thEnemyTank.x-10) && (this.x+10)<=(thEnemyTank.x+10) && (this.y-15) >= (thEnemyTank.y-15) && (this.y-15)<=(thEnemyTank.y+15)) {
							return true;
						}
					}
					if(thEnemyTank.direct==1 || thEnemyTank.direct==3) {
						if((this.x-10)>=(thEnemyTank.x-15) && (this.x-10)<=(thEnemyTank.x+15) && (this.y-15) >= (thEnemyTank.y-15) && (this.y-15)<=(thEnemyTank.y+15)) {
							return true;
						}
						if((this.x+10)>=(thEnemyTank.x-15) && (this.x+10)<=(thEnemyTank.x+15) && (this.y-15) >= (thEnemyTank.y-10) && (this.y-15)<=(thEnemyTank.y+15)) {
							return true;
						}
					}
				}
			}
			break;
		case 1:
			for(int i=0;i<enemyTanks.size();i++) {
				// 取出一个坦克做判断
				EnemyTank thEnemyTank = enemyTanks.get(i);
				if(thEnemyTank!=this) {
					if(thEnemyTank.direct==0 || thEnemyTank.direct==2) {
						if((this.x+15)>=(thEnemyTank.x-10) && (this.x+15)<=(thEnemyTank.x-10) && (this.y-10) >= (thEnemyTank.y-15) && (this.y-10)<=(thEnemyTank.y+15)) {
							return true;
						}
						if((this.x+15)>=(thEnemyTank.x-10) && (this.x+15)<=(thEnemyTank.x+10) && (this.y-10) >= (thEnemyTank.y+15) && (this.y+10)<=(thEnemyTank.y+15)) {
							return true;
						}
					}
					if(thEnemyTank.direct==1 || thEnemyTank.direct==3) {
						if((this.x+15)>=(thEnemyTank.x-15) && (this.x+15)<=(thEnemyTank.x+15) && (this.y-10) >= (thEnemyTank.y-10) && (this.y-10)<=(thEnemyTank.y+10)) {
							return true;
						}
						if((this.x+15)>=(thEnemyTank.x-15) && (this.x+15)<=(thEnemyTank.x+15) && (this.y+10) >= (thEnemyTank.y-10) && (this.y+10)<=(thEnemyTank.y+10)) {
							return true;
						}
					}
				}
			}
			break;
		case 2:
			for(int i=0;i<enemyTanks.size();i++) {
				// 取出一个坦克做判断
				EnemyTank thEnemyTank = enemyTanks.get(i);
				if(thEnemyTank!=this) {
					if(thEnemyTank.direct==0 || thEnemyTank.direct==2) {
						if((this.x-10)>=(thEnemyTank.x-10) && (this.x-10)<=(thEnemyTank.x+10) && (this.y+15) >= (thEnemyTank.y-15) && (this.y+15)<=(thEnemyTank.y+15)) {
							return true;
						}
						if((this.x+10)>=(thEnemyTank.x-10) && (this.x+10)<=(thEnemyTank.x+10) && (this.y+15) >= (thEnemyTank.y-15) && (this.y+15)<=(thEnemyTank.y+15)) {
							return true;
						}
					}
					if(thEnemyTank.direct==1 || thEnemyTank.direct==3) {
						if((this.x-10)>=(thEnemyTank.x-15) && (this.x-10)<=(thEnemyTank.x+15) && (this.y+15) >= (thEnemyTank.y-10) && (this.y+15)<=(thEnemyTank.y+10)) {
							return true;
						}
						if((this.x+10)>=(thEnemyTank.x-10) && (this.x+10)<=(thEnemyTank.x+15) && (this.y+15) >= (thEnemyTank.y-10) && (this.y+15)<=(thEnemyTank.y+10)) {
							return true;
						}
					}
				}
			}
			break;
		case 3:
			for(int i=0;i<enemyTanks.size();i++) {
				// 取出一个坦克做判断
				EnemyTank thEnemyTank = enemyTanks.get(i);
				if(thEnemyTank!=this) {
					if(thEnemyTank.direct==0 || thEnemyTank.direct==2) {
						if((this.x-15)>=(thEnemyTank.x-10) && (this.x-15)<=(thEnemyTank.x+10) && (this.y-10) >= (thEnemyTank.y-15) && (this.y-10)<=(thEnemyTank.y+15)) {
							return true;
						}
						if((this.x-15)>=(thEnemyTank.x-10) && (this.x-15)<=(thEnemyTank.x+10) && (this.y+10) >= (thEnemyTank.y-15) && (this.y+10)<=(thEnemyTank.y+15)) {
							return true;
						}
					}
					if(thEnemyTank.direct==1 || thEnemyTank.direct==3) {
						if((this.x-15)>=(thEnemyTank.x-15) && (this.x-15)<=(thEnemyTank.x+15) && (this.y-10) >= (thEnemyTank.y-10) && (this.y-10)<=(thEnemyTank.y+10)) {
							return true;
						}
						if((this.x-15)>=(thEnemyTank.x-15) && (this.x-15)<=(thEnemyTank.x+15) && (this.y+10) >= (thEnemyTank.y-10) && (this.y+10)<=(thEnemyTank.y+10)) {
							return true;
						}
					}
				}
			}
			break;
		}
		

		return status;
	}

	// 设置一个速度
	// 坦克向上移动
	public void moveUp() {
		y -= speed;
	}

	// 坦克向右移动
	public void moveRight() {
		x += speed;
	}

	// 坦克向下移动
	public void moveDown() {
		y += speed;
	}

	// 坦克向左移动
	public void moveLeft() {
		x -= speed;
	}

	// 发射子弹的方法
	public void Shot() {

		switch (direct) {
		case 0:
			bullet = new Bullet(x - 1, y - 15, 0);
			bullets.add(bullet);
			break;
		case 1:
			bullet = new Bullet(x + 15, y, 1);
			bullets.add(bullet);
			break;
		case 2:
			bullet = new Bullet(x - 1, y + 15, 2);
			bullets.add(bullet);
			break;
		case 3:
			bullet = new Bullet(x - 15, y, 3);
			bullets.add(bullet);
			break;
		}
		Thread shoThread = new Thread(bullet);
		shoThread.start();
	}

	@Override
	public void run() {
		// TODO 每个敌人坦克都是一个独立的线程
		while (true) {
			// 通过随机数控制敌人坦克发射子弹
			if (x > 15 && x < 570 && y > 15 && y < 450 && !this.isOverlapped()) {
				// 控制敌人坦克随机发射子弹
				int RandomShot = (int) (Math.random() * 100);
				if (RandomShot < 50) {
					this.Shot();
				}
			}
			// 通过敌人坦克当前的方向控制坦克的运动
			switch (this.direct) {
			case 0:
				for (int i = 0; i < 30; i++) {
					if (y > 15 && !this.isOverlapped()) {
						y -= speed;
					}
					try {
						Thread.sleep(50);
					} catch (Exception e) {
						// TODO: handle exception
						e.printStackTrace();
					}
				}
				break;
			case 1:
				for (int i = 0; i < 30; i++) {
					if (x < 450 && !this.isOverlapped()) {
						x += speed;
					}
					try {
						Thread.sleep(50);
					} catch (Exception e) {
						// TODO: handle exception
						e.printStackTrace();
					}
				}
				break;
			case 2:
				for (int i = 0; i < 30; i++) {
					if (y < 380 && !this.isOverlapped()) {
						y += speed;
					}
					try {
						Thread.sleep(50);
					} catch (Exception e) {
						// TODO: handle exception
						e.printStackTrace();
					}
				}
				break;
			case 3:
				for (int i = 0; i < 30; i++) {
					if (x > 15 && !this.isOverlapped()) {
						x -= speed;
					}
					try {
						Thread.sleep(50);
					} catch (Exception e) {
						// TODO: handle exception
						e.printStackTrace();
					}
				}
				break;
			}
			// 随机控制方向
			this.direct = (int) (Math.random() * 4);
			// 判断坦克是否被打死,打死了则停止线程
			if (isAlive == false) {
				break;
			}

		}
	}
}

我方坦克

package cn.wenxiao.release9;

import java.util.Vector;

public class MyTank extends Tanks {
	// 定义子弹
	Bullet bullet = null;
	// 定义我的弹夹
	Vector<Bullet> bullets = new Vector<Bullet>();
	// 我方坦克的生命状态
	boolean isAlive = true;
	// 构造函数
	public MyTank(int x, int y, int direct) {
		super(x, y, direct);
	}

	// 发射子弹的方法
	public void Shot() {

		switch (direct) {
		case 0:
			bullet = new Bullet(x - 1, y - 15, 0);
			bullets.add(bullet);
			break;
		case 1:
			bullet = new Bullet(x + 15, y, 1);
			bullets.add(bullet);
			break;
		case 2:
			bullet = new Bullet(x - 1, y + 15, 2);
			bullets.add(bullet);
			break;
		case 3:
			bullet = new Bullet(x - 15, y, 3);
			bullets.add(bullet);
			break;
		}
		Thread shoThread = new Thread(bullet);
		shoThread.start();
	}

	// 坦克向上移动
	public void moveUp() {
		if (y > 15) {
			y -= speed;
		}
	}

	// 坦克向右移动
	public void moveRight() {
		if (x < 770) {
			x += speed;
		}
	}

	// 坦克向下移动
	public void moveDown() {
		if (y < 550) {
			y += speed;
		}
	}

	// 坦克向左移动
	public void moveLeft() {
		if (x > 15) {
			x -= speed;
		}
	}
}

子弹

package cn.wenxiao.release9;
/*
 * 子弹对象
 */
public class Bullet implements Runnable{
	// 坐标
	int x;
	int y;
	// 子弹的方向
	int directory;
	// 子弹运行的速度
	int speed = 10;
	// 子弹的生命状态
	Boolean isAlive = true;
	public Bullet(int x, int y, int directory) {
		this.x = x;
		this.y = y;
		this.directory = directory;
	}
	
	@Override
	public void run() {
		// TODO 每一颗子弹都是一个独立的线程
		while(true) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			// 判断子弹的方向,每100毫秒运动一次
			switch(directory) {
			case 0:
				y -= speed;
				break;
			case 1:
				x += speed;
				break;
			case 2:
				y += speed;
				break;
			case 3:
				x -= speed;
				break;
			}
			// 如果子弹触碰到了战场面板的边缘,则生命周期结束
			if(x<0 || x >600 || y < 0 || y>400) {
				this.isAlive = false;
				break;
			}
		}
	}
}

爆炸效果

package cn.wenxiao.release9;
/*
 * 爆炸效果对象
 */
public class Bomb {
	// 坐标
	int x;
	int y;
	// 生命周期
	int life=8;
	// 状态
	boolean isAlive=true;

	public Bomb(int x, int y) {
		this.x = x;
		this.y = y;
	}
	// 爆炸显示过程控制
	public void lifeDown() {
		if(life>=0) {
			life--;
		}else {
			isAlive=false;
		}
	}
}

数据存盘及恢复

package cn.wenxiao.release9;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Vector;

public class Recorder {
	// 敌人坦克总数
	private static int enemyTankTotal = 20;
	// 我方坦克总数
	private static int myLife = 3;
	// 歼灭敌方坦克数
	private static int killedNum = 0;
	// 文件输出流
	private static FileWriter fWriter = null;
	// Buffered输出流
	private static BufferedWriter bWriter = null;
	// 文件输入流
	private static FileReader fReader = null;
	// Buffered输入流
	private static BufferedReader bReader = null;
	// 得到敌机集合
	private static Vector<EnemyTank> enemyTanks = null;
	// 是否是恢复游戏
	private static boolean isContinue = false;

	public static Vector<EnemyTank> getEnemyTanks() {
		return enemyTanks;
	}

	public static void setEnemyTanks(Vector<EnemyTank> enemyTanks) {
		Recorder.enemyTanks = enemyTanks;
	}

	public static int getEnemyTankTotal() {
		return enemyTankTotal;
	}

	public static void setEnemyTankTotal(int enemyTankTotal) {
		Recorder.enemyTankTotal = enemyTankTotal;
	}

	public static int getMyLife() {
		return myLife;
	}

	public static void setMyLife(int myLife) {
		Recorder.myLife = myLife;
	}

	public static int getKilledNum() {
		return killedNum;
	}

	public static void setKilledNum(int killedNum) {
		Recorder.killedNum = killedNum;
	}

	public static boolean isContinue() {
		return isContinue;
	}

	public static void setContinue(boolean isContinue) {
		Recorder.isContinue = isContinue;
	}

	// 保存当前游戏数据
	public static void saveData() {
		try {
			fWriter = new FileWriter(".\\GameData.txt");
			bWriter = new BufferedWriter(fWriter);
			bWriter.write("当前总击杀:" + killedNum + "\r\n");
			bWriter.write("敌机剩余:" + enemyTankTotal + "\r\n");
			bWriter.write("我的生命剩余:" + myLife + "\r\n");
			// 遍历当前在场上的敌机,并将坐标存入文件
			for (int i = 0; i < enemyTanks.size(); i++) {
				EnemyTank currEnemyTank = enemyTanks.get(i);
				String positionData = "第" + (i + 1) + "辆敌机坐标:" + "X:" + currEnemyTank.x + ":Y:" + currEnemyTank.y
						+ ":Directory:" + currEnemyTank.direct + "\r\n";
				bWriter.write(positionData);
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} finally {
			try {
				bWriter.close();
				fWriter.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	// 读取数据
	public static void readData() {
		enemyTanks = new Vector<EnemyTank>();
		isContinue = true;
		try {
			fReader = new FileReader(".\\GameData.txt");
			bReader = new BufferedReader(fReader);
			int[] data = new int[3];
			int index = 0;
			String dataString = null;
			while ((dataString = bReader.readLine()) != null) {
				String[] string = dataString.split(":");
				// 前三个是游戏主要数据,通过数组取出
				if (index < 3) {
					data[index++] = Integer.parseInt(string[1]);
				// 后面的数据都是上一局游戏中敌机的坐标信息,单独处理
				} else if (index >= 3) {
					int x = Integer.parseInt(string[2]);
					int y = Integer.parseInt(string[4]);
					int direct = Integer.parseInt(string[6]);
					EnemyTank enemyTank = new EnemyTank(x, y, direct);
					enemyTanks.add(enemyTank);
				}
			}
			killedNum = data[0];
			enemyTankTotal = data[1];
			myLife = data[2];
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			try {
				bReader.close();
				fReader.close();
			} catch (IOException e) {
				e.printStackTrace();
			}

		}
	}

	// 敌人坦克减少
	public static void enemyTankTotalDown() {
		enemyTankTotal--;
	}

	// 我方坦克被击中,命数减少
	public static void myLifeDown() {
		myLife--;
	}

	// 歼灭敌方坦克数
	public static void killedNumUp() {
		killedNum++;
	}
}

图片

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/337430.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

套接字通信(附带单线程TCP套接字通信代码)

套接字-Socket 1. 概念 1.1 局域网和广域网 局域网&#xff08;LAN&#xff09;和广域网&#xff08;WAN&#xff09;是两种不同范围的计算机网络&#xff0c;它们用于连接多台计算机以实现数据共享和通信。 局域网&#xff08;LAN&#xff09;&#xff1a; 定义&#xff1…

【JavaEE】文件操作与IO

作者主页&#xff1a;paper jie_博客 本文作者&#xff1a;大家好&#xff0c;我是paper jie&#xff0c;感谢你阅读本文&#xff0c;欢迎一建三连哦。 本文于《JavaEE》专栏&#xff0c;本专栏是针对于大学生&#xff0c;编程小白精心打造的。笔者用重金(时间和精力)打造&…

0121-1-计算机网络安全

计算机网络安全 1.Get 和 Post 的区别 结构&#xff1a;get 有请求体&#xff0c;post没有请求体 应用场景&#xff1a;get 用于获取数据&#xff0c;post用于提交数据&#xff1b; 缓存&#xff1a;get 的缓存保存在浏览器和web服务器日志中&#xff1b; 传输方式&#x…

typing python 类型标注学习笔记

在Python 3.5版本后引入的typing模块为Python的静态类型注解提供了支持。这个模块在增强代码可读性和维护性方面提供了帮助。 目录 简介为什么需要 Type hints typing常用类型typing初级语法typing基础语法默认参数及 Optional联合类型 (Union Type)类型别名 (Type Alias)子类型…

ESP32-HTTP_webServer库(Arduino)

ESP32-HTTP 介绍 ESP32是一款功能强大的微控制器&#xff0c;具有丰富的网络和通信功能。其中之一就是支持HTTP协议&#xff0c;这使得ESP32可以用于创建Web服务器。 HTTP是什么&#xff1f; HTTP&#xff08;Hyper Text Transfer Protocol&#xff09;&#xff0c;即超文本传…

[Error]连接iPhone调试时提示Failed to prepare the device for development.

环境&#xff1a; iPhone 7 Plus iOS 15.8 Xcode14.2 问题&#xff1a; 连接iPhone设备运行时&#xff0c;设备旁提示如下文案。 Failed to prepare the device for development. 这时强行点击运行按钮&#xff0c;会弹窗提示如下文案。 The run destination ZDMiPhone is n…

CTF show逆向5

1.查壳看看 没有壳&#xff0c;32位文件 同时注意到附件里的dll文件 2.放入IDA里看看 找到主函数 分别看看sub_4020B0 sub_4015BD 这两个函数 我发现一般看到MessageBoxA函数&#xff0c;都需要动态调试 动调看到 这里直接进行了返回,返回到了主函数 执行sub_4015BD函数 步…

力扣hot100 找到字符串中所有字母异位词 滑动窗口 双指针 一题双解

Problem: 438. 找到字符串中所有字母异位词 文章目录 思路滑动窗口 数组滑动窗口 双指针 思路 &#x1f469;‍&#x1f3eb; 参考题解 滑动窗口 数组 ⏰ 时间复杂度: O ( n ) O(n) O(n) &#x1f30e; 空间复杂度: O ( 1 ) O(1) O(1) class Solution { // 滑动窗口 …

【Gradle】Maven-Publishing

使用Java开发完成一个模块或者一个基础框架需要提供给团队项目使用&#xff0c;这个时候有两种方式可提供&#xff0c;一是提供源码&#xff0c;二是提供编译构建好的jar包供使用&#xff0c;这个时候需要讲构建好的包发布到公司的私服&#xff08;公司maven仓库&#xff09;&a…

分布式锁实现(mysql,以及redis)以及分布式的概念

道生一&#xff0c;一生二&#xff0c;二生三&#xff0c;三生万物 我旁边的一位老哥跟我说&#xff0c;你知道分布式是是用来干什么的嘛&#xff1f;一句话给我干懵了&#xff0c;我能隐含知道&#xff0c;大概是用来做分压处理的&#xff0c;并增加系统稳定性的。但是具体如…

C语言第四弹---printf和scanf详解

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 printf和scanf详解 1、printf和scanf详解介绍1.1 printf1.1.1 基本用法1.1.2 占位符1.1.3 占位符列举1.1.4 输出格式1.1.4.1 限定宽度1.1.4.2 总是显示正负号1.1…

第一篇【传奇开心果系列】WeUI开发原生微信小程序:汽车租赁小程序示例

传奇开心果博文系列目录 WeUI开发原生微信小程序示例系列博文目录博文目录一、项目目标二、编程思路三、初步实现汽车租赁微信小程序示例代码四、实现汽车租赁微信小程序的登录注册示例代码五、实现汽车租赁微信小程序的订单管理示例代码六、整合实现比较完整的汽车租赁微信小程…

css绘制下拉框头部三角(分实心/空心)

1:需求图: 手绘下拉框 带三角 2:网上查了一些例子,但都是实心的, 可参考,如图: (原链接: https://blog.csdn.net/qq_33463449/article/details/113375804) 3:简洁版的: a: 实心: <view class"angle"/>.angle{width:0;height:0;border-left: 10px solid t…

[晓理紫]每日论文分享(有中文摘要,源码或项目地址)--机器人相关、强化学习

专属领域论文订阅 VX 扫吗关注{晓理紫|小李子}&#xff0c;每日更新论文&#xff0c;如感兴趣&#xff0c;请转发给有需要的同学&#xff0c;谢谢支持 分类: 大语言模型LLM视觉模型VLM扩散模型视觉导航具身智能&#xff0c;机器人强化学习开放词汇&#xff0c;检测分割 [晓理紫…

K8s(七)四层代理Service

Service概述 Service在Kubernetes中提供了一种抽象的方式来公开应用程序的网络访问&#xff0c;并提供了负载均衡和服务发现等功能&#xff0c;使得应用程序在集群内外都能够可靠地进行访问。 每个Service都会自动关联一个对应的Endpoint。当创建一个Service时&#xff0c;Ku…

JS-日期对象

日期对象&#xff1a;用来表示时间的对象 作用&#xff1a;可以得到当前系统时间 实例化 在代码中发现了new关键字时&#xff0c;一般将这个操作称为实例化 创建一个时间对象并获取时间 1&#xff09;获得当前时间 const datenew Date() 2)获得指定时间 const datenew D…

Python项目——计算器(PySide6+Pyinstaller)

1、介绍 使用python编写一个计算器&#xff0c;可以实现基本的运算。【注】该项目最终还有一些细小的bug没有完善&#xff0c;例如符号可以一直输入。 2、实现 使用pyCharm创建一个新的项目。 2.1、设计UI 使用Qt designer设计一个UI界面&#xff0c;保存ui文件&#xff0…

基于docker,k8s 搭建服务(单体docker-compose编排)

1、 yum -y install gcc yum -y instacc gcc-c 2、安装yum 工具 yum install -y yum-utils device-mapper-persistent-data lvm2 --skip-broken 3、设置docker镜像仓库 阿里云 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.…

四种方法将 Docker Registry 迁移至 Harbor

Registry Docker Distribution Docker Distribution 是第一个是实现了打包、发布、存储和镜像分发的工具&#xff0c;起到 docker registry 的作用。&#xff08;目前 Distribution 已经捐赠给了 CNCF&#xff09;。其中 Docker Distribution 中的 spec 规范后来也就成为了 O…

Leetcode 2788. 按分隔符拆分字符串

我们可以先自己模拟一下分隔字符串的过程。如果只是简单的&#xff0c;遇到分隔符&#xff0c;将分隔符前后的子串加入结果的List&#xff0c;那么很显然并没有考虑到一个String中有多个字符串的情况。一种比较容易想到的方法是&#xff1a; 先对List中每个字符串遍历&#xf…