JAVA写的坦克大战(简单)

【Java实战】Java实现坦克大战(韩顺平版) 该坦克大战运用了JavaGUI图形库,多线程,文件IO,反射等Java高级编程中的知识,用来巩固Java语法非常合适。我在韩老师原版的设计上做了一些改变,敌方坦克会永远保持三个,你每杀死一辆敌方坦克,并会在屏幕内随机生成一个敌方坦克以此来增加游戏乐趣,其他内容与原版无异。下面是展示图:该项目总共九个类,包含近1000行代码。 阅读详情

这里写图片描述
这里写图片描述
这里写图片描述
这里写图片描述


package _25增加配置文件;

import java.awt.*;
import java.awt.event.*;
import java.util.List;

import java.util.ArrayList;
/**
 * 这是这款游戏的主窗口,各个类都有他的引用
 * @author ☆东★
 *
 */
public class TankClient extends Frame{
    private Image offScreamImage = null;
    public static int WIDTH,HEIGHT;
    public int times = 0;//用来表示发了几发炮弹
    public List<Bullets> myBullets = new ArrayList<Bullets>();//代表还有几发炮弹
    public List<Explode> explodes = new ArrayList<Explode>();
    public List<Tank> enemyTank = new ArrayList<Tank>();
    public Tank myTank = new Tank(50,500,true,Direction.STOP,this);//把TankClient对象传进去,使Tank可以操作TankClient里面的部分数据

    public int width = Toolkit.getDefaultToolkit().getScreenSize().width;
    public int height = Toolkit.getDefaultToolkit().getScreenSize().height;

    public Wall wall1 = new Wall(100,100,20,200,this);
    public Wall wall2 = new Wall(300,450,70,70,this);
    public Blood b = new Blood(this);
    private boolean GAME_OVER = false;

    /**
     * 这个方法时画出图形的主要方法,其他类实现的图形,最终都要放到这个方法中
     */
    public void paint(Graphics g) {
        wall1.draw(g);
        wall2.draw(g);
        b.draw(g);
        myTank.drawTank(g);
        myTank.eat(b);

        /**
         * 当敌人没有了,就再生成一些敌人
         */
        if(enemyTank.size()==0){
            int reinitTank = Integer.parseInt(GetProp.getProp("reTankCount"));
            for(int i = 0;i<reinitTank;i++){
                Tank t = new Tank(50+80*i,50,false,Direction.STOP,this);
                t.GAME_LEVEL -= 3 ;
                enemyTank.add(t);
            }
        }
        /**
         * 每隔25毫秒就重画地方所有坦克
         */
        for(int i=0 ;i<enemyTank.size();i++){//画出敌人坦克
            Tank t = enemyTank.get(i);
            t.hitWall(wall1);
            t.hitWall(wall2);
            t.hitTank(enemyTank);//敌方坦克不能互相碰撞
//          myTank.hitTank(enemyTank);//使我方坦克也不能喝敌方坦克相碰(这个还有点问题  以后研究)
            t.drawTank(g);
        }
        /**
         * 画出爆炸
         */
        for(int i = 0;i<explodes.size();i++){
            Explode e = explodes.get(i);
            e.draw(g);
        }
        /**
         *  给用户的提示信息
         */
        g.setFont(new Font("", Font.BOLD, 15));//设置字体
        if(times>=30){
            g.drawString("还有多少发炮弹:"+0, 10, 50);
            g.setColor(Color.red);
            g.drawString("没炮弹了(充钱)", 20, 75);
        }
        else{
            g.drawString("还有多少发炮弹:"+(30-times), 10, 50);
            g.drawString("敌方坦克:"+enemyTank.size(), 10, 70);
        }
        /**
         * 画子弹,当子弹没有了,就不能画子弹了
         */
        if(myBullets.size()!=0)
        for(int i=0;i<myBullets.size();i++){
            Bullets b = myBullets.get(i);//创建这一发炮弹  这一发子弹里面有坐标有方向
            b.hitTanks(enemyTank);//判断是否击中坦克(击中了就设置live标志为false)
            b.hitTank(myTank);
            b.hitWall(wall1);//设置子弹撞墙时的动作
            b.hitWall(wall2);//设置子弹撞墙时的动作
            b.draw(g);//当击中坦克,子弹自己就不再画自己了(通过坦克自己内部的live标志)
        }
    }

    /**
     * 添加双缓冲消除闪烁现象
     */
    public void update(Graphics g) {
        if(offScreamImage == null){
            offScreamImage = this.createImage(WIDTH,HEIGHT);//把所有东西都画在这张图片上
        }

        Graphics gOffScream = offScreamImage.getGraphics();//获取这张图片的画笔
        //下面是重画屏幕,使他恢复原来的颜色
        Color c = g.getColor();
        gOffScream.setColor(Color.gray);
        gOffScream.fillRect(0, 0, WIDTH, HEIGHT);
        gOffScream.setColor(c);

        paint(gOffScream);//调用paint方法。使这张图片也画上   paint方法里面的图片

        g.drawImage(offScreamImage, 0, 0, null);
    }

    /**
     * 程序开始的主方法
     */
    public void lauchFrame(){
        //获取屏幕信息
        Toolkit kit = Toolkit.getDefaultToolkit();
        Dimension size = kit.getScreenSize();
        WIDTH = size.width/2+size.width/4;
        HEIGHT = size.height/2+size.height/4;
        this.setBounds(size.width/8,size.height/8,WIDTH,HEIGHT);

        Image image = kit.getImage("1.jpg");
        setIconImage(image);

//      this.setResizable(false);//设置不可以调整大小
        this.setBackground(Color.gray);
//      setUndecorated(true);//把标题栏去掉
//      setUndecorated(true);//全屏
//      getGraphicsConfiguration().getDevice().setFullScreenWindow(this);


        this.addWindowListener(new WindowAdapter(){
            public void windowClosing(WindowEvent e) {
                GAME_OVER = true;
                System.exit(0);
            }
        });
        this.addKeyListener(myTank.new MyKeyEvent());

        //使用配置文件
        int initTankCount = Integer.parseInt(GetProp.getProp("initTankCount"));
        for(int i = 1;i<initTankCount;i++){
            enemyTank.add(new Tank(50+50*i,50,false,Direction.STOP,this));
        }

        setVisible(true);

        new Thread(new PaintThread()).start();//创建一个线程,重画
    }

    public static void main(String[] args) {
        new TankClient().lauchFrame();
    }

    /**
     * 重画的一个线程
     * @author ☆东★
     *
     */
    private class PaintThread implements Runnable{
        public void run() {
            while(!GAME_OVER){
                repaint();
                try {
                    Thread.sleep(25);//每80毫秒重画一次
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
/*//获取屏幕信息
   Toolkit kit = Toolkit.getDefaultToolkit();
   Dimension size = kit.getScreenSize();
   int screenWidth = size.width;
   int screenHeight = size.height;
   //设置窗口宽高
   jf.setSize(screenWidth/4, screenHeight/4);
   jf.setLocation(screenWidth/4, screenHeight/4);
   //设置图标
   Image image = kit.getImage("smile.gif");
   jf.setIconImage(image);


    void setResizable(boolean resizable) 
          设置此窗体是否可由用户调整大小。 

    public abstract Color getColor()获取此图形上下文的当前颜色。

    public abstract void setColor(Color c)将此图形上下文的当前颜色设置为指定颜色。使用此图形上下文的所有后续图形操作均使用这个指定的颜色。 

    public void repaint()重绘此组件。 
    如果此组件是轻量级组件,则此方法会尽快调用此组件的 paint 方法。否则此方法会尽快调用此组件的 update 方法。

    abstract  boolean drawImage(Image img, int x, int y, ImageObserver observer) 
          绘制指定图像中当前可用的图像。 
 */
package _25增加配置文件;

import java.awt.*;
import java.awt.event.*;
import java.util.*;
/**
 * 画坦克的主要类
 * @author ☆东★
 *
 */
public class Tank {
    private int x,y;// x  y  代表了tank现在的位置
    private int oldX,oldY;//记录坦克上一步的位置
//  private static final int WIDTH = 30,HEIGHT = 30;//坦克大小
    private static final int WIDTH = 50,HEIGHT = 50;//坦克大小
    private static final int XSPEED = 5,YSPEED = 5;//坦克xy方向运动速度 
    public int GAME_LEVEL = 14;//默认游戏难度为12  越高越简单,最高17  最低3
    //想让Tank向8个方向走
    private boolean bL = false ,bU = false ,bR = false ,bD = false;//用于记录  键盘按下的  上下左右  (按下之后就设置为True)
    private Direction dir = Direction.STOP;//坦克的最开始的方向
    private Direction ptDir = Direction.D;//炮筒最开始的方向
    private TankClient tc = null;
    private boolean good ;
    private boolean live = true;
    private static Random rand = new Random();
    private int step = rand.nextInt(15)+3;//设置随机朝一个方向移动的步数,不然老是在同一个地方乱动
    private int life = 100;//给我方坦克设置血量
    private BloodBar bb  = new BloodBar();

    /**
     * 增加图片
     */
    private static Toolkit tk = Toolkit.getDefaultToolkit();
    private static Map<String,Image> imags = new HashMap<String,Image>();
    private static Image[] tankImage = null;
    static {
        tankImage = new Image[]{
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankL.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankLU.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankU.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankRD.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankR.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankRU.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankD.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/tankLD.gif"))
        };
        imags.put("L", tankImage[0]);
        imags.put("LU", tankImage[1]);
        imags.put("U", tankImage[2]);
        imags.put("RD", tankImage[3]);
        imags.put("R", tankImage[4]);
        imags.put("RU", tankImage[5]);
        imags.put("D", tankImage[6]);
        imags.put("LD", tankImage[7]);
    }

    public int getLife() {
        return life;
    }
    public void setLife(int life) {
        this.life = life;
    }
    public void setGood(boolean good) {
        this.good = good;
    }
    public boolean isGood() {
        return good;
    }
    public boolean isLive() {
        return live;
    }
    public void setLive(boolean live) {
        this.live = live;
    }

    public Tank(int x,int y,boolean good,Direction dir,TankClient tc){//获取TankClient的引用,让Tank可以调用TankClient里面的数据,因为子弹的方向是由Tank决定的,而TankClient要获取Bullets方向
        this.x = x;
        this.y = y;
        this.good = good;
        this.dir = dir;
        this.tc = tc;
    }

    public void drawTank(Graphics g){//坦克自己画自己
        if(!live){
            tc.enemyTank.remove(this);
            return;
        }

        if(good){
            bb.draw(g);
        }

        ptDraw(g);//画炮筒

        move();
    }
    /**
     * 用于判断  tank 往哪个方向走        用枚举里面的数   来判断是往哪个方向走的    从此 x y 的改变就从move这个方法里面改变(原来是从KeyAdapter 里面改变的)
     */
    private void move(){
        oldX = x;//记录上一步的位置
        oldY = y;

        switch(dir){//dir决定最终坦克的方向
        case L : 
            x-=XSPEED; break;
        case LU :
            x-=XSPEED; y-=YSPEED; break;
        case U :
            y-=XSPEED; break;
        case RD :
            x+=XSPEED; y+=YSPEED; break;
        case R :
            x+=XSPEED; break;
        case RU :
            x+=XSPEED; y-=YSPEED; break;
        case D :
            y+=YSPEED; break;
        case LD :
            x-=XSPEED; y+=YSPEED; break;
        case STOP : break;
        }
        /**
         * 判断是否出界
         */
        if(x<=5)
            x = 5;
        if(y<=30)
            y = 30;
        if(x>=TankClient.WIDTH-Tank.WIDTH-5)
            x = TankClient.WIDTH-Tank.WIDTH-5;
        if(y>=TankClient.HEIGHT-Tank.HEIGHT-5)
            y=TankClient.HEIGHT-Tank.HEIGHT-5;

        /**
         * 给炮筒一个方向
         */
        if(this.dir != Direction.STOP)//如果地方坦克   坦克方向不为Stop,,那么改变炮筒方向(与坦克方向一样)
            ptDir = dir;
        /**
         * 让炮筒发射子弹
         */
        if(!good){//如果是敌方坦克
            if(step == 0){
                Direction[] arr = Direction.values();// 把enum转化为数组
                int r = rand.nextInt(arr.length);//从0到arr的最大长度
                dir = arr[r];
                step = rand.nextInt(15)+3;//生成0---14之间的数

                //给敌方tank增加炮弹。。不能太密集
                if(step>=GAME_LEVEL) fire();
            }
            step--;
        }
    }
    /**
     * 画出炮筒
     * @param g
     */
    private void ptDraw(Graphics g){
        switch(ptDir){
        case L : 
            g.drawImage(imags.get("L"),x, y, null); break;
        case LU :
            g.drawImage(imags.get("LU"),x, y, null); break;
        case U :
            g.drawImage(imags.get("U"),x, y, null); break;
        case RD :
            g.drawImage(imags.get("RD"),x, y, null); break;
        case R :
            g.drawImage(imags.get("R"),x, y, null); break;
        case RU :
            g.drawImage(imags.get("RU"),x, y, null); break;
        case D :
            g.drawImage(imags.get("D"),x, y, null); break;
        case LD :
            g.drawImage(imags.get("LD"),x, y, null); break;
        case STOP :
            g.drawImage(imags.get("STOP"),x, y, null); break;
        }
    }
    /**
     * Tank真正走的方向  L, LU, U, RD, R, RU, D, LD, STOP   取决于dir的值
     */
    private void realDirection(){
        if(bL && !bU && !bR && !bD)
            dir = Direction.L;
        else if(bL && bU && !bR && !bD)
            dir = Direction.LU;
        else if(!bL && bU && !bR && !bD)
            dir = Direction.U;
        else if(!bL && !bU && bR && bD)
            dir = Direction.RD;
        else if(!bL && !bU && bR && !bD)
            dir = Direction.R;
        else if(!bL && bU && bR && !bD)
            dir = Direction.RU;
        else if(!bL && !bU && !bR && bD)
            dir = Direction.D;
        else if(bL && !bU && !bR && bD)
            dir = Direction.LD;
        else if(!bL && !bU && !bR && !bD)
            dir = Direction.STOP;
    }
    /**
     * Tank发射子弹   给子弹一个信号,,让子弹往自己指定的方向发子弹
     */
    private void fire(){
        if(good)
            tc.times++;//每次 发子弹的时候,设置一个计数器

        int x = this.x + Tank.WIDTH/2 - Bullets.WIDTH/2;
        int y = this.y + Tank.HEIGHT/2 - Bullets.HEIGHT/2;
        Bullets b = new Bullets(x,y,ptDir,good,tc);

        if(!good)//地方塔克可以一直创建子弹
            tc.myBullets.add(b);
        else if(tc.times<30 && live){//如果是我方坦克,发子弹次数少于20次,而且坦克活着,那么就装一发炮弹
            tc.myBullets.add(b);
        }//这样做保证了,当自己的子弹用完了,敌方还可以发炮弹
    }
    /**
     * 超级炮筒
     */
    private void superFire(){
        Direction[] arr = dir.values();//转化为数组
        for(int i = 0;i<8;i++){
            fire(arr[i]);
        }
        tc.times += 4;//相当于给散弹多一点子弹  发一发相当于以前发4发
    }
    /**
     * 发射超级炮弹
     * @param dir 不受炮筒方向控制的炮弹
     */
    private void fire(Direction dir){
        int x = this.x + Tank.WIDTH/2 - Bullets.WIDTH/2;
        int y = this.y + Tank.HEIGHT/2 - Bullets.HEIGHT/2;
        Bullets b = new Bullets(x,y,dir,good,tc);

        if(tc.times<30 && live){//如果是我方坦克,发子弹次数少于80次
            tc.myBullets.add(b);
        }
    }
    /**
     * 判断两个矩形是否相碰的方法
     * @return 返回值在判断是否相碰会用到
     */
    public Rectangle getRect(){
        return new Rectangle(x,y,WIDTH,HEIGHT);
    }
    /**
     * 判断是否撞墙
     * @param w 墙
     */
    public void hitWall(Wall w){
        if(live && this.getRect().intersects(w.getRect())){
            x = oldX;
            y = oldY;
        }
    }
    public void hitTank(java.util.List<Tank> tanks){
        for(int i = 0;i<tanks.size();i++){
            Tank t = tanks.get(i);
            if(this != t)//这一个判断非常重要,不然自己肯定和自己是相碰的,全都不动了
            if(live && this.getRect().intersects(tanks.get(i).getRect())){
                x = oldX;
                y = oldY;
            }
        }
    }
    /**
     * 吃血块方法
     * @param b 血块
     */
    public void eat(Blood b){
        if(this.live && this.getRect().intersects(b.getRect())){
            this.life = 100;
            b.setLive(false);
        }
    }
    /**
     * 画血量
     * @author ☆东★
     *
     */
    private class BloodBar{
        public void draw(Graphics g){
            Color c = g.getColor();
            g.setColor(Color.red);
            g.drawRect(x, y-15, WIDTH, HEIGHT/4);
            int width = WIDTH * life/100;
            g.fillRect(x, y-15, width, HEIGHT/4);
            g.setColor(c);
        }
    }

    /**
     * 添加按键事件
     * @author ☆东★
     *
     */
    class MyKeyEvent extends KeyAdapter{
        public void keyPressed(KeyEvent e) {
            int key = e.getKeyCode();
            switch(key){
            case KeyEvent.VK_UP    : bU = true; break;//注意这里不能用e.VK_UP  e是变量了,不能出现变量
            case KeyEvent.VK_DOWN  : bD = true; break;
            case KeyEvent.VK_RIGHT : bR = true; break;
            case KeyEvent.VK_LEFT  : bL = true; break;

            case KeyEvent.VK_Q     : fire(); break;//按下Q键就可以获取子弹  的位置和  坦克现在的方向(子弹的方向)然后调用paint函数重画子弹
            case KeyEvent.VK_W     : superFire(); break;
            case KeyEvent.VK_SPACE : tc.times = 0; break;
            case KeyEvent.VK_F2    : if(!live) { live = true; life = 100;}//获得重生
            }
            realDirection();//上面只是判断是那几个按键被按下,,最终tank的走向是看dir的值
        }
        public void keyReleased(KeyEvent e) {
            int key = e.getKeyCode();
            switch(key){
            case KeyEvent.VK_UP    : bU = false; break;//注意这里不能用e.VK_UP  e是变量了,不能出现变量
            case KeyEvent.VK_DOWN  : bD = false; break;
            case KeyEvent.VK_RIGHT : bR = false; break;
            case KeyEvent.VK_LEFT  : bL = false; break;
            }
            realDirection();//上面只是判断是那几个按键被释放
        }
    }
}
package _25增加配置文件;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Toolkit;
/**
 * 爆炸类
 * @author ☆东★
 *
 */
public class Explode {//爆炸
    private int x , y;
    private boolean live = true;
    private int step = 0;//画到第几步了
    private TankClient tc;
    private static boolean init;
    private static Toolkit tk = Toolkit.getDefaultToolkit();
    private static Image[] image = {
            tk.getImage(Explode.class.getClassLoader().getResource("images/0.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/1.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/2.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/3.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/4.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/5.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/6.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/7.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/8.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/9.gif")),
            tk.getImage(Explode.class.getClassLoader().getResource("images/10.gif"))
    };

    Explode(int x,int y,TankClient tc){
        this.x = x;
        this.y = y;
        this.tc = tc;
    }

    public void draw(Graphics g){
        if(!init){
            for (int i = 0; i< image.length; i++) {//会发现第一次打敌人,不会出现爆炸。可能是系统第一次 加载图片的时候不会放到内存中
                g.drawImage(image[i], 100, 100, null);
            }
            init = true;
        }

        if(!live){
            tc.explodes.remove(this);//当爆炸不存在了,就从TankClient的爆炸集合中移除当前爆炸
            return ;
        }
        if(step==11){
            this.live = false;
            this.step = 0;
            return ;
        }
        g.drawImage(image[step++], x, y, null);
    }
}
package _25增加配置文件;
/**
 * 方向的枚举
 * @author ☆东★
 *
 */
public enum Direction {
    L, LU, U, RD, R, RU, D, LD, STOP//用来表示Tank是朝 哪个方法走的   以后这个枚举就来代表坦克的走向
}
package _25增加配置文件;

import java.awt.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * 子弹类
 * @author ☆东★
 *
 */
public class Bullets {//子弹类
    private int x,y;//坦克的位置,也是子弹的位置
    private boolean live = true;
    public static final int WIDTH = 10, HEIGHT = 10;//子弹大小
    private static final int XSPEED = 10,YSPEED = 10;//子弹速度
    private TankClient tc;
    private boolean good;//用于标识子弹是哪一方的子弹
    Direction dir;

    private static Toolkit tk = Toolkit.getDefaultToolkit();
    private static Map<String,Image> imags = new HashMap<String,Image>();
    private static Image[] tankImage = null;
    static {
        tankImage = new Image[]{//L, LU, U, RD, R, RU, D, LD, STOP
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileL.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileLU.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileU.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileRD.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileR.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileRU.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileD.gif")),
                tk.getImage(Explode.class.getClassLoader().getResource("images/missileLD.gif"))
        };
        imags.put("L", tankImage[0]);
        imags.put("LU", tankImage[1]);
        imags.put("U", tankImage[2]);
        imags.put("RD", tankImage[3]);
        imags.put("R", tankImage[4]);
        imags.put("RU", tankImage[5]);
        imags.put("D", tankImage[6]);
        imags.put("LD", tankImage[7]);
    }

    public Bullets(int x,int y,Direction dir,boolean good,TankClient tc){
        this.x = x;
        this.y = y;
        this.dir = dir;
        this.good = good;
        this.tc = tc;
    }

    public void draw(Graphics g){
        if(!live){
            tc.myBullets.remove(this);//用于删除子弹。不然这一发子弹打中敌人,另一个敌人来到这个地方也会死
            return;
        }
        if(good){
            Color c = g.getColor();
            g.setColor(Color.black);
            g.fillOval( x, y, WIDTH, HEIGHT);
            g.setColor(c);
        }

            switch(dir){
            case L : 
                g.drawImage(imags.get("L"),x, y, null); break;
            case LU :
                g.drawImage(imags.get("LU"),x, y, null); break;
            case U :
                g.drawImage(imags.get("U"),x, y, null); break;
            case RD :
                g.drawImage(imags.get("RD"),x, y, null); break;
            case R :
                g.drawImage(imags.get("R"),x, y, null); break;
            case RU :
                g.drawImage(imags.get("RU"),x, y, null); break;
            case D :
                g.drawImage(imags.get("D"),x, y, null); break;
            case LD :
                g.drawImage(imags.get("LD"),x, y, null); break;
            case STOP :
                g.drawImage(imags.get("STOP"),x, y, null); break;
            }

        move();
    }

    //子弹自己的移动方向速度
    private void move() {
        switch(dir){
        case L : 
            x-=XSPEED; break;
        case LU :
            x-=XSPEED; y-=YSPEED; break;
        case U :
            y-=XSPEED; break;
        case RD :
            x+=XSPEED; y+=YSPEED; break;
        case R :
            x+=XSPEED; break;
        case RU :
            x+=XSPEED; y-=YSPEED; break;
        case D :
            y+=YSPEED; break;
        case LD :
            x-=XSPEED; y+=YSPEED; break;
        }

        if(x<0 || y<0 || x>TankClient.WIDTH || y>TankClient.HEIGHT){//子弹超出边界  就让他在子弹集合中删除
            live = false;
        }
    }

    public Rectangle getRect(){
        return new Rectangle(x,y,WIDTH,HEIGHT);
    }


    //下面就是判断  坦克是否被击中,一级击中后会发生的事,一个函数可以解决,第一个函数里面就是循环,可以把它放在第二个函数里(只是不容易看而已)
    public void hitTanks(List<Tank> tanks){
        for(int i=0;i<tanks.size();i++)
            hitTank(tanks.get(i));//每次,挨个挨个的判断每一辆坦克是否被击中
    }
    public void hitTank(Tank t){
        //判断是否这辆坦克的面积,是否和子弹相碰,,,,坦克必须活着,不然死了以后,子弹打到相同位置,子弹也会消失
        if(this.getRect().intersects(t.getRect()) && t.isLive() && this.good != t.isGood()){//boolean intersects(Rectangle r) 确定此 Rectangle 是否与指定的 Rectangle 相交。 
            if(t.isGood()){
                t.setLife(t.getLife()-20);//每当我们被击中就减少20滴血
                if(t.getLife()<=0)
                    t.setLive(false);
            } else//如果是敌方坦克就直接死
            t.setLive(false);//把塔克也弄死,,,把标志live设置为false(死)

            this.live = false;//把子弹也弄消失
            Explode e = new Explode(x,y,tc);//每次击中再增加一个爆炸类
            tc.explodes.add(e);//给TankClient的爆炸集合,增加一个爆炸
        }
    }

    public void hitWall(Wall w){//判断是否撞到墙了
        if(this.live && this.getRect().intersects(w.getRect())){
            this.live = false;
        }
    }

}
package _25增加配置文件;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;
import java.util.Random;
/**
 * 血量类
 * @author ☆东★
 *
 */
public class Blood {
    private int x ,y , w ,h;
    private TankClient tc;
    private boolean live = true;
    private Random rand = new Random();


    Blood(TankClient tc){
        this.tc = tc;
    }

    public boolean isLive() {
        return live;
    }
    public void setLive(boolean live) {
        this.live = live;
    }

    public void draw(Graphics g){
        if(!live) return ;
        x = rand.nextInt(tc.WIDTH/50)+600;
        y = rand.nextInt(tc.HEIGHT/50)+150;
        Color c = g.getColor();
        g.setColor(Color.green);
        g.fillRect(x, y, 20, 20);
        g.setColor(c);
    }

    public Rectangle getRect(){
        return new Rectangle(x, y, 20, 20);
    }

}
package _25增加配置文件;

import java.awt.Graphics;
import java.awt.Rectangle;
/**
 * 墙类
 * @author ☆东★
 *
 */
public class Wall {
    private int x,y,w,h;
    private TankClient tc;

    public Wall(int x, int y, int w, int h, TankClient tc) {
        super();
        this.x = x;
        this.y = y;
        this.w = w;
        this.h = h;
        this.tc = tc;
    }

    public void draw(Graphics g){
        g.fillRect(x, y, w, h);
    }

    public Rectangle getRect(){
        return new Rectangle(x,y,w,h);
    }

}
package _25增加配置文件;

import java.io.IOException;
import java.util.Properties;

/**
 * 使用配置文件,,采用了单例设计模式
 * @author ☆东★
 *
 */
public class GetProp {
    private static Properties prop = new Properties();

    static{
        try {
            prop.load(GetProp.class.getClassLoader().getResourceAsStream("config/tank.properties"));
        } catch (IOException e1) {
            e1.printStackTrace();
        }
    }

    private GetProp(){}

    public static String getProp(String key){
        return prop.getProperty(key);
    }

}
initTankCount=15
reTankCount=10
《Java小游戏实现》:坦克大战 《Java小游戏实现》:坦克大战前面写了一个简单的聊天小程序,今天开始就写一个坦克大战的游戏,算是对Java相关小知识点的一个应用。这个游戏的完成,我们也是分步完成,逐步累加,一个一个小功能的添加,最后直至完成整个游戏的开发。第一步:写一个界面 public class TankClient extends JFrame{ public static void main(Stri 阅读详情

相关推荐

Java坦克大战简易版1.0

java 编写的简易坦克大战,由键盘控制坦克移动,和子弹发射。控制坦克不能跑出游戏界面以外,以及删除飞出界面外的无效子弹。

weixin_42172720的博客 2218

Java坦克大战

Java坦克大战

weixin_72040135的博客 2198

Java游戏项目之坦克大战

视频课程讲解了一个坦克大战游戏的详细编写流程,即使你是刚入门Java的新手,只要你简单掌握了该游戏所需要的JavaSE基础知识,便可以跟随教程视频制作出属于你自己的坦克大战游戏!

平平无奇の小透明的博客 1621

java实现坦克大战

话不多说,直接上思维导图(比较粗略) 目录 ​窗口初始化 游戏父类的编写 添加坦克类 初始化子弹类 添加围墙、基地 添加游戏规则 窗口初始化 准备工作 首先创建一个TankWar项目,在scr相同路径下创建images、music文件夹,将需要使用的图片、音乐分别放在images、music中。创建一个com.tankwar(包),注意命名规范 窗口初始化 在com.tankwar中创建GamePanel类 import javax.swing.JFrame; public

小熙的博客 2万+

Java实现坦克大战【升级版】

笔者去各地打了一圈酱油,又忙一些离职换房子的事情,

码上行动的吐槽跟自恋 3154

java实现经典坦克大战及源代码下载

坦克大战 一、需求分析 坦克大战中有我方坦克和敌方坦克,我方坦克有一个,敌方坦克有多个。坦克可以移动,也可以发射子弹。我方坦克可以通过上下左右键来控制方向,敌方坦克自动改变方向。在游戏窗体中有障碍物,包括砖墙、钢墙、水墙和草地。坦克可以穿过草地,在遇到其他障碍物时,我方坦克停止移动,并通过操纵改变方向再移动,敌方坦克遇到其他障碍物时可以自动的改变方向。我方坦克有三次生命值,当与敌方坦克或敌方子弹相撞时,生命值减- -, 当生命值是零时,敌方胜利,游戏结束。敌方坦克的生命值为-一,当敌方坦克与我方坦克或.

Java_may的博客 1406

Java游戏开发 —— 坦克大战

坦克大战,所有坦克、砖墙等效果都是用Java自己画的,当然各种图片素材也包含在里面,但没用。

小木鱼的博客 1万+

Java小游戏之坦克大战

随着人们对生活质量的要求一天比一天高,为了让人们更好地开掘自身的智慧,游戏就此进入了大众的视野,在人们的生活中有着重要的位置,已然变得必不可少。游戏产业推动高新技术不断升级,极大地促进了经济的增长,推动了“第四产业”的经济腾飞。坦克大战游戏是童年时期经常玩的经典游戏,我们对它都十分了解。游戏通过分析JAVA游戏开发和代码设计,用Eclipse软件开发了坦克大战游戏,运用接口技术,使一个类能够实现多个接口,使用套接字Socket来完成client端和server端的连接。

qq_24907431的博客 1585

JAVA笔记(二十一):坦克大战【一】(Java绘图----绘制坦克、事件处理机制----坦克移动)

在这里,第一次在屏幕显示,所以系统自动调用。

欢迎~ 1393

java简易版坦克大战游戏

基于java的简易版坦克大战游戏,主要实现了坦克的移动,子弹的移动,坦克与子弹的碰撞,坦克和子弹是否出界,输掉游戏的检测等功能

华为CNA VRM搭建(使用vmware worfstartion搭建)

华为CNA和VRM在 vmware workstation安装使用

weixin_70595351的博客 1809

韩顺平--Java坦克大战

韩顺平坦克大战

闲言 1万+

卡尔曼滤波、互补滤波与Tsinghua滤波:平衡车姿态感知的三大算法对比

本文对比了平衡车姿态感知中的卡尔曼滤波、互补滤波与Tsinghua滤波三大核心算法。互补滤波计算简单,适合入门;卡尔曼滤波理论最优但实现复杂;Tsinghua滤波则是一种面向嵌入式优化的轻量级方案,通过动态权重调整和零偏估计,在资源受限的MCU上实现了性能与效率的平衡,是智能车竞赛等场景的实用选择。

weixin_29232121的博客 349

Java实现坦克大战小游戏

Java实现坦克大战小游戏 MyTankGame3.java Members.java MyTankGame3.java /** * 功能:坦克游戏的5.0[] * 1.画出坦克. * 2.我的坦克可以上下左右移动 * 3.可以发射子弹,子弹连发(最多5) * 4.当我的坦克击中敌人坦克时,敌人就消失(爆炸的效果) * 5.我被击中后,显示爆炸效果 * 6.防止敌人坦克重叠...

AnalogElectronic的博客 8072

从空调温控到信号降噪:一阶RC低通滤波器在Arduino和STM32上的C语言实现指南

本文详细介绍了如何在Arduino和STM32平台上使用C语言实现一阶RC低通滤波器,涵盖从基础理论到实际应用的完整流程。通过具体代码示例和优化技巧,帮助开发者有效处理传感器噪声、信号平滑等问题,提升嵌入式系统的信号处理能力。

weixin_30565199的博客 501

ADNI数据集下载(详细)

刚刚接触到这个数据集的时候比较头疼,用了好长的时间才把下载过程和预处理过程弄明白。需要发送电子邮件给官方平台,收到回信后才能够下载到数据集。 1、ADNI账号注册 第一步:搜索百度打开ADNI 第二步,点击ADTA&amp;amp;SAMPLES 第三步:一直将鼠标往下拉 点击ADNI,进入里面填写信息。需要填写的信息还是挺多的,耐心填写,再等到邮件回复就可以了 2、ADNI数据集下载 登录申请的邮...

蜗牛遥遥 3万+

基于java swing的坦克大战游戏

一.功能描述 java坦克大战主要功能: 1. 图形用户界面; 2. 有坦克、森林、河流、墙体等元素; 3. 界面中有一个我方大本营,我方大本营被敌方攻击则输游戏; 4. 墙体分为普通墙体和金属墙体两种,普通墙体可以被子弹射穿,金属墙体不能被子弹射穿; 5. 坦克可以通过森林,不能通过河流、墙体; 6. 坦克可以发射子弹,敌我双方的坦克属性相同; 7. 敌方坦克之间不能互相攻击

江江的博客 1万+

Masta调用Geometry Modeller(Space Claim)进行根据三维模型快速建模设置方法

masta中调用ANSYS的space claim的设置方法

xifegnlie的博客 239

Java———坦克大战

坦克大战

weixin_70139631的博客 1213

OpenAI最强编程助手Codex:下载安装、使用指南(含使用方式、提示技巧、趋势)

OpenAI最近上线了最强编程Agent——Codex,一起来看看吧!

Code_流苏:在代码中寻诗意,在实践中觅真知 1万+

ER图从入门到精通:数据库建模全攻略

本文为数据库建模领域的 ER 图全面指南,系统解析从基础概念到实战应用的核心要点。首先介绍 ER 图的定义、三大组成元素(实体、属性、关系)及三种基础关系类型(一对一、一对多、多对多);其次详解绘制流程,涵盖工具选择(如 Visio、PowerDesigner)、需求分析方法及实体 - 属性 - 关系的分步建模技巧;进一步探讨弱实体、复合属性等高级概念,结合范式理论讲解模型优化策略;针对实体属性混淆、关系类型误判等常见问题提供解决方案;最后通过电商系统、图书馆管理系统等实际案例展示 ER 图设计全流程。

邓邓子的博客 4212

java 实现简单的坦克大战 韩顺平

学习java,跟做韩顺平教程的坦克代战,总结了一份不正式的开发文档(开发过程的总结)。如有需要,提供完整代码和相关资源文件,可做参考。

qq_52046856的博客 1503

【云原生之Docker实战】使用docker部署Monica个人开源CRM系统

【云原生之Docker实战】使用docker部署Monica个人开源CRM系统

jks212454的博客 2383

坦克大战代码

package mytankgame; import javax.swing.; import java.awt.; import java.awt.event.*; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.FileReader; import java.io.FileWriter; ...

qq_38125191的博客 5162

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

JAVA游戏《坦克大战》(二)

JAVA游戏《坦克大战》(二) 控制坦克移动 在前面将场景创建完成后,下一步就是控制坦克的移动了,如果是仅是移动实现起来也比较简单,但是除了简单的移动还要处理好坦克到达边界的问题以及后面的多个坦克重叠的问题。 首先最重要的是进行按键的监听,在原先的类中写入按键监听 //键盘监听 private class Keynote extends KeyAdapter{ //键盘按下 @Override...

丘秋的博客 2290

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

上一篇: java写的记事本程序
下一篇: 字节序不是由操作系统决定的,而是由cpu架构决定的
帅东
博客等级 码龄11年 676粉丝 88原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值