坦克大战游戏代码

news2024/11/24 17:15:45

坦克大战游戏

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

主函数

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

图片

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

2024年【金属非金属矿山(地下矿山)安全管理人员】证考试及金属非金属矿山(地下矿山)安全管理人员模拟考试题库

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年【金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员】证考试及金属非金属矿山&#xff08;地下矿山&#xff09;安全管理人员模拟考试题库&#xff0c;包含金属非金属矿山&#xff08;地下矿山&…

RabbitMQ-消息延迟

一、死信交换机 1、描述 一个队列接收到的消息有过期时间&#xff0c;消息过期之后&#xff0c;如果配置有死信队列&#xff0c;消息就会进去死信队列。 2、图解 3、过程 当生产者将消息发送到exchange1&#xff0c;然后交换机将消息路由到队列queue1&#xff0c;但是队列que…

探索指针的奇妙世界,程序中的魔法箭头(上)

目录 一.指针是什么二.指针和指针类型1.指针加减整数2.指针的解引用 三.野指针1.野指针形成的原因&#xff08;1&#xff09;指针未初始化指针越界访问 2.如何规避野指针&#xff08;1&#xff09;指针初始化&#xff08;2&#xff09;小心指针越界&#xff08;3&#xff09;指…

SpringSecurity+JWT前后端分离架构登录认证

目录 1. 数据库设计 2. 代码设计 登录认证过滤器 认证成功处理器AuthenticationSuccessHandler 认证失败处理器AuthenticationFailureHandler AuthenticationEntryPoint配置 AccessDeniedHandler配置 UserDetailsService配置 Token校验过滤器 登录认证过滤器接口配置…

理解PCIE设备透传

PCIE设备透传解决的是使虚拟机直接访问PCIE设备的技术&#xff0c;通常情况下&#xff0c;为了使虚拟机能够访问Hypervisor上的资源&#xff0c;QEMU&#xff0c;KVMTOOL等虚拟机工具提供了"trap and emulate"&#xff0c; Virtio半虚拟化等机制实现。但是这些实现都…

用通俗易懂的方式讲解:使用 Langchain 和 Hugging Face ,轻松实现大模型 RAG 用法

检索增强生成&#xff08;RAG&#xff09;是一种与预训练的大型语言模型&#xff08;LLM&#xff09;和自己的数据一起工作的模式&#xff0c;用于生成响应。 现在我将向大家介绍在代码中实现 RAG 的过程。让我们开始使用 Langchain 和 Hugging Face 实现 RAG&#xff01; 文章…

matlab appdesigner系列-常用14-树(复选框)

之前系列常用9&#xff0c;为单个复选框。树&#xff0c;就是多个复选框形成的选项组 示例&#xff1a;列举湖北省的几个城市 湖北省 武汉 宜昌 襄阳 荆州 1&#xff09;将树&#xff08;复选框&#xff09;拖拽到画布上&#xff0c;方式1就是&#xff1a;文字可以在右侧…

【线上问题】CompletableFuture与线程池使用不当导致服务整个挂掉

Informal Essay By English It is always a pleasure to learn 背景 在某一个风和日丽的早上&#xff0c;小组同事说昨晚线上服务有20分钟左右的不可用&#xff0c;当时内心一紧&#xff0c;不会是我写的代码有bug导致的吧&#x1f440;&#xff0c;我正了正心态&#xff0c…

[小程序]样式与配置

一、外部样式导入 使用import加外部样式表的相对路径并以 ; 表示语句结束。 import "common.wxss"; 二、全局样式和局部样式 全局样式位于app.wxss中&#xff0c;会作用于整个项目中所有页面中。 局部样式位于对应的wxss文件中&#xff0c;仅作用于当前页面&#x…

WebDriverWait太强大

selenium webdriver及wait 1 implicitly包打天下2 Linkedin无法登录返回值很乱&#xff0c;怎么破&#xff1f; 1 implicitly包打天下 有了implicitly之后&#xff0c;基本上不再关注网速之类的影响。 self.driver.implicitly_wait(511)2 Linkedin无法登录返回值很乱&#xf…

Vulnhub-TECH_SUPP0RT: 1渗透

文章目录 一、前言1、靶机ip配置2、渗透目标3、渗透概括 开始实战一、信息获取二、使用smb服务获取信息三、密码破解四、获取webshell五、反弹shell六、web配置文件获取信息七、提权 一、前言 由于在做靶机的时候&#xff0c;涉及到的渗透思路是非常的广泛&#xff0c;所以在写…

ad18报错:clearance constraint

最常见的报错&#xff0c;直译过来的意思&#xff1a;间隙约束。也就是约束PCB中的电气间距&#xff0c;比如阻容各类元件的焊盘间距小于规则中的设定值&#xff0c;即报警。 Altium Designer 中的 Clearance Constraint 错误如何修改-CSDN博客 【Altium Designer21】DRC规则…

Vulnhub靶机:FunBox 2

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;FunBox 2&#xff08;10.0.2.27&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://download.vulnhub.com/funbo…

决策树的分类

概念 决策树是一种树形结构 树中每个内部节点表示一个特征上的判断&#xff0c;每个分支代表一个判断结果的输出&#xff0c;每个叶子节点代表一种分类结果 决策树的建立过程 1.特征选择&#xff1a;选取有较强分类能力的特征。 2.决策树生成&#xff1a;根据选择的特征生…

【代码随想录07】344.反转字符串 541. 反转字符串II 05.替换空格 151.翻转字符串里的单词 55. 右旋转字符串

目录 344. 反转字符串题目描述做题思路参考代码 541. 反转字符串 II题目描述参考代码 05. 替换数字题目描述参考代码 151. 反转字符串中的单词题目描述参考代码 55. 右旋转字符串题目描述参考代码 344. 反转字符串 题目描述 编写一个函数&#xff0c;其作用是将输入的字符串反…

HTML以及CSS相关知识总结(一)

近日就开始回顾html和css相关知识啦&#xff0c;并且会学习html5和css3的新知识&#xff0c;以下是我对记忆不太深刻的地方以及新知识点的总结&#xff1a; Web标准&#xff1a; 结构&#xff1a;用于对网页元素进行整理和分类&#xff0c;即HTML 表现&#xff1a;用于设置网页…

CentOS Linux操作系统源码安装最新Redis版本,使用JSON数据类型踩入新坑

最近有空查阅了redis官网&#xff0c;发现redis数据类型不止Strings、Lists、Sets、Hashes、Sorted sets&#xff0c;还多了几种&#xff0c;决定先试用下JSON数据类型 1、安装Redis软件 JSON数据类型&#xff0c;对Redis版本有要求&#xff0c;需要大于4.0版本。下图是华为云…

Transformer|1.4 CNN遇到的问题与窘境

文章目录 CNN遇到的问题与窘境transformer 的优势 CNN遇到的问题与窘境 判断一个人是否为美人&#xff0c;既要看她各个五官&#xff0c;也要看她各个五官占的比例和协调。 既要照顾好局部信息&#xff0c;也要照顾好全局信息。 局部信息用小的感受野进行感受&#xff0c;而全局…

【操作系统和计网从入门到深入】(六)进程间通信

前言 这个专栏其实是博主在复习操作系统和计算机网络时候的笔记&#xff0c;所以如果是博主比较熟悉的知识点&#xff0c;博主可能就直接跳过了&#xff0c;但是所有重要的知识点&#xff0c;在这个专栏里面都会提到&#xff01;而且我也一定会保证这个专栏知识点的完整性&…

python算法与数据结构---单调栈与实践

单调栈 单调栈是一个栈&#xff0c;里面的元素的大小按照它们所在栈的位置&#xff0c;满足一定的单调性&#xff1b; 性质&#xff1a; 单调递减栈能找到左边第一个比当前元素大的元素&#xff1b;单调递增栈能找到左边第一个比当前元素小的元素&#xff1b; 应用场景 一般用…