0基础学java-day20(坦克大战终极版)

2023-12-15 04:28

本文主要是介绍0基础学java-day20(坦克大战终极版),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、IO -应用到坦克大战

1.坦克大战 0.5

【重叠判断】【在敌人坦克类新增一个判断重叠的方法,并加入所有的坦克的数据,且在Mypanel传入数据给每个敌人坦克类】

 

 【一个加载音乐的API】

package com.hspedu.tankgame05;import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;/*** @author 林然* @version 1.0*/
public 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[512];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();}}
}

【播放音乐的一个类,我用于让他是一个线程,游戏的全程可播放音乐】

package com.hspedu.tankgame05;/*** @author 林然* @version 1.0*/
public class bofang implements Runnable{@Overridepublic void run() {while (true){new AePlayWave("src\\111.wav").start();try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

【子弹类】 

package com.hspedu.tankgame05;/*** @author 林然* @version 1.0* 炸弹*/
public class Bomb {int x,y;//炸弹坐标int life = 9;//炸弹的生命周期boolean isLife =true;//是否还存活public Bomb(int x, int y) {this.x = x;this.y = y;}//减少生命值public void lifeDown(){if(life>0){life--;}else{isLife=false;}}
}

【敌人坦克类】 

package com.hspedu.tankgame05;import java.util.Vector;/*** @author 韩顺平* @version 1.0* 敌人的坦克*/
public class EnemyTank extends Tank implements Runnable{Vector <Shot> shots=new Vector<>();//增加成员,EnemyTank可以得到敌人坦克的VectorVector<EnemyTank> enemyTanks =new Vector<>();//1.<Vector<EnemyTank>boolean isLive =true;public EnemyTank(int x, int y) {super(x, y);}//这里提供一个方法可以将MyPanel的成员添加到Vector<EnemyTank> enemyTanks =new Vector<>();//设置到EnemyTank的成员public void setEnemyTanks(Vector<EnemyTank> enemyTanks) {this.enemyTanks = enemyTanks;}//编写方法,判断当前的这个坦克是否和enemyTanks中的其他坦克发生的重叠或者碰撞public boolean isTouchEnemyTank(){//判断当前坦克的方向switch (getDirect()){//让当前敌人坦克和其他所有的敌人坦克比较,不和自己比较case 0://上for(int i=0;i<enemyTanks.size();i++){//从Vector取出一个敌人坦克EnemyTank enemyTank =enemyTanks.get(i);if(this!=enemyTank){//如果敌人坦克是上下/*如果敌人坦克是上下,其x和y的坐标范围1.如果敌人坦克时上下 x=[enemyTank.getX(),enemyTank.getX()+40]y=[enemyTank.getY(),enemyTank.getY()+60]*/if(enemyTank.getDirect()==0||enemyTank.getDirect()==2){//2.当前坦克左上角坐标【this.getX(),this.getY()】if(this.getX()>=enemyTank.getX()&&this.getX()<=enemyTank.getX()+40&&this.getY()>=enemyTank.getY()&&this.getY()<=enemyTank.getY()+60){return true;}//3.当前坦克左上角坐标【this.getX()+40,this.getY()】if(this.getX()+40>=enemyTank.getX()&&this.getX()+40<=enemyTank.getX()+40&&this.getY()>=enemyTank.getY()&&this.getY()<=enemyTank.getY()+60){return true;}}else{//如果敌人坦克是左右/*如果敌人坦克是左右,其x和y的坐标范围1.如果敌人坦克时上下 x=[enemyTank.getX(),enemyTank.getX()+60]y=[enemyTank.getY(),enemyTank.getY()+40]*///2.当前坦克左上角坐标【this.getX(),this.getY()】if(this.getX()>=enemyTank.getX()&&this.getX()<=enemyTank.getX()+60&&this.getY()>=enemyTank.getY()&&this.getY()<=enemyTank.getY()+40){return true;}//3.当前坦克左上角坐标【this.getX()+40,this.getY()】if(this.getX()+40>=enemyTank.getX()&&this.getX()+40<=enemyTank.getX()+60&&this.getY()>=enemyTank.getY()&&this.getY()<=enemyTank.getY()+40){return true;}}}}break;case 1://右for(int i=0;i<enemyTanks.size();i++){//从Vector取出一个敌人坦克EnemyTank enemyTank =enemyTanks.get(i);if(this!=enemyTank){//如果敌人坦克是上下/*如果敌人坦克是上下,其x和y的坐标范围1.如果敌人坦克时上下 x=[enemyTank.getX(),enemyTank.getX()+40]y=[enemyTank.getY(),enemyTank.getY()+60]*/if(enemyTank.getDirect()==0||enemyTank.getDirect()==2){//2.当前坦克右上角坐标【this.getX()+60,this.getY()】if(this.getX() + 60>=enemyTank.getX()&&this.getX() + 60 <=enemyTank.getX()+40&&this.getY()>=enemyTank.getY()&&this.getY()<=enemyTank.getY()+60){return true;}//3.当前坦克右下角坐标【this.getX()+60,this.getY()+40】if(this.getX()+60>=enemyTank.getX()&&this.getX()+60<=enemyTank.getX()+40&&this.getY()+40>=enemyTank.getY()&&this.getY()+40<=enemyTank.getY()+60){return true;}}else{//如果敌人坦克是左右/*如果敌人坦克是左右,其x和y的坐标范围1.如果敌人坦克时上下 x=[enemyTank.getX(),enemyTank.getX()+60]y=[enemyTank.getY(),enemyTank.getY()+40]*///2.当前坦克右上角坐标【this.getX()+60,this.getY()】if(this.getX()+60>=enemyTank.getX()&&this.getX()+60<=enemyTank.getX()+60&&this.getY()>=enemyTank.getY()&&this.getY()<=enemyTank.getY()+40){return true;}//3.当前坦克右下角坐标【this.getX()+60,this.getY()+40】if(this.getX()+60>=enemyTank.getX()&&this.getX()+60<=enemyTank.getX()+60&&this.getY()+40>=enemyTank.getY()&&this.getY()+40<=enemyTank.getY()+40){return true;}}}}break;case 2://下for(int i=0;i<enemyTanks.size();i++){//从Vector取出一个敌人坦克EnemyTank enemyTank =enemyTanks.get(i);if(this!=enemyTank){//如果敌人坦克是上下/*如果敌人坦克是上下,其x和y的坐标范围1.如果敌人坦克时上下 x=[enemyTank.getX(),enemyTank.getX()+40]y=[enemyTank.getY(),enemyTank.getY()+60]*/if(enemyTank.getDirect()==0||enemyTank.getDirect()==2){//2.当前坦克左下角坐标【this.getX(),this.getY()+60】if(this.getX() >=enemyTank.getX()&&this.getX() <=enemyTank.getX()+40&&this.getY()+60>=enemyTank.getY()&&this.getY()+60<=enemyTank.getY()+60){return true;}//3.当前坦克右下角坐标【this.getX()+40,this.getY()+60】if(this.getX()+40>=enemyTank.getX()&&this.getX()+40<=enemyTank.getX()+40&&this.getY()+60>=enemyTank.getY()&&this.getY()+60<=enemyTank.getY()+60){return true;}}else{//如果敌人坦克是左右/*如果敌人坦克是左右,其x和y的坐标范围1.如果敌人坦克时上下 x=[enemyTank.getX(),enemyTank.getX()+60]y=[enemyTank.getY(),enemyTank.getY()+40]*///2.当前坦克左下角坐标【this.getX(),this.getY()+60】if(this.getX()>=enemyTank.getX()&&this.getX()<=enemyTank.getX()+60&&this.getY()+60>=enemyTank.getY()&&this.getY()+60<=enemyTank.getY()+40){return true;}//3.当前坦克右下角坐标【this.getX()+40,this.getY()+60】if(this.getX()+40>=enemyTank.getX()&&this.getX()+40<=enemyTank.getX()+60&&this.getY()+60>=enemyTank.getY()&&this.getY()+60<=enemyTank.getY()+40){return true;}}}}break;case 3://左for(int i=0;i<enemyTanks.size();i++){//从Vector取出一个敌人坦克EnemyTank enemyTank =enemyTanks.get(i);if(this!=enemyTank){//如果敌人坦克是上下/*如果敌人坦克是上下,其x和y的坐标范围1.如果敌人坦克时上下 x=[enemyTank.getX(),enemyTank.getX()+40]y=[enemyTank.getY(),enemyTank.getY()+60]*/if(enemyTank.getDirect()==0||enemyTank.getDirect()==2){//2.当前坦克左上角坐标【this.getX(),this.getY()】if(this.getX() >=enemyTank.getX()&&this.getX()  <=enemyTank.getX()+40&&this.getY()>=enemyTank.getY()&&this.getY()<=enemyTank.getY()+60){return true;}//3.当前坦克左下角坐标【this.getX(),this.getY()+40】if(this.getX()>=enemyTank.getX()&&this.getX()<=enemyTank.getX()+40&&this.getY()+40>=enemyTank.getY()&&this.getY()+40<=enemyTank.getY()+60){return true;}}else{//如果敌人坦克是左右/*如果敌人坦克是左右,其x和y的坐标范围1.如果敌人坦克时上下 x=[enemyTank.getX(),enemyTank.getX()+60]y=[enemyTank.getY(),enemyTank.getY()+40]*///2.当前坦克左上角坐标【this.getX(),this.getY()】if(this.getX()>=enemyTank.getX()&&this.getX()<=enemyTank.getX()+60&&this.getY()>=enemyTank.getY()&&this.getY()<=enemyTank.getY()+40){return true;}//3.当前坦克左下角坐标【this.getX(),this.getY()+40】if(this.getX()>=enemyTank.getX()&&this.getX()<=enemyTank.getX()+60&&this.getY()+40>=enemyTank.getY()&&this.getY()+40<=enemyTank.getY()+40){return true;}}}}break;}return false;}//射击public void shotHeroTank(){//创建 Shou 对象,根据当前EnemyTank对象的位置和方向来创建Shot shot =null;switch (getDirect()){//得到EnemyTank方向case 0://向上shot =new Shot(getX()+20,getY(),0);break;case 1://向右shot=new Shot(getX()+60,getY()+20,1);break;case 2://向下shot=new Shot(getX()+20,getY()+60,2);break;case 3://向左shot=new Shot(getX(),getY()+20,3);break;}//加入子弹集合shots.add(shot);//启动子弹线程new Thread(shot).start();}@Overridepublic void run() {int count=0;while (isLive){if(shots.size()<5){shotHeroTank();}count++;//根据坦克方向来继续移动[前提是没有重叠]switch (getDirect()){case 0://向上if(!isTouchEnemyTank()){moveUp();}break;case 1://向右if(!isTouchEnemyTank()){moveRight();}break;case 2://向下if(!isTouchEnemyTank()){moveDown();}break;case 3://向左if(!isTouchEnemyTank()){moveLeft();}break;}try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}//然后随机的改变坦克方向[0-4).连续走10步后换方向if(count%10==0){setDirect((int)(Math.random()*4));count=0;}//写并发程序一定要考虑线程什么时候结束}}
}

【我方坦克类】 

package com.hspedu.tankgame05;import java.util.Vector;/*** @author linran* @version 1.0* 自己的坦克*/
public class Hero extends Tank {//定义一个Shot对象Shot shot =null;boolean isLife =true;//可以发送多颗子弹Vector<Shot> shots =new Vector<>();public Hero(int x, int y) {super(x, y);}//射击public void shotEnemyTank(){//创建 Shou 对象,根据当前Hero对象的位置和方向来创建switch (getDirect()){//得到hero方向case 0://向上shot =new Shot(getX()+20,getY(),0);break;case 1://向右shot=new Shot(getX()+60,getY()+20,1);break;case 2://向下shot=new Shot(getX()+20,getY()+60,2);break;case 3://向左shot=new Shot(getX(),getY()+20,3);break;}//加入子弹集合shots.add(shot);//启动子弹线程new Thread(shot).start();}
}

【游戏入口】

package com.hspedu.tankgame05;import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.Scanner;/*** @author Linran* @version 1.0*/
public class HspTankGame05 extends JFrame {Scanner sc =new Scanner(System.in);//定义MyPanelMyPanel mp = null;public static void main(String[] args) {HspTankGame05 hspTankGame01 = new HspTankGame05();}public HspTankGame05() {System.out.println("请输入选择1:新游戏  2:继续上局");String key =sc.next();mp = new MyPanel(key);Thread thread =new Thread(mp);thread.start();this.add(mp);//把面板(就是游戏的绘图区域)this.setSize(1400, 750);this.addKeyListener(mp);//让JFrame 监听mp的键盘事件this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setVisible(true);//在JFrame中增加相应的关闭窗口的处理this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {Recoder.keepRecoder();System.out.println("监听到关闭窗口");System.exit(0);}});}
}

【面板类】

package com.hspedu.tankgame05;import javax.swing.*;
import java.awt.*;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.util.Vector;/*** @author linran* @version 1.0* 坦克大战的绘图区域*///为了监听 键盘事件, 实现KeyListener//为了让Panel 不停地重绘子弹,需要将MyPanelRunnable,当做一个线程使用
public class MyPanel extends JPanel implements KeyListener,Runnable {//定义我的坦克Hero hero = null;//定义敌人坦克,放入到VectorVector<EnemyTank> enemyTanks = new Vector<>();int enemyTankSize = 3;//定义一个Vector用于存放炸弹//当子弹击中坦克时,就加入Vector<Bomb> bombs =new Vector<>();//定义三张图片用于显示爆炸效果Image image1 = null;Image image2 =null;Image image3 =null;//定义一个存放Node的Vector用于恢复敌人坦克坐标和方向Vector<Node> nodes=null;public MyPanel(String key) {//判断记录的文件是否存在//如果存在,就正常执行,如果不存在,提示只能开新游戏,key=1File file =new File(Recoder.getRecoderFile());if(file.exists()){nodes=Recoder.getNodesAndEnemyTankRec();}else {key="1";System.out.println("无上局记录,只能开启新游戏");}hero = new Hero(500, 200);//初始化自己坦克//初始化敌人坦克switch (key){case "1":Recoder.setAllEnemyNum(0);Recoder.setHero_life(3);for (int i = 0; i < enemyTankSize; i++) {//创建一个敌人的坦克EnemyTank enemyTank = new EnemyTank((100 * (i + 1)), 0);enemyTank.setEnemyTanks(enemyTanks);//设置方向enemyTank.setDirect(2);//启动坦克线程,让他动起来new Thread(enemyTank).start();//加入一颗子弹Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirect());//加入enemyTank的Vector成员进行管理enemyTank.shots.add(shot);//启动shot对象new Thread(shot).start();//加入enemyTanks.add(enemyTank);Recoder.setEnemyTanks(enemyTanks);}break;case "2":for (int i = 0; i < nodes.size(); i++) {Node node =nodes.get(i);//创建一个敌人的坦克EnemyTank enemyTank = new EnemyTank(node.getX(), node.getY());enemyTank.setEnemyTanks(enemyTanks);//设置方向enemyTank.setDirect(node.getDirect());//启动坦克线程,让他动起来new Thread(enemyTank).start();//加入一颗子弹Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirect());//加入enemyTank的Vector成员进行管理enemyTank.shots.add(shot);//启动shot对象new Thread(shot).start();//加入enemyTanks.add(enemyTank);Recoder.setEnemyTanks(enemyTanks);}break;default:System.out.println("你的输入有误");}//初始化炸弹图片image1=Toolkit.getDefaultToolkit().getImage(MyPanel.class.getResource("/bomb_1.gif"));image2=Toolkit.getDefaultToolkit().getImage(MyPanel.class.getResource("/bomb_2.gif"));image3=Toolkit.getDefaultToolkit().getImage(MyPanel.class.getResource("/bomb_3.gif"));bofang bofang = new bofang();new Thread(bofang).start();}//编写方法,显示我方击毁敌方坦克数量public void showInfo(Graphics g){//画出玩家总成绩g.setColor(Color.BLACK);Font font = new Font("宋体", Font.BOLD, 25);g.setFont(font);g.drawString("您累积击毁敌方坦克",1020,30);drawTank(1020,60,g,0,0);//画出敌方坦克//这里需要重新设置成黑色,因为在画坦克时,被设置了g.setColor(Color.BLACK);g.drawString(Recoder.getAllEnemyNum()+"",1080,100);g.drawString("您的剩余游戏次数",1020,160);drawTank(1020,200,g,0,1);//画出敌方坦克g.setColor(Color.BLACK);g.drawString(Recoder.getHero_life()+"",1080,240);}@Overridepublic void paint(Graphics g) {super.paint(g);g.fillRect(0, 0, 1000, 750);//填充矩形,默认黑色showInfo(g);//画出自己坦克-封装方法if(hero.isLife){drawTank(hero.getX(), hero.getY(), g, hero.getDirect(), 1);}//画出hero射击的子弹for (int i=0;i<hero.shots.size();i++){Shot shot = hero.shots.get(i);if(shot!=null&&shot.isLive!=false){g.draw3DRect(shot.x,shot.y,5,5,false);}else {//从vector移除hero.shots.remove(shot);}}for(int i=0;i<bombs.size();i++){Bomb bomb = bombs.get(i);//根据当前对象的life值去画图片if(bomb.life>6){g.drawImage(image1,bomb.x,bomb.y,60,60,this);}else if(bomb.life>3){g.drawImage(image2,bomb.x,bomb.y,60,60,this);}else {g.drawImage(image3,bomb.x,bomb.y,60,60,this);}//让炸弹生命值减少bomb.lifeDown();if(bomb.life==0){bombs.remove(i);//如果生命为0就删除}}//画出敌人的坦克, 遍历Vectorfor (int i = 0; i < enemyTanks.size(); i++) {//取出坦克EnemyTank enemyTank = enemyTanks.get(i);if(enemyTank.isLive){//当子弹存活才画出坦克drawTank(enemyTank.getX(), enemyTank.getY(), g, enemyTank.getDirect(), 0);//画出enemyTank的所有子弹for (int j=0;j<enemyTank.shots.size();j++){//取出子弹Shot shot = enemyTank.shots.get(j);if(shot.isLive!=false){g.draw3DRect(shot.x,shot.y,5,5,false);}else {enemyTank.shots.remove(shot);}}}}}//编写方法,画出坦克/*** @param x      坦克的左上角x坐标* @param y      坦克的左上角y坐标* @param g      画笔* @param direct 坦克方向(上下左右)* @param type   坦克类型*/public void drawTank(int x, int y, Graphics g, int direct, int type) {//根据不同类型坦克,设置不同颜色switch (type) {case 0: //敌人的坦克g.setColor(Color.cyan);break;case 1: //我的坦克g.setColor(Color.yellow);break;}//根据坦克方向,来绘制对应形状坦克//direct 表示方向(0: 向上 1 向右 2 向下 3 向左 )//switch (direct) {case 0: //表示向上g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克盖子g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子g.drawLine(x + 20, y + 30, x + 20, y);//画出炮筒break;case 1: //表示向右g.fill3DRect(x, y, 60, 10, false);//画出坦克上边轮子g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克下边轮子g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克盖子g.fillOval(x + 20, y + 10, 20, 20);//画出圆形盖子g.drawLine(x + 30, y + 20, x + 60, y + 20);//画出炮筒break;case 2: //表示向下g.fill3DRect(x, y, 10, 60, false);//画出坦克左边轮子g.fill3DRect(x + 30, y, 10, 60, false);//画出坦克右边轮子g.fill3DRect(x + 10, y + 10, 20, 40, false);//画出坦克盖子g.fillOval(x + 10, y + 20, 20, 20);//画出圆形盖子g.drawLine(x + 20, y + 30, x + 20, y + 60);//画出炮筒break;case 3: //表示向左g.fill3DRect(x, y, 60, 10, false);//画出坦克上边轮子g.fill3DRect(x, y + 30, 60, 10, false);//画出坦克下边轮子g.fill3DRect(x + 10, y + 10, 40, 20, false);//画出坦克盖子g.fillOval(x + 20, y + 10, 20, 20);//画出圆形盖子g.drawLine(x + 30, y + 20, x, y + 20);//画出炮筒break;default:System.out.println("暂时没有处理");}}//判断我方子弹是否击中敌人坦克public  void hittank(Vector<Shot> shots,EnemyTank enemyTank){//判断s击中坦克for (int i=0;i<shots.size();i++){Shot s = shots.get(i);switch (enemyTank.getDirect()){case 0://上case 2://下if(s.x>enemyTank.getX()&&s.x<enemyTank.getX()+40&&s.y>enemyTank.getY()&&s.y<enemyTank.getY()+60){   s.isLive=false;enemyTank.isLive=false;//创建Bomb对象加入集合中Bomb bomb =new Bomb(enemyTank.getX(),enemyTank.getY());bombs.add(bomb);enemyTanks.remove(enemyTank);Recoder.addAllEnemyNum();}break;case 1: //左右case 3:if(s.x>enemyTank.getX()&&s.x<enemyTank.getX()+60&&s.y>enemyTank.getY()&&s.y<enemyTank.getY()+40){   s.isLive=false;enemyTank.isLive=false;//创建Bomb对象加入集合中Bomb bomb =new Bomb(enemyTank.getX(),enemyTank.getY());bombs.add(bomb);enemyTanks.remove(enemyTank);Recoder.addAllEnemyNum();}break;}}}//判断我方子弹是否击中敌人坦克public  void hitHero(Vector<Shot> shots,Hero hero){//判断s击中坦克for (int i=0;i<shots.size();i++){Shot s = shots.get(i);if(s.isLive&&hero.isLife){switch (hero.getDirect()){case 0://上case 2://下if(s.x>hero.getX()&&s.x<hero.getX()+40&&s.y>hero.getY()&&s.y<hero.getY()+60){   s.isLive=false;//创建Bomb对象加入集合中Bomb bomb =new Bomb(hero.getX(),hero.getY());bombs.add(bomb);hero.isLife=false;Recoder.Minus_Hero_life();}break;case 1: //左右case 3:if(s.x>hero.getX()&&s.x<hero.getX()+60&&s.y>hero.getY()&&s.y<hero.getY()+40){   s.isLive=false;hero.isLife=false;//创建Bomb对象加入集合中Bomb bomb =new Bomb(hero.getX(),hero.getY());bombs.add(bomb);Recoder.Minus_Hero_life();}break;}}}}@Overridepublic void keyTyped(KeyEvent e) {}//处理wdsa 键按下的情况@Overridepublic void keyPressed(KeyEvent e) {System.out.println(e.getKeyCode());if (e.getKeyCode() == KeyEvent.VK_W) {//按下W键//改变坦克的方向hero.setDirect(0);////修改坦克的坐标 y -= 1hero.moveUp();} else if (e.getKeyCode() == KeyEvent.VK_D) {//D键, 向右hero.setDirect(1);hero.moveRight();} else if (e.getKeyCode() == KeyEvent.VK_S) {//S键hero.setDirect(2);hero.moveDown();} else if (e.getKeyCode() == KeyEvent.VK_A) {//A键hero.setDirect(3);hero.moveLeft();}if(e.getKeyCode()==KeyEvent.VK_J){//if(!(hero.shot!=null&&hero.shot.isLive)) {发射一颗子弹if(hero.shots.size()<5)hero.shotEnemyTank();//发射多颗子弹,在面板最多有5g颗子弹//}}//让面板重绘this.repaint();}@Overridepublic void keyReleased(KeyEvent e) {}@Overridepublic void run() {while (true){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}//判断是否击中坦克if(hero.shots.size()>0){//当前我的子弹存活//遍历敌人所有坦克for (int i = 0; i < enemyTanks.size(); i++) {EnemyTank enemyTank =enemyTanks.get(i);hittank(hero.shots,enemyTank);}}//判断是否击中我方坦克for (int i=0;i<enemyTanks.size();i++){hitHero(enemyTanks.get(i).shots,hero);}if(enemyTanks.size()<3){//创建一个敌人的坦克int i= (int) (Math.random()*10);EnemyTank enemyTank = new EnemyTank((100 * (i )), 0);enemyTank.setEnemyTanks(enemyTanks);//设置方向enemyTank.setDirect(2);//启动坦克线程,让他动起来new Thread(enemyTank).start();//加入一颗子弹Shot shot = new Shot(enemyTank.getX() + 20, enemyTank.getY() + 60, enemyTank.getDirect());//加入enemyTank的Vector成员进行管理enemyTank.shots.add(shot);//启动shot对象new Thread(shot).start();//加入enemyTanks.add(enemyTank);Recoder.setEnemyTanks(enemyTanks);}if(hero.isLife==false&&Recoder.getHero_life()>0){hero.isLife=true;}if(Recoder.getHero_life()<=0){System.exit(0);}this.repaint();}}
}

【从文件中读取存储坦克的信息】 

package com.hspedu.tankgame05;/*** @author 林然* @version 1.0* 一个Node对象,就表示一个敌人坦克信息*/
public class Node {private int x;private int y;private int direct;public Node(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 com.hspedu.tankgame05;import java.io.*;
import java.util.Vector;/*** @author 林然* @version 1.0* 用于记录相关的信息,和文件交互*/
public class Recoder {//定义变量,我方击毁敌人坦克数量private static int allEnemyNum =0;private static int hero_life =3;public static int getHero_life() {return hero_life;}public static void setHero_life(int hero_life) {Recoder.hero_life = hero_life;}public static void Minus_Hero_life() {hero_life--;}//定义IO对象private static Vector<EnemyTank> enemyTanks =null;private static BufferedWriter bw =null;private static BufferedReader br =null;private static String recoderFile ="src\\myrecode.txt";//定义一个Node的集合,用于存储信息public static Vector<Node> nodes =new Vector<>();//增加一个方法,用于读取文件,用于恢复信息public static String getRecoderFile() {return recoderFile;}public static void setEnemyTanks(Vector<EnemyTank> enemyTanks) {Recoder.enemyTanks = enemyTanks;}//增加一个方法,当游戏退出时,保存到文件中public static Vector<Node> getNodesAndEnemyTankRec()//该方法在启动位置进行{try {br=new BufferedReader(new FileReader(recoderFile));allEnemyNum=Integer.parseInt(br.readLine());hero_life=Integer.parseInt(br.readLine());//循环读取String line ="";while((line=br.readLine())!=null){String [] s= line.split(" ");Node node = new Node(Integer.parseInt(s[0]), Integer.parseInt(s[1]), Integer.parseInt(s[2]));nodes.add(node);}} catch (IOException e) {e.printStackTrace();} finally {try {if(br!=null){br.close();}} catch (IOException e) {}}return nodes;}public static void keepRecoder(){try {bw=new BufferedWriter(new FileWriter(recoderFile));bw.write(allEnemyNum+"");bw.newLine();bw.write(hero_life+"");bw.newLine();//遍历敌人坦克Vector,然后根据情况保存即可//OOP,定义一个属性获取敌人坦克for (int i = 0; i < enemyTanks.size(); i++) {EnemyTank enemyTank =enemyTanks.get(i);if(enemyTank.isLive){//建议判断下//保存信息String record =enemyTank.getX()+" "+enemyTank.getY()+" "+enemyTank.getDirect();//写入文件bw.write(record);bw.newLine();}}} catch (IOException e) {e.printStackTrace();} finally {if(bw!=null){try {bw.close();} catch (IOException e) {e.printStackTrace();}}}}public static int getAllEnemyNum() {return allEnemyNum;}public static void setAllEnemyNum(int allEnemyNum) {Recoder.allEnemyNum = allEnemyNum;}public static void addAllEnemyNum(){allEnemyNum++;}
}

【射击类】

package com.hspedu.tankgame05;/*** @author 林然* @version 1.0*/
public class Shot implements Runnable{//设计子弹int x;//子弹x坐标int y;//子弹y坐标int direction =0;//子弹方向int speed = 2;//子弹宿舍boolean isLive = true;//是否存活//构造器public Shot(int x, int y, int direction) {this.x = x;this.y = y;this.direction = direction;}@Overridepublic void run() {while (true){try {Thread.sleep(50);} catch (InterruptedException e) {e.printStackTrace();}//根据方向来改变switch (direction){case 0:y-=speed;break;//上case 1:x+=speed;break;//右case 2:y+=speed;break;//下case 3:x-=speed;break;//左}System.out.println("子弹x="+x+"子弹y="+y);//当子弹碰到面板边界时应该被销毁//当子弹碰到敌人坦克时,也应该结束进程if(!(x>=0&&x<=1000&&y>=0&&y<=750&&isLive)){isLive=false;break;}}}
}

【坦克类】

package com.hspedu.tankgame05;/*** @author 韩顺平* @version 1.0*/
public class Tank {private int x;//坦克的横坐标private int y;//坦克的纵坐标private int direct = 0;//坦克方向 0 上1 右 2下 3左private int speed = 5;public int getSpeed() {return speed;}public void setSpeed(int speed) {this.speed = speed;}//上右下左移动方法public void moveUp() {if(y>0)//判断边界条件,个人感觉在这里设置的话我方和敌人坦克都可以直接控制{y -= speed;}}public void moveRight() {if(x<1000&&(x+80)<1000){x += speed;}}public void moveDown() {if(y<750&&(y+100)<750){y += speed;}}public void moveLeft() {if(x>0){x -= speed;}}public int getDirect() {return direct;}public void setDirect(int direct) {this.direct = direct;}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;}
}

2.文件结构图

记得把相关图片和音频等文件放入对应的文件夹 

3.课件资源

链接:https://pan.baidu.com/s/1anOddH3cE47HuAUHyAGiVg?pwd=msmz 
提取码:msmz 

4.展示视频

坦克大战

这篇关于0基础学java-day20(坦克大战终极版)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/495117

相关文章

JVM 的类初始化机制

前言 当你在 Java 程序中new对象时,有没有考虑过 JVM 是如何把静态的字节码(byte code)转化为运行时对象的呢,这个问题看似简单,但清楚的同学相信也不会太多,这篇文章首先介绍 JVM 类初始化的机制,然后给出几个易出错的实例来分析,帮助大家更好理解这个知识点。 JVM 将字节码转化为运行时对象分为三个阶段,分别是:loading 、Linking、initialization

Spring Security 基于表达式的权限控制

前言 spring security 3.0已经可以使用spring el表达式来控制授权,允许在表达式中使用复杂的布尔逻辑来控制访问的权限。 常见的表达式 Spring Security可用表达式对象的基类是SecurityExpressionRoot。 表达式描述hasRole([role])用户拥有制定的角色时返回true (Spring security默认会带有ROLE_前缀),去

浅析Spring Security认证过程

类图 为了方便理解Spring Security认证流程,特意画了如下的类图,包含相关的核心认证类 概述 核心验证器 AuthenticationManager 该对象提供了认证方法的入口,接收一个Authentiaton对象作为参数; public interface AuthenticationManager {Authentication authenticate(Authenti

Spring Security--Architecture Overview

1 核心组件 这一节主要介绍一些在Spring Security中常见且核心的Java类,它们之间的依赖,构建起了整个框架。想要理解整个架构,最起码得对这些类眼熟。 1.1 SecurityContextHolder SecurityContextHolder用于存储安全上下文(security context)的信息。当前操作的用户是谁,该用户是否已经被认证,他拥有哪些角色权限…这些都被保

Spring Security基于数据库验证流程详解

Spring Security 校验流程图 相关解释说明(认真看哦) AbstractAuthenticationProcessingFilter 抽象类 /*** 调用 #requiresAuthentication(HttpServletRequest, HttpServletResponse) 决定是否需要进行验证操作。* 如果需要验证,则会调用 #attemptAuthentica

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式Factory工厂模式Singleton单例模式Delegate委派模式Strategy策略模式Prototype原型模式Template模板模式 Spring5 beans 接口实例化代理Bean操作 Context Ioc容器设计原理及高级特性Aop设计原理Factorybean与Beanfactory Transaction 声明式事物

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

JAVA智听未来一站式有声阅读平台听书系统小程序源码

智听未来,一站式有声阅读平台听书系统 🌟&nbsp;开篇:遇见未来,从“智听”开始 在这个快节奏的时代,你是否渴望在忙碌的间隙,找到一片属于自己的宁静角落?是否梦想着能随时随地,沉浸在知识的海洋,或是故事的奇幻世界里?今天,就让我带你一起探索“智听未来”——这一站式有声阅读平台听书系统,它正悄悄改变着我们的阅读方式,让未来触手可及! 📚&nbsp;第一站:海量资源,应有尽有 走进“智听

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]