JAVA写的坦克大战(单机图片版)

第一次写那么大的程序(感觉还是不错)


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
时间: 2024-11-07 06:14:46

JAVA写的坦克大战(单机图片版)的相关文章

分享一下Java写的坦克大战游戏,相信很多人小时候玩过

写在前面 程序是五六年前读书的时候写的,里面会有一些不规范的,我已经将代码传到github上了,有时间会优化修改. 程序运行机制 定义了一个JPanel,然后每隔一小段时间重绘一遍. 重绘的内容如下: 地图信息: 敌方坦克: 我方坦克: 右边游戏基本信息: 炸弹爆炸. 涉及一些逻辑: 重叠判断: 坦克什么时候改变方向: 坦克什么时候射击: 坦克中弹之后的处理: 砖块.铁块.河流中弹,碰撞逻辑: ...等等 如何执行程序 下载源码: 执行maven命令clean package,可在target目

(java项目)坦克大战 2.0

这个版本,只能算是一个雏形,把最基本的东西给完成了,不过,后面可添加的也不多.有一点,还是想去实现,那就是敌方坦克自己寻找对手!也就是游戏AI. emmm, 什么时候可以了解一下这个AI.顺便学学python. 这个帖子只是为了贴上代码,对后续的代码作为优化和添加游戏AI做准备的. 1. 各类接口 package Event; /* *具有攻击力的接口 */ public interface Attackable { /* * 校验具有攻击力的实物, 和, 具有被攻击的实物,是否能撞在一起 *

java课程设计--坦克大战

java课程设计--坦克大战 一. 团队课程设计博客链接 https://www.cnblogs.com/zwtcyt/p/12173572.html 二.个人负责模块和任务说明 墙体类,子弹类,道具类以及音效类的编写,部分GUI的编写 三.代码的提交记录截图 四.负责模块和任务详细说明 墙体类 主墙体即不可摧毁的墙体 该类为所有障碍物的父类,子类继承时改变里面draw方法 草地类 河流类 可摧毁的墙类 音效类 子弹类 子弹与碰撞检测 利用javafx中shape的intersect方法来得出两

【blade04】用面向对象的方法写javascript坦克大战

前言 javascript与程序的语言比如C#或者java不一样,他并没有“类”的概念,虽然最新的ECMAScript提出了Class的概念,我们却没有怎么用 就单以C#与Java来说,要到真正理解面向对象的程度也是要花一点功夫的,特别是初学的同学往往意识不到面向对象的好处,因为我们编码的流程是这样的 ① 面向过程 这个时候,我们要思想一个东西,往往就用一个大代码段完成了 ② 方法重用 我们有时候再也受不了重复的代码在一个地方存在了,于是这个时候我们会将相同的逻辑抽象为一个方法 ③ 当代码达到一

坦克大战1.0版项目实战

这里终于要开始我们的坦克大战的开发了! 正文 我个人并不认为在一个足够大的项目中一个人能尽善尽美地把所有因素都考虑在内,或许有那样的人,但做程序员太可惜了:),但是我们不能说不能全部顾着,就什么都不管不顾了.既然大多数人都不能把所有因素都考虑在内,又不能不管不顾,那么我们要考虑什么?要怎么去做,让我们的程序有章法,有很好地扩展性?我想这会是一个恒久的问题.但我个人有几点对自己做项目时考虑的想法! 首先:我们的项目得有版本意识,就正如市场上所有的软件一样,它们必定会有版本,我们不可能一次性把所有功

坦克大战1.0版

心得 1.熟悉了Actionlistener的用法 2.了解了awt类的使用方法 体会 1.创建了属于自己的坦克 2.未来将不断更新,做出一款好玩的坦克大战 原文地址:https://www.cnblogs.com/kendn/p/8319290.html

java学习之坦克大战游戏

总结:由于这几天快过年比较忙然后没怎么写,写代码途中一些经验总结现在给忘记了.这次的小项目感觉比上次写的思路清楚了点.没有之前第一次写那么逻辑混乱,结构也搞的比之前的要好,添加功能比较容易.学习了之前的经验,操作对象的方法由对象本身提供.不过这次小项目还有不足和不完善之处,有些可以做的功能没有实现,比如游戏存档,这里应该可以用下对象的序列化,还有游戏难度的设置也可以写个文件弄出来.要过年了,到处走亲戚没什么心思写了,这里只能留个尾巴了. 前言:之前的及时通信项目完成后感觉线程方面和对java的运

JAVA乐趣之坦克大战系列7

前言本篇主要介绍Robocode中如何对敌方进行扫描以便于更好的通过扫描结果不断改变自身的移动和***方式.扫描策略扫描策略的主要目标就是能够更好的锁定对方,即让敌方在我们的视野范围之内,或者使用更专业的名词-雷达锁定.为了锁定目标,我们可以把雷达往反方向扫描.因为雷达旋转很快,而雷达的方向与对方坦克方向的偏移量不大,机器人是有一定大小的.于是扫描线在目标身上来回扫动,实现了雷达锁定.代码示例如下:1.double?RadarOffset=敌人的绝对角度-雷达方向??2.setTurnRadar

坦克大战系列(8.0版)

人生在勤,不索何获.--张衡 本讲内容:坦克大战8.0版(面向对象的思想) 一.解决:防止敌人坦克重叠运动 1.定义一个Vector容器,装所有敌人的坦克(为了得到所有坦克坐标) 2.定义一个方法getEts()可以得到敌人的坦克(为了得到所有坦克坐标) 3.在我的我的面板的构造方法调用getEts() 4.定义一个判断是否碰到了别的敌人的坦克的方法isTouchOtherEnemy() 5.在设置敌人坦克随机走动那调用isTouchOtherEnemy() 二.解决:我方坦克死亡(即隐身)后,