JAVA坦克大战游戏v3
JAVA坦克大战游戏v3
素材
bomb_3.gif
bomb_2.gif
bomb_1.gif
项目结构
游戏演示
MyTankGame3.java
/*** 功能:坦克游戏的5.0[]* 1.画出坦克.* 2.我的坦克可以上下左右移动* 3.可以发射子弹,子弹连发(最多5)* 4.当我的坦克击中敌人坦克时,敌人就消失(爆炸的效果)* 5.我被击中后,显示爆炸效果* 6.防止敌人坦克重叠运动(*)* 6.1决定把判断是否碰撞的函数写到EnemyTank类* 7.可以分关(*)* 7.1做一个开始的Panle,它是一个空的* 7.2闪烁效果* 8.可以在玩游戏的时候暂停和继续(*)* 8.1当用户点击暂停时,子弹的速度和坦克速度设为0,并让坦克的方向不要变化* 9.可以记录玩家的成绩(*)* 9.1用文件流.* 9.2单写一个记录类,完成对玩家记录* 9.3先完成保存共击毁了多少辆敌人坦克的功能.* 9.4存盘退出游戏,可以记录当时的敌人坦克坐标,并可以恢复* 10.java如何操作声音文件(*)* 10.1对声音文件的操作*/
package org.example;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import java.io.*;
public class MyTankGame3 extends JFrame implements ActionListener {MyPanel mp=null; //定义一个游戏面板MyStartPanel msp=null; //定义一个开始面板JMenuBar jmb=null; //菜单条JMenu jm1=null; //菜单JMenuItem jmil=null; //菜单选项1 开始新游戏JMenuItem jmi2=null; //菜单选项2 退出游戏JMenuItem jmi3=null; //菜单选项3 存盘退出游戏JMenuItem jmi4=null; //菜单选项4 继续上局游戏//主函数public static void main(String[] args) {// TODO Auto-generated method stub//定义一个MyTankGame3 的对象mtg并创建它MyTankGame3 mtg=new MyTankGame3();}//未完//构造函数public MyTankGame3(){//创建菜单及菜单选项jmb=new JMenuBar();jm1 =new JMenu("游戏(G)");//设置快捷方式jm1.setMnemonic('G');jmil =new JMenuItem("开始新游戏(N)");jmi2 =new JMenuItem("退出游戏(E)");jmi3 =new JMenuItem("存盘退出游戏(C)");jmi4 =new JMenuItem("继续上局游戏(S)");//注册监听jmi4.addActionListener(this);jmi4.setActionCommand("conGame");//注册监听jmi3.addActionListener(this);jmi3.setActionCommand("saveExit");jmi2.addActionListener(this);jmi2.setActionCommand("exit");jmi2.setMnemonic('E');//对jmil相应jmil.addActionListener(this);jmil.setActionCommand("newgame");jm1.add(jmil);jm1.add(jmi2);jm1.add(jmi3);jm1.add(jmi4);jmb.add(jm1);msp=new MyStartPanel();Thread t=new Thread(msp);t.start();this.setJMenuBar(jmb);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.add(msp);this.setSize(600, 500);this.setVisible(true);}//未完public void actionPerformed(ActionEvent arg0) {// TODO Auto-generated method stub//对用户不同的点击作出不同的处理if(arg0.getActionCommand().equals("newgame")){mp=new MyPanel("newGame");//创建战场面板Thread t=new Thread(mp);//启动mp线程t.start();this.remove(msp); //先删除旧的开始面板this.add(mp);this.addKeyListener(mp);//注册监听this.setVisible(true); //显示,刷新JFrame}else if(arg0.getActionCommand().equals("exit")){//用户点击了退出系统的菜单//保存击毁敌人数量.Recorder.keepRecording();System.exit(0);}//对存盘退出左处理else if(arg0.getActionCommand().equals("saveExit")){System.out.println("111");System.out.println("mp.ets.size="+mp.ets.size());//工作Recorder rd=new Recorder();rd.setEts(mp.ets);//保存击毁敌人的数量和敌人的坐标rd.keepRecAndEnemyTank();//退出System.exit(0);}else if(arg0.getActionCommand().equals("conGame")){//创建战场面板mp=new MyPanel("con");//启动mp线程Thread t=new Thread(mp);t.start();//先删除旧的开始面板this.remove(msp);this.add(mp);//注册监听this.addKeyListener(mp);//显示,刷新JFramethis.setVisible(true);}} //MyTankGame3()构造函数完
}//class MyTankGame3完
//class MyStartPanel 打开游戏的第一个画面,就是一个提示作用
class MyStartPanel extends JPanel implements Runnable
{int times=0; //设置时间public void paint(Graphics g){super.paint(g);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() {// TODO Auto-generated method stubwhile(true){//休眠try{Thread.sleep(100);} catch (Exception e) {e.printStackTrace();// TODO: handle exception}times++;this.repaint();//重画}}
}//class MyStartPanel完
//class MyPanel,我的面板,游戏就在这个面板上运行
class MyPanel extends JPanel implements KeyListener,Runnable {//定义一个我的坦克Hero hero=null;//定义敌人的坦克组Vector<EnemyTank> ets=new Vector<EnemyTank>();Vector<Node> nodes=new Vector<Node>();//定义炸弹集合Vector<Bomb> bombs=new Vector<Bomb>();int enSize=3;//定义三张图片,三张图片才能组成一颗炸弹Image image1=null;Image image2=null;Image image3=null;
//class MyPanel未完//MyPanel()构造函数public MyPanel(String flag){//恢复记录Recorder.getRecoring();hero=new Hero(100,100);if(flag.equals("newGame"))//如果玩家点击的是开始新游戏{//初始化敌人的坦克for(int i=0;i<enSize;i++){//创建一辆敌人的坦克对象EnemyTank et=new EnemyTank((i+1)*50,0);et.setColor(0);//颜色设置为黄色et.setDirect(2);//方向设置为朝上//将MyPanel的敌人坦克向量交给该敌人坦克et.setEts(ets);//启动敌人的坦克Thread t=new Thread(et);t.start();//给敌人坦克添加一颗子弹Shot s=new Shot(et.x+10,et.y+30,2);//加入给敌人坦克et.ss.add(s);Thread t2=new Thread(s);t2.start();//加入ets.add(et);}}//判断完毕,还有下一个判断//MyPanel()构造函数未完//玩游戏只有两种情况,要么新游戏,要么接着玩,保存和退出不在这个地方做判断else{System.out.println("接着玩");nodes=new Recorder().getNodesAndEnNums();//初始化敌人的坦克for(int i=0;i<nodes.size();i++){Node node=nodes.get(i);//创建一辆敌人的坦克对象EnemyTank et=new EnemyTank(node.x,node.y);et.setColor(0);et.setDirect(node.direct);//将MyPanel的敌人坦克向量交给该敌人坦克et.setEts(ets);//启动敌人的坦克Thread t=new Thread(et);t.start();//给敌人坦克添加一颗子弹Shot s=new Shot(et.x+10,et.y+30,2);//加入给敌人坦克et.ss.add(s);Thread t2=new Thread(s);t2.start();//加入ets.add(et);}}//判断完毕//创建图片try {image1=ImageIO.read(new File("images/O.png"));image2=ImageIO.read(new File("images/S.png"));image3=ImageIO.read(new File("images/T.png"));} catch (Exception e) {e.printStackTrace();// TODO: handle exception}//播放开战声音AePlayWave apw=new AePlayWave("out/ring05.wav");apw.start();}//MyPanel()构造函数完//showInfo(Graphics g)函数画出提示信息public void showInfo(Graphics g){//画出提示信息坦克(该坦克不参与战斗)this.drawTank(80,330, g, 0, 0);g.setColor(Color.black);g.drawString(Recorder.getEnNum()+"", 110, 350);this.drawTank(130, 330, g, 0, 1);g.setColor(Color.black);g.drawString(Recorder.getMyLife()+"", 165, 350);//画出玩家的总成绩g.setColor(Color.black);Font f=new Font("宋体",Font.BOLD,20);g.setFont(f);g.drawString("您的总成绩", 420, 30);this.drawTank(420, 60, g, 0, 0);g.setColor(Color.black);g.drawString(Recorder.getAllEnNum()+"", 460, 80);}//public paint(Graphics g)函数,整个游戏的前台public void paint(Graphics g){super.paint(g);g.fillRect(0, 0, 400, 300);//画出提示信息this.showInfo(g);//画出自己的坦克if(hero.isLive){this.drawTank(hero.getX(), hero.getY(), g, this.hero.direct, 1);}//从ss,中取出每颗子弹,并画出for(int i=0;i<hero.ss.size();i++){Shot myShot=hero.ss.get(i);//画出子弹,画出一颗子弹if(myShot!=null&&myShot.isLive==true){
// g.drawOval(myShot.x, myShot.y, 50, 50);g.draw3DRect(myShot.x, myShot.y, 1, 1,false);}if(myShot.isLive==false){//从ss中删除掉该子弹hero.ss.remove(myShot);}}//画出炸弹for(int i=0;i<bombs.size();i++){System.out.println("bombs.size()="+bombs.size());//取出炸弹Bomb b=bombs.get(i);if(b.life>6){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;i<ets.size();i++){EnemyTank et=ets.get(i);if(et.isLive){this.drawTank(et.getX(), et.getY(), g, et.getDirect(), 0);//再画出敌人的子弹//System.out.println("坦克子弹有:"+et.ss.size());for(int j=0;j<et.ss.size();j++){//取出子弹Shot enemyShot=et.ss.get(j);if(enemyShot.isLive){//System.out.println("第 "+i+"坦克的 "+j+"颗子弹x="+enemyShot.x);g.draw3DRect(enemyShot.x, enemyShot.y, 1, 1,false);}else{//如果敌人的坦克死亡就从Vector去掉et.ss.remove(enemyShot);}}}}}//paint(Graphics g)函数完
//class MyPanel未完//public void hitMe()函数敌人的坦克是否击中我public void hitMe(){//取出每一个敌人的坦克for(int i=0;i<this.ets.size();i++){//取出坦克EnemyTank et=ets.get(i);//取出每一颗子弹for(int j=0;j<et.ss.size();j++){//取出坦克的子弹Shot enemyShot=et.ss.get(j);if(hero.isLive){if(this.hitTank(enemyShot, hero)){}}}}}//判断我的子弹是否击中敌人的坦克public void hitEnemyTank(){//判断是否击中敌人的坦克for(int i=0;i<hero.ss.size();i++){//取出子弹Shot myShot=hero.ss.get(i);//判断子弹是否有效if(myShot.isLive){//取出每个坦克,与它判断for(int j=0;j<ets.size();j++){//取出坦克EnemyTank et=ets.get(j);if(et.isLive){if(this.hitTank(myShot, et)){//减少敌人数量Recorder.reduceEnNum();//增加我的记录Recorder.addEnNumRec();}}}}}}//写一个函数专门判断子弹是否击中敌人坦克public boolean hitTank(Shot s,Tank et){boolean b2=false;//判断该坦克的方向switch(et.direct){//如果敌人坦克的方向是上或者是下case 0:case 2:if(s.x>et.x&&s.x<et.x+20&&s.y>et.y&&s.y<et.y+30){//击中//子弹死亡s.isLive=false;//敌人坦克死亡et.isLive=false;b2=true;//创建一颗炸弹,放入VectorBomb b=new Bomb(et.x,et.y);//放入Vectorbombs.add(b);}break;case 1:case 3:if(s.x>et.x&&s.x<et.x+30&&s.y>et.y&&s.y<et.y+20){//击中//子弹死亡s.isLive=false;//敌人坦克死亡et.isLive=false;b2=true;//创建一颗炸弹,放入VectorBomb b=new Bomb(et.x,et.y);//放入Vectorbombs.add(b);}}return b2;}//画出坦克的函数(扩展)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;}//判断方向switch(direct){//向上case 0://画出我的坦克(到时再封装成一个函数)//1.画出左边的矩形g.fill3DRect(x, y, 5, 30,false);//2.画出右边矩形g.fill3DRect(x+15,y , 5, 30,false);//3.画出中间矩形g.fill3DRect(x+5,y+5 , 10, 20,false);//4.画出圆形g.fillOval(x+5, y+10, 10, 10);//5.画出线g.drawLine(x+10, y+15, x+10, y);break;case 1://炮筒向右//画出上面矩形g.fill3DRect(x, y, 30, 5,false);//画出下面的矩形g.fill3DRect(x, y+15, 30, 5, false);//画出中间的矩形g.fill3DRect(x+5, y+5, 20, 10, false);//画出圆形g.fillOval(x+10, y+5, 10, 10);//画出线g.drawLine(x+15, y+10, x+30, y+10);break;case 2://向下//画出我的坦克(到时再封装成一个函数)//1.画出左边的矩形g.fill3DRect(x, y, 5, 30,false);//2.画出右边矩形g.fill3DRect(x+15,y , 5, 30,false);//3.画出中间矩形g.fill3DRect(x+5,y+5 , 10, 20,false);//4.画出圆形g.fillOval(x+5, y+10, 10, 10);//5.画出线g.drawLine(x+10, y+15, x+10, y+30);break;case 3://向左//画出上面矩形g.fill3DRect(x, y, 30, 5,false);//画出下面的矩形g.fill3DRect(x, y+15, 30, 5, false);//画出中间的矩形g.fill3DRect(x+5, y+5, 20, 10, false);//画出圆形g.fillOval(x+10, y+5, 10, 10);//画出线g.drawLine(x+15, y+10, x, y+10);break;}}//键按下处理 a 表示向左 s 表示 下 w 表示向上 d表示右public void keyPressed(KeyEvent arg0) {// TODO Auto-generated method stubif(arg0.getKeyCode()==KeyEvent.VK_W){//设置我的坦克的方向this.hero.setDirect(0);this.hero.moveUp();}else if(arg0.getKeyCode()==KeyEvent.VK_D){//向右this.hero.setDirect(1);this.hero.moveRight();}else if(arg0.getKeyCode()==KeyEvent.VK_S){//向下this.hero.setDirect(2);this.hero.moveDown();}else if(arg0.getKeyCode()==KeyEvent.VK_A){//向左this.hero.setDirect(3);this.hero.moveLeft();}if(arg0.getKeyCode()==KeyEvent.VK_J){//判断玩家是否按下j//开火//System.out.println("this.hero.ss.size()="+this.hero.ss.size());if(this.hero.ss.size()<=4){this.hero.shotEnemy();}}//必须重新绘制Panelthis.repaint();}public void keyReleased(KeyEvent arg0) {// TODO Auto-generated method stub}public void keyTyped(KeyEvent arg0) {// TODO Auto-generated method stub}//class MyPanel的线程函数public void run() {// TODO Auto-generated method stub//每隔100毫秒去重绘while(true){try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();// TODO: handle exception}this.hitEnemyTank();//函数,判断敌人的子弹是否击中我this.hitMe();//重绘this.repaint();}}
}//class MyPanel完
Members.java
package org.example;import javax.sound.sampled.*;
import java.io.*;
import java.util.Vector;
public class Members{}//播放声音的类
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();}}
}//class AePlayWave extends Thread完
class Node{int x;int y;int 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;//从文件中恢复记录点static Vector<Node> nodes=new Vector<Node>();private static FileWriter fw=null;private static BufferedWriter bw=null;private static FileReader fr=null;private static BufferedReader br=null;private Vector<EnemyTank> ets=new Vector<EnemyTank>();//public Vector<Node> getNodesAndEnNums()函数public Vector<Node> getNodesAndEnNums(){try {fr=new FileReader("d:\\myRecording.txt");br=new BufferedReader(fr);String n="";//先读取第一行n=br.readLine();allEnNum=Integer.parseInt(n);while((n=br.readLine())!=null){String []xyz=n.split(" ");Node node=new Node(Integer.parseInt(xyz[0]),Integer.parseInt(xyz[1]),Integer.parseInt(xyz[2]));nodes.add(node);}} catch (Exception e) {e.printStackTrace();// TODO: handle exception}finally{try {//后打开则先关闭br.close();fr.close();} catch (Exception e) {e.printStackTrace();// TODO: handle exception}}return nodes;}//保存击毁敌人的数量和敌人坦克坐标,方向public void keepRecAndEnemyTank(){try {//创建fw=new FileWriter("d:\\myRecording.txt");bw=new BufferedWriter(fw);bw.write(allEnNum+"\r\n");System.out.println("size="+ets.size());//保存当前活的敌人坦克的坐标和方向for(int i=0;i<ets.size();i++){//取出第一个坦克EnemyTank et=ets.get(i);if(et.isLive){//活的就保存String recode=et.x+" "+et.y+" "+et.direct;//写入bw.write(recode+"\r\n");}}} catch (Exception e) {e.printStackTrace();// TODO: handle exception}finally{//关闭流try {//后开先关闭bw.close();fw.close();} catch (Exception e) {e.printStackTrace();// TODO: handle exception}}}//从文件中读取,记录public static void getRecoring(){try {fr=new FileReader("d:\\myRecording.txt");br=new BufferedReader(fr);String n=br.readLine();allEnNum=Integer.parseInt(n);} catch (Exception e) {e.printStackTrace();// TODO: handle exception}finally{try {//后打开则先关闭br.close();fr.close();} catch (Exception e) {e.printStackTrace();// TODO: handle exception}}}//把玩家击毁敌人坦克数量保存到文件中public static void keepRecording(){try {//创建fw=new FileWriter("d:\\myRecording.txt");bw=new BufferedWriter(fw);bw.write(allEnNum+"\r\n");} catch (Exception e) {e.printStackTrace();// TODO: handle exception}finally{//关闭流try {//后开先关闭bw.close();fw.close();} catch (Exception e) {e.printStackTrace();// TODO: handle exception}}}public static int getEnNum() {return enNum;}public static void setEnNum(int enNum) {Recorder.enNum = enNum;}public static int getMyLife() {return myLife;}public static void setMyLife(int myLife) {Recorder.myLife = myLife;}//减少敌人数public static void reduceEnNum(){enNum--;}//消灭敌人public static void addEnNumRec(){allEnNum++;}public static int getAllEnNum() {return allEnNum;}public static void setAllEnNum(int allEnNum) {Recorder.allEnNum = allEnNum;}public Vector<EnemyTank> getEts() {return ets;}public void setEts(Vector<EnemyTank> ets1) {this.ets = ets1;System.out.println("ok");}
}
//炸弹类
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;int y;int direct;int speed=1;//是否还活着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);} catch (Exception e) {// TODO: handle exception}switch(direct){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>400||y<0||y>300){this.isLive=false;break;}}}
}
//坦克类
class Tank {//表示坦克的横坐标int x=0;//坦克纵坐标int y=0;//坦克方向//0表示上 1表示 右 2表示下 3表示左int direct=0;int color;boolean isLive=true;//坦克的速度int speed=3;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 times=0;//定义一个向量,可以访问到MyPanel上所有敌人的坦克Vector<EnemyTank> ets=new Vector<EnemyTank>();//定义一个向量,可以存放敌人的子弹Vector<Shot> ss=new Vector<Shot>();//敌人添加子弹,应当在刚刚创建坦克和敌人的坦克子弹死亡后public EnemyTank(int x,int y){super(x,y);}//得到MyPanel的敌人坦克向量public void setEts(Vector<EnemyTank> vv){this.ets=vv;}//判断是否碰到了别的敌人坦克public boolean isTouchOtherEnemy(){boolean b=false;switch(this.direct){case 0://我的坦克向上//取出所有的敌人坦克for(int i=0;i<ets.size();i++){//取出第一个坦克EnemyTank et=ets.get(i);//如果不是自己if(et!=this){//如果敌人的方向是向下或者向上if(et.direct==0||et.direct==2){//左点if(this.x>=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==3||et.direct==1){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<ets.size();i++){//取出第一个坦克EnemyTank et=ets.get(i);//如果不是自己if(et!=this){//如果敌人的方向是向下或者向上if(et.direct==0||et.direct==2){//上点if(this.x+30>=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==3||et.direct==1){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;case 2://坦克向下//取出所有的敌人坦克for(int i=0;i<ets.size();i++){//取出第一个坦克EnemyTank et=ets.get(i);//如果不是自己if(et!=this){//如果敌人的方向是向下或者向上if(et.direct==0||et.direct==2){//我的左点if(this.x>=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==3||et.direct==1){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 3://向左//取出所有的敌人坦克for(int i=0;i<ets.size();i++){//取出第一个坦克EnemyTank et=ets.get(i);//如果不是自己if(et!=this){//如果敌人的方向是向下或者向上if(et.direct==0||et.direct==2){//我的上一点if(this.x>=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==3||et.direct==1){//上一点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;}return b;}public void run() {// TODO Auto-generated method stubwhile(true){switch(this.direct){case 0://说明坦克正在向上for(int i=0;i<30;i++){if(y>0&&!this.isTouchOtherEnemy()){y-=speed;}try {Thread.sleep(50);} catch (Exception e) {e.printStackTrace();// TODO: handle exception}}break;case 1://向右for(int i=0;i<30;i++){//保证坦克不出边界if(x<400&&!this.isTouchOtherEnemy()){x+=speed;}try {Thread.sleep(50);} catch (Exception e) {e.printStackTrace();// TODO: handle exception}}break;case 2://向下for(int i=0;i<30;i++){if(y<300&&!this.isTouchOtherEnemy()){y+=speed;}try {Thread.sleep(50);} catch (Exception e) {e.printStackTrace();// TODO: handle exception}}break;case 3://向左for(int i=0;i<30;i++){if(x>0&&!this.isTouchOtherEnemy()){x-=speed;}try {Thread.sleep(50);} catch (Exception e) {e.printStackTrace();// TODO: handle exception}}break;}this.times++;if(times%2==0){if(isLive){if(ss.size()<5){//System.out.println("et.ss.size()<5="+et.ss.size());Shot s=null;//没有子弹//添加switch(direct){case 0://创建一颗子弹s=new Shot(x+10,y,0);//把子弹加入向量ss.add(s);break;case 1:s=new Shot(x+30,y+10,1);ss.add(s);break;case 2:s=new Shot(x+10,y+30,2);ss.add(s);break;case 3:s=new Shot(x,y+10,3);ss.add(s);break;}//启动子弹Thread t=new Thread(s);t.start();}}}//让坦克随机产生一个新的方向this.direct=(int)(Math.random()*4);//判断敌人坦克是否死亡if(this.isLive==false){//让坦克死亡后,退出线程.break;}}}
}
//我的坦克
class Hero extends Tank {//子弹//Shot s=null;Vector<Shot> ss=new Vector<Shot>();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+30,y+10,1);ss.add(s);break;case 2:s=new Shot(x+10,y+30,2);ss.add(s);break;case 3:s=new Shot(x,y+10,3);ss.add(s);break;}//启动子弹线程Thread t=new Thread(s);t.start();}//坦克向上移动public void moveUp(){y-=speed;}//坦克向右移动public void moveRight(){x+=speed;}//坦克向下移动public void moveDown(){y+=speed;}//向左public void moveLeft(){x-=speed;}
}
相关文章:
JAVA坦克大战游戏v3
JAVA坦克大战游戏v3 素材 bomb_3.gif bomb_2.gif bomb_1.gif 项目结构 游戏演示 MyTankGame3.java /*** 功能:坦克游戏的5.0[]* 1.画出坦克.* 2.我的坦克可以上下左右移动* 3.可以发射子弹,子弹连发(最多5)* 4.当我的坦克击中敌人坦克时,敌人就消失(爆炸的效…...
使用acme,自动续签免费的SSL,无忧http升级https
使用acme自动续签免费的SSL 安装acme.sh颁发域名将证书安装到nginx下配置nginx的ssl自动续签 这里只进行最简单的操作 安装acme.sh 进入你的用户目录,如果你使用root登陆,那么你的用户目录就是 /root/ curl https://get.acme.sh | sh -s emailmyexam…...
Uniapp笔记(五)uniapp语法4
本章目标 授权登录【难点、重点】 条件编译【理解】 小程序分包【理解】 一、授权登录 我的模块其实是两个组件,一个是登录组件,一个是用户信息组件,根据用户的登录状态判断是否要显示那个组件 1、登录的基本布局 <template><…...
编写一个yolov5的模型检测,只要运行后,就不结束,只要有文件放入到文件夹中,就去执行读取
编写一个yolov5的模型检测,只要运行后,就不结束,只要有文件放入到文件夹中,就去执行读取 import os import cv2 import torch from torchvision import transforms from PIL import Image from yolo.model import YOLO…...
vscode调试PHP代码
目录 准备工作ssh的连接以及配置调试 准备工作 1.首先你需要下载一个vscode 2.下载模块 你需要在VScode中去下载我们所需的两个模块PHP Debug以及remote -ssh 3.安装对应版本的xdebug 需要在xdebug的官方去进行分析,选择适合你自己版本的xdebug 去往官方&#x…...
js reverse实现数据的倒序
2023.8.25今天我学习了如何在数组顺序进行倒序排列,如: 原数组为: 我们只需要对数组使用reverse()方法 let demo [{id: 1, name: 一号},{id: 2, name: 二号},{id: 3, name: 三号},]demo.reverse()console.log(demo) 扩展: 当我…...
日常踩坑记录
本篇文章主要介绍一下最近的开发中用到的些小问题。问题不大,但有些小细节,记录一下,有遇到的朋友可以看一下,有更好的解决方法欢迎分享。 浏览器记住密码自动填充表单 这个问题我在火狐浏览器遇到了。我登录系统时选择了浏览器…...
threejs特殊几何体(一:文字几何体对象)
threejs中文字几何体通过newTextGeometry()生成,它被单独作为一个类存在于threejs中const txtGeo new TextGeometry("threejs", { ...opts, font: font }); 我们先看效果: <template><div></div> &…...
链表的实现
本程序List链表用两种方式实现,一种是双向链表,一种是双向循环链表。循环双向链表和双向链表,它们的编码差别很小;但是循环链表在插入效率上胜出很多,同时查询时候更灵活。综合考虑,循环链表是首选。 另外…...
c++ std::mutex与std::condition_variable
1. std::mutex lock()加锁; try_lock()尝试加锁; unlock()解锁; std::mutex m_mutex; m_mutex.lock(); ... m_mutex.unlock(); 2. std::lock_guard 类模板;等同自动锁,直接取代lock()和unlock(); 构造时加锁,析构时解锁; std::mutex m_mutex; {std::lock_guard<std:…...
Aspose.Tasks for .NET V23Crack
Aspose.Tasks for .NET V23Crack 改进了大型项目的内存占用。 添加了API,允许您在应用程序无法访问系统字体文件夹时指定用户的字体文件夹。 Aspose.Tasksfor.NET是处理MicrosoftProject文件的可靠的项目管理API。API支持在不依赖Microsoft Project的情况下读取、写…...
vue过渡及动画
文章目录 前言类名使用自己定义动画样式多个元素过渡使用第三方库 前言 对于vue中的过渡与动画,官网上是这样概述的: Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。包括以下工具: 在 CSS 过渡和动画中自动…...
Linux环境下SVN服务器的搭建与公网访问:使用cpolar端口映射的实现方法
文章目录 前言1. Ubuntu安装SVN服务2. 修改配置文件2.1 修改svnserve.conf文件2.2 修改passwd文件2.3 修改authz文件 3. 启动svn服务4. 内网穿透4.1 安装cpolar内网穿透4.2 创建隧道映射本地端口 5. 测试公网访问6. 配置固定公网TCP端口地址6.1 保留一个固定的公网TCP端口地址6…...
【ubuntu】 DNS 设置工具 resolvectl
什么是 resolvectl “resolvectl” 是一个用于管理系统 DNS 解析配置的命令行工具。它是 systemd-resolved 服务的一部分,该服务是在许多基于 Systemd 的 Linux 发行版中用于管理网络配置和 DNS 解析的系统服务。 通过 resolvectl 命令,可以查看当前系…...
Keepalived+Lvs(dr)调度器主备配置小实验
目录 前言 一、实验拓扑图 二、配置LVS(dr)模式 三、配置调配器热备 四、测试 总结 前言 Keepalived和LVS(Linux Virtual Server)是两个常用的开源软件,通常结合使用以提供高可用性和负载均衡的解决方案。 Keepalive…...
第四讲Java基本语法——数组结构(多维数组)
前言 前面几讲,我们讲了Java基本语法,初学者也能够有一定的入门。本讲,我们也是继续来讲解一下Java另一个基础语法——数组,其实在前面讲解数据类型的时候,我们也有提到数组是引用类型,那今天我们就来分析一下什么是数组,怎么用数组呢? 一、数组是什么 数组是…...
【题解】JZOJ6578 / 洛谷P5201[USACO2019Jan]Shortcut G
洛谷 P5201 [USACO19JAN] Shortcut G 题意 在一个带权无向连通图上,每个点有 a i a_i ai 只奶牛,奶牛会走最短路径到 1 1 1,如果有多条路径,选择字典序最小的,定义移动总时间为所有奶牛走到 1 1 1 的时间之和。…...
npm install sentry-cli失败的问题
1. 目前报错 2. 终端运行 npm set ENTRYCLI_CDNURLhttps://cdn.npm.taobao.org/dist/sentry-cli npm set sentrycli_cdnurlhttps://cdn.npm.taobao.org/dist/sentry-cli3. 再安装 npx sentry/wizardlatest -i nextjs即可成功...
Node opensslErrorStack 错误解决方法记录
从Git仓库中下载了一个老项目,使用npm install 安装后没有问题,当我使用npm run dev 的时候遇到了 OpenSSL 相关错误,例如 opensslErrorStack: [error:03000086:digital envelope routines::initialization error] 网上找了一下相关信息&am…...
你知道什么是Grandmillennial风格吗,进来看看吧
如果你既欣赏祖母的印花棉布扶手椅和大胆的图案,又喜欢千禧一代朋友现代家居中的开放空间和时尚家具,那么 "千禧一代 “风格就是为你量身打造的。它借鉴了几十年来的流行趋势,形成了一种独特的、带有现代风格的老式设计。 在典型的 &quo…...
App Inventor 2 开发 ChatGPT 对话App
ChatGPT大家应该不会陌生,它的回答内容非常的专业及深入,具有实际的可指导性。我们通过App Inventor 2开发一个简单的对话App,先看效果: App Inventor 2 ChatGPT教育领域对话演示 代码块如下: 用到的核心组件“ChatBot…...
SQL 大小敏感问题
在SQL中,关键字和函数名 是不区分 大小写的 比如(select、where、order by 、group by update 等关键字),以及函数(ABS、MOD、round、min等) window系统默认是大小写不敏感 (ZEN文件和zen 文件 不能同时存在ÿ…...
微信小程序+Taro 混编,Taro 使用微信原生 behaviors
最近有一个小程序项目,因为一些原因项目架构选择了微信小程序原生Taro 混编的方式进行开发,在开发的过程中发现 Taro 不支持使用原生的 behaviors 特性,因为混编的原因项目当中已有原生页面在使用 behaviors,所以需要一个方案在不…...
b树/b+树、时间轮、跳表、LSM-Tree
b树、b树:关系型数据库核心存储结构 1、为什么磁盘数据存储结构用B树、而不用红黑树 磁盘每次读取不是读一个节点、是返回一页数据。 红黑树每次遍历一个节点排除一半数据。 B树通常映射相邻的磁盘页数据。4K mysql索引一个节点隐射16k故而映射4倍,故…...
Unity OnDrawGizmos的简单应用 绘制圆形
编辑器和配置表各有各的好。 卡牌游戏即使再复杂,哪怕是梦幻西游,大话西游那种,甚至wow那种,用配表都完全没问题。但是崩坏3,或者鬼泣,格斗游戏,可视化编辑器是唯一的选择。 开发初期刚开始配技…...
Uniapp笔记(四)uniapp语法3
一、商品详情 1、从商品列表页跳转到商品详情页 在商品列表的项中绑定单击事件,并传递商品id值 <view class"goods-item" v-for"(item,index) in goodsList" :key"index" click"goGoodsDetail(item.goods_id)"> &…...
leetcode做题笔记105. 从前序与中序遍历序列构造二叉树
给定两个整数数组 preorder 和 inorder ,其中 preorder 是二叉树的先序遍历, inorder 是同一棵树的中序遍历,请构造二叉树并返回其根节点。 思路一:递归 struct TreeNode* buildTree(int* preorder, int preorderSize, int* ino…...
Python里的列表List求和
1、使用sum()函数 numbers [1, 2, 3, 4, 5] total sum(numbers) print(total) # 输出 15 2、注意事项 在使用 sum() 函数获取列表的总和时,需要注意以下几点: sum() 函数只能用于数字类型的可迭代对象,如果 iterable 中包含了非数字类…...
启动docker容器的几种方法和注意事项(docker-compose,dockerfile)
1:要启动容器必须都先创建好镜像文件 C:\Users\dell>docker images REPOSITORY TAG IMAGE ID CREATED SIZE poi 1.0 22738bb31074 4 hours ago 105MB redis latest 506734eb5e71 6 days ago 138MB ng…...
bash: conda: command not found
问题描述: 在Pycharm上用SSH远程连接到服务器,打开Terminal准备查看用 conda 创建的虚拟环境时,却发现调用 conda 指令时出现以下报错: -bash: conda: command not found如果使用Xshell 利用端口号直接连接该 docker 容器&#…...
怎样制作网站二维码/平面设计
《Windows Azure Platform 系列文章目录》 本章介绍的内容是将本地Hyper-V的VHD,上传到Azure数据中心,作为自定义的虚拟机模板。 注意:因为在制作VHD的最后执行了Sysprep命令,所以该VHD中的OS会重新部署。 如果您想迁移本地的Hype…...
我想自己创建购物网站/网站一般需要怎么推广
一、包名 包名命名规范:包名一律小写,采用如下规则:【com】.【公司名/组织名】.【项目名称】.【模块名】,例如:com.foreverstar.xxx 1.com.xx.应用名称缩写.模块.activity 页面用到的Activity类 (activitie层级名用户界面层) 2.com.xx.应用名称缩写.模块.fragment …...
在百度网站备案查询上显示未备案是什么意思/百度竞价排名利弊
基于命令行执行jar的外放配置文件的执行方法 配置文件在工程目录存放位置: src/conf/application.properties打包生成sproutgis-exec.jar文件 拷贝到/usr/test目录下,目录内容: #--------------------------------------- conf/application.properties…...
淄博做网站小程序的公司/惠州seo外包服务
洛谷 P1886 滑动窗口 (单调队列) 题解 洛谷 P1886 题目 有一个长为 nnn 的序列 aaa,以及一个大小为 kkk 的窗口。现在这个从左边开始向右滑动,每次滑动一个单位,求出每次滑动后窗口中的最大值和最小值。 例如&…...
江苏专业做网站的公司/数字营销网站
转自:http://blog.chinaunix.net/uid-9688646-id-3087625.html 一个由C/C编译的程序占用的内存分为以下几个部分 1、栈区(stack)— 由编译器自动分配释放 ,存放函数参数值,局部变量的值等。其操作方式类似于数据结构中…...
精美合同网站建设/最好的优化公司
DNS域名解析 简单的说就是把域名翻译成 IP 地址,但如果在浏览器直接输入IP,则跳过这个步骤。 DNS寻找解析顺序: 浏览器缓存解析 操作系统缓存解析 公共域名服务器解析(根域名服务器/Root Server,主域名服务器&…...