• (java项目)坦克大战 2.0


    这个版本,只能算是一个雏形,把最基本的东西给完成了,不过,后面可添加的也不多。有一点,还是想去实现,那就是敌方坦克自己寻找对手!也就是游戏AI.

    emmm, 什么时候可以了解一下这个AI。顺便学学python。

    这个帖子只是为了贴上代码,对后续的代码作为优化和添加游戏AI做准备的。


    1. 各类接口

    package Event;
    /*
     *具有攻击力的接口
     */
    public interface Attackable {
        /*
         * 校验具有攻击力的实物, 和, 具有被攻击的实物,是否能撞在一起
         *
         */
        boolean checkAttack(Hitable hit);
    }
    package Event;
    /*
     * 具有阻挡功能的实物
     */
    public interface Blockable {
    
    }
    package Event;
    /*
     * 能被销毁的类
     */
    import domain.Blast;
    /*
     * 销毁接口
     */
    public interface Destoryable {
        /*
         * 判断是否需要销毁
         */
        boolean isDestoryable();
        
        /*
         * 销毁时,绘制爆炸物
         */
        Blast showDestory();
    }
    package Event;
    
    import domain.Blast;
    /*
     * 能被攻击的类
     */
    public interface Hitable {
        Blast showAttack();
    }
    package Event;
    /*
     * 具有移动功能的事物
     * 
     */
    public interface Moveable {
        boolean checkHit(Blockable blockable);
    }

    2.各类游戏元素的父类

    package domain;
    
    /*
     * 父类:
     * 是砖墙,坦克,水墙等所有元素的抽象出来的抽象类
     */
    public abstract class Element {
        /*
         * 属性
         * 坐标
         */
        protected int x;
        protected int y;
        //宽高
        protected int width;
        protected int hight;
        
        //构造函数
        //空参构造函数
        public Element() {super();}        //可以不写super(),java会自己调用,也就是调用抽象类的父类
        
        public Element(int x, int y) {
            this.x=x;        this.y=y;
        }
        
        /*
         * 绘制元素
         */
        public abstract void draw();
        
        /*
         * 设置元素的渲染级别,数字越高,渲染级别越高
         */
        public int getOrder() {return 0;}
    }

    坦克的父类

    package domain;
    
    import org.itheima.game.utils.CollisionUtils;
    
    import Event.Blockable;
    import Event.Destoryable;
    import Event.Hitable;
    import Event.Moveable;
    /*
     * 所有坦克的父类
     * 坦克具有移动,阻挡,被攻击,被销毁的功能
     * 
     */
    public abstract class Tank extends Element implements Moveable, Blockable, Hitable,Destoryable{
        /*
         * 属性
         */
        //攻击力
        protected int power=1;
        //血量
        protected int blood=5;
        
        //坦克的移动方向
        protected Direction direction=Direction.UP;
        
        //每次移动的速度
        protected int speed=3;
        
        //记录最后一颗子弹的发射时间
        protected long lastTime;
        
        //记录坦克不能移动的方向
        protected Direction badDirection;
        
        //记录坦克碰撞的最小移动距离
        protected int badSpeed;
        
        
        /*
         * 构造函数
         */
        public Tank() {super();}
        public Tank(int x, int y) {super(x, y);}
        
        /*
         * 绘制坦克
         */
        public abstract void draw();
        
        /*
         * 发射子弹
         */
        public Bullet shot() {
            //思路:如歌最后一颗子弹  - 当前发射的时间  > 650ms 就发射子弹
            //获取当前时间
            long newTime=System.currentTimeMillis();
            if(newTime-lastTime<650) {
                return null;    //不发射子弹
            }else {
                lastTime=newTime;
                return new Bullet(this);        //谁调用了就是谁的子弹
            }
        }
        
        /*
         * 获取坦克的移动方向
         */
        public Direction getDirection() {return direction;}
        
        /*
         * 校验:移动物(坦克)是否与障碍物是否撞上
         */
        public boolean checkHit(Blockable block){
            Element e=(Element)block;
            int x1=e.x;
            int y1=e.y;
            int w1=e.width;
            int h1=e.hight;
            
            //预判坦克的坐标
            int x2=x;
            int y2=y;
            switch (direction) {
            case UP:
                y2-=speed;
                break;
            case DOWN:
                y2+=speed;
                break;
            case LEFT:
                x2-=speed;
                break;
            case RIGHT:
                x2+=speed;
                break;
            default:
                break;
            }
            boolean flag=CollisionUtils.isCollsionWithRect(x1, y1, w1, h1, x2, y2, width, hight);
            if(flag) {
                //说明预判可以撞上,不仅要记录不能移动的方向,还要记录最小间隙
                badDirection=direction;
                switch (direction) {
                case UP:
                    badSpeed=y-y1-h1;
                    break;
                case DOWN:
                    badSpeed = y1 - y - hight;
                    break;
                case LEFT:
                    badSpeed = x - x1 - w1;
                    break;
                case RIGHT:
                    badSpeed = x1 - w1 - width;
                    break;
                default:
                    break;
                }
            }else {
                badDirection=null;        //没有撞上的话,就没有坏的方向
            }
            return flag;
        }
        
        /*
         * 销毁的方法
         */
        public boolean isDestory() {return blood<=0;}
        
        /*
         * 被销毁物,在被销毁时的表现。
         */
        public Blast showDestory() {return new Blast(this);}
        
        
    }

    各种游戏元素

    package domain;
    
    import java.io.IOException;
    
    import org.itheima.game.utils.DrawUtils;
    import org.itheima.game.utils.SoundUtils;
    
    import Event.Blockable;
    import Event.Destoryable;
    import Event.Hitable;
    
    /*
     * 
     * 爆炸物类
     * 
     */
    public class Blast extends Element implements Destoryable{
        /*
         * 属性
         */
        //1.图片
        private String[]arr= {"res/img/blast_1.gif", "res/img/blast_2.gif", "res/img/blast_3.gif", "res/img/blast_4.gif",
                "res/img/blast_5.gif", "res/img/blast_6.gif", "res/img/blast_7.gif", "res/img/blast_8.gif"};
        //2.定义变量,记录要绘制的图片索引
        private int index;
        
        //3.定义变量,记录是否需要销毁该爆炸物
        //true:销毁, false :不销毁
        private boolean isDestory;
    
        /*
         * 构造方法
         * 爆炸物的坐标依赖墙的坐标
         */
        public Blast(Hitable hit) {
            this(hit, false);
            try {
                SoundUtils.play("res/snd/blast.wav");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        /*
         * flag :true表示挨打,绘制1~4的图片
         *         false 说明是销毁,绘制1~8的图片
         */
        public Blast(Hitable hit, boolean flag) {
            Element element=(Element)hit;
            //计算爆炸物的位置
            //获取墙的坐标和宽高
            int x1=element.x;
            int y1=element.y;
            int w1=element.width;
            int h1=element.hight;
            //获取爆炸物的宽度
            try {
                int size[]=DrawUtils.getSize("res/img/blast_1.gif");
                width=size[0];    hight=size[1];
                
                //计算爆炸物的坐标
                x=x1+(w1-width)/2;
                y=y1+(h1-hight)/2;
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            if(flag) {
                arr=new String[] {"res/img/blast_1.gif", "res/img/blast_2.gif", "res/img/blast_3.gif", "res/img/blast_4.gif"};
                try {
                    SoundUtils.play("res/snd/hit.wav");
                } catch (IOException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        @Override
        public void draw() {
            // TODO Auto-generated method stub
            //定义变量,记录要绘制的图片的路径
            String res=arr[index++];
            if(index>=arr.length) {
                index=0;
                //说明爆炸物已经绘制过一次了可以销毁
                isDestory=true;
            }
            try {
                DrawUtils.draw(res, x, y);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        /*
         * 获取爆炸物的状态
         */
        public boolean isDestoryable() {
            // TODO Auto-generated method stub
            return isDestory;
        }
        /*
         * 销毁时,绘制销毁的爆炸物
         */
        public Blast showDestory() {return null;}
        
        
    }
    View Code
    package domain;
    
    import java.io.IOException;
    
    import org.itheima.game.utils.CollisionUtils;
    import org.itheima.game.utils.DrawUtils;
    import org.itheima.game.utils.SoundUtils;
    
    import Event.Attackable;
    import Event.Destoryable;
    import Event.Hitable;
    import Grame.config;
    
    /*
     * 子弹类,具有攻击能力,被销毁的能力
     */
    public class Bullet extends Element implements Attackable, Destoryable {
    
        //记录子弹移动的方向
        private Direction direction;
        //记录子弹的速度
        private int speed=7;
        //定义变量,记录子弹所属的坦克
        private Tank tank;
        
        
        /*
         * 构造函数(non-Javadoc)
         * @see Event.Destoryable#isDestoryable()
         */
        //子弹的坐标依赖坦克
        public Bullet(Tank tank) {
            // TODO Auto-generated constructor stub
            super();
            //用变量tank记录,子弹所属的坦克
            this.tank=tank;
            
            //获取坦克的坐标,宽高,方向
            int tankX=tank.x;
            int tankY=tank.y;
            int tankWidth=tank.width;
            int tankHight=tank.hight;
            direction=tank.getDirection();
            
            //获取子弹的宽高
            try {
                int size[]=DrawUtils.getSize("res/img/bullet_u.gif");
                width=size[0];        hight=size[1];
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            //计算子弹的坐标
            switch (direction) {
            case UP:
                x = tankX + (tankWidth - width)/2;
                y = tankY - hight / 2;
                break;
            case DOWN:
                x = tankX + (tankWidth - width)/2;
                y = tankY + tankHight - hight /2;
                break;
            case LEFT:
                x=tankX-width;
                y=tankY+(tankHight-hight)/2;
                break;
            case RIGHT:
                x = tankX + tankWidth - width / 2;
                y = tankY + (tankHight - hight)/2;
                break;
            default:
                break;
            }
            
            try {
                SoundUtils.play("res/snd/fire.wav");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        /* 出边界
         * 销毁子弹  true:销毁,false:不销毁(non-Javadoc)
         * @see Event.Destoryable#isDestoryable()
         */
        @Override
        public boolean isDestoryable() {
            // TODO Auto-generated method stub
            if(x<0||x>config.WIDTH||y<0||y>config.HIGHT) return true;
            return false;
        }
    
        /*
         * 子弹销毁时的反映(non-Javadoc)
         * @see Event.Destoryable#showDestory()
         */
        @Override
        public Blast showDestory() {
            // TODO Auto-generated method stub
            return null;
        }
        /*校验是否与阻碍物碰上
         * (non-Javadoc)
         * @see Event.Attackable#checkAttack(Event.Hitable)
         */
        @Override
        public boolean checkAttack(Hitable hit) {
            // TODO Auto-generated method stub
            Element e=(Element)hit;
            int x1=e.x;
            int y1=e.y;
            int w1=e.width;
            int h1=e.hight;
            //第一个矩形:障碍物,第二个撞击物:子弹
            return CollisionUtils.isCollsionWithRect(x1, y1, w1, h1, x, y, width, hight);
        }
    
        
        /*
         * 绘制子弹(non-Javadoc)
         * @see domain.Element#draw()
         */
        @Override
        public void draw() {
            // TODO Auto-generated method stub
            String res="";
            //判断坦克方向
            switch (direction) {
            case UP:
                res = "res/img/bullet_u.gif";
                y-=speed;
                break;
            case DOWN:
                res = "res/img/bullet_d.gif";
                y += speed;
                break;
            case LEFT:
                res = "res/img/bullet_l.gif";
                x -= speed;
                break;
            case RIGHT:
                res = "res/img/bullet_r.gif";
                x += speed;
                break;
            default:
                break;
            }
            
            try {
                DrawUtils.draw(res, x, y);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        /*
         * 获取子弹所属坦克
         */
        public Tank getTank() {
            return tank;
        }
    }
    View Code
    package domain;
    /*
     * 枚举四个方向
     */
    public enum Direction {
        UP,DOWN,LEFT,RIGHT;
    }
    View Code
    
    
    package domain;
    
    import java.io.IOException;
    import java.util.Random;
    
    import org.itheima.game.utils.DrawUtils;
    
    import Grame.config;
    
    public class EnemyTank extends Tank{
    
        /*
         * 属性(non-Javadoc)
         * @see Event.Hitable#showAttack()
         */
        public EnemyTank(int x, int y) {
            super(x, y);
            try {
                int size[]=DrawUtils.getSize("res/img/enemy_u.gif");
                width=size[0];    hight=size[1];
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        public EnemyTank() {super();}
        
        
        @Override
        public Blast showAttack() {
            // TODO Auto-generated method stub
            //扣血
            blood-=new Mytank().power;
            return new Blast(this, true);
        }
    
        @Override
        public boolean isDestoryable() {
            // TODO Auto-generated method stub
            return blood<=0;
        }
    
        /*
         * 坦克的绘制(non-Javadoc)
         * @see domain.Tank#draw()
         */
        @Override
        public void draw() {
            // TODO Auto-generated method stub
            String res="";
            //判断坦克的方向
            switch (direction) {
            case UP:
                res = "res/img/enemy_u.gif";
                break;
            case DOWN:
                res = "res/img/enemy_d.gif";
                break;
            case LEFT:
                res = "res/img/enemy_l.gif";
                break;
            case RIGHT:
                res = "res/img/enemy_r.gif";
                break;
            default:
                break;
            }
            
            try {
                DrawUtils.draw(res, x, y);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        /*
         * 随机获取敌方坦克的方向
         */
        public Direction getRandDirection() {
            int num=new Random().nextInt(4);
            switch (num) {
            case 0:
                return Direction.UP;
            case 1:
                return Direction.DOWN;
            case 2:
                return Direction.LEFT;
            case 3:
                return Direction.RIGHT;
            default:
                break;
            }
            return Direction.UP;
        }
        
        /*
         * 移动
         */
        public void move() {
            //如果传过来的方向,与坦克不能移动的方向相同,则移动最小距离
            if(direction==badDirection) {
                switch (direction) {
                case UP:
                    y-=badSpeed;
                    break;
                case DOWN:
                    y+=badSpeed;
                    break;
                case LEFT:
                    x-=badSpeed;
                    break;
                case RIGHT:
                    x+=badSpeed;
                    break;
                default:
                    break;
                }
                //不能移动就随机换一下方向
                direction=getRandDirection();
                return ;
            }
            
            switch (direction) {
            case UP:
                y-=speed;
                break;
            case DOWN:
                y+=speed;
                break;
            case LEFT:
                x-=speed;
                break;
            case RIGHT:
                x+=speed;
                break;
            default:
                break;
            }
            
            //边界处理
            if(x<0) {
                x=0;
                direction=getRandDirection();
            }
            if(x>config.WIDTH-64) {
                x=config.WIDTH-64;
                direction=getRandDirection();
            }
            if(y<0) {
                y=0;
                direction=getRandDirection();
            }
            if(y>config.HIGHT-64) {
                y=config.HIGHT-64;
                direction=getRandDirection();
            }
        }
    }
    View Code
     
    package domain;
    
    import java.io.IOException;
    
    import org.itheima.game.utils.DrawUtils;
    /*
     * 草坪
     */
    public class Grass extends Element{
    
        public Grass(int x, int y) {
            // TODO Auto-generated constructor stub
            super(x, y);
            //获取宽高
            try {
                int size[]=DrawUtils.getSize("res/img/grass.gif");
                width=size[0];        hight=size[1];
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        @Override
        public void draw() {
            // TODO Auto-generated method stub
            try {
                DrawUtils.draw("res/img/grass.gif", x, y);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        /*
         * 修改草坪的渲染级别
         */
        public int getOrder() {return 1;}
    }
    View Code
    package domain;
    
    import java.io.IOException;
    
    import javax.swing.plaf.DimensionUIResource;
    
    import org.itheima.game.utils.DrawUtils;
    
    import Grame.config;
    
    public class Mytank extends Tank{
        public Mytank(int x, int y) {
            // TODO Auto-generated constructor stub
            super(x, y);
            //初始化速度
            speed=30;    power=2;    blood=10;
            
            //获取坦克的宽高
            try {
                int size[] = DrawUtils.getSize("res/img/tank_u.gif");
                width=size[0];
                hight=size[1];
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
        public Mytank() {
            // TODO Auto-generated constructor stub
            super();
            power=2;
        }
        
        
        /*
         * 挨打方法(non-Javadoc)
         * @see Event.Hitable#showAttack()
         */
        @Override
        public Blast showAttack() {
            // TODO Auto-generated method stub
            //扣血
            blood-=new EnemyTank().power;
            return new Blast(this, true);
        }
    
        @Override
        public boolean isDestoryable() {
            // TODO Auto-generated method stub
            return blood<=0;
        }
    
        @Override
        public void draw() {
            // TODO Auto-generated method stub
            String res="";
            switch (direction) {
            case UP:
                res = "res/img/tank_u.gif";
                break;
            case DOWN:
                res = "res/img/tank_d.gif";
                break;
            case LEFT:
                res = "res/img/tank_l.gif";
                break;
            case RIGHT:
                res = "res/img/tank_r.gif";
                break;
            default:
                break;
            }
            try {
                DrawUtils.draw(res, x, y);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        /*
         * 坦克的移动
         */
        public void move(Direction direction) {
            //如果传过来的方向和坦克不能动的方向一致,则移动最小
            if(badDirection==direction) {
                //移动最小间距
                switch (direction) {
                case UP:
                    y -= badSpeed;
                    break;
                case DOWN:
                    y += badSpeed;
                    break;
                case LEFT:
                    x -= badSpeed;
                    break;
                case RIGHT:
                    x += badSpeed;
                    break;
                default:
                    break;
                }
                return ;
            }
            
            //刷新方向,用户按下的方向传给坦克:坦克的方向
            if(this.direction!=direction)
            {
                this.direction=direction;
                return ;
            }
            
            switch (direction) {
            case UP:
                y -= speed;
                break;
            case DOWN:
                y += speed;
                break;
            case LEFT:
                x -= speed;
                break;
            case RIGHT:
                x += speed;
                break;
            default:
                break;
            }
            
            /*
             * 边界处理
             */
            if(x<0) {x=0;}
            if(x>config.WIDTH-64) {x=config.WIDTH-64;}
            if(y<0) {y=0;}
            if(y>config.HIGHT-64) {y=config.HIGHT-64;}
        }
        
    }
    View Code
    
    
    package domain;
    
    import java.io.IOException;
    
    import org.itheima.game.utils.DrawUtils;
    
    import Event.Blockable;
    import Event.Destoryable;
    import Event.Hitable;
    
    public class Steel extends Element implements Blockable, Hitable, Destoryable{
        /*
         * 属性:
         */
        //1.血量
        private int blood=5;
        
        public Steel(int x, int y) {
            super(x, y);
            
            //获取铁墙的宽高
            try {
                int size[]=DrawUtils.getSize("res/img/steel.gif");
                width=size[0];
                hight=size[1];
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
        
    
        
    
        @Override
        public void draw() {
            // TODO Auto-generated method stub
            try {
                DrawUtils.draw("res/img/steel.gif", x, y);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        /*
         * 挨打后的反映(non-Javadoc)
         * @see Event.Hitable#showAttack()
         */
        @Override
        public Blast showAttack() {
            // TODO Auto-generated method stub
            blood--;
            return new Blast(this,true);
        }
        
        /*
         * 销毁时响应的动作(non-Javadoc)
         * @see Event.Destoryable#showDestory()
         */
        @Override
        public Blast showDestory() {
            // TODO Auto-generated method stub
            return new Blast(this);
        }
        
        
        /*
         * 销毁铁墙(non-Javadoc)
         * @see Event.Destoryable#isDestoryable()
         */
        @Override
        public boolean isDestoryable() {
            // TODO Auto-generated method stub
            return blood<=0;
        }
    }
    package domain;
    
    import java.io.IOException;
    
    import org.itheima.game.utils.DrawUtils;
    
    import Event.Blockable;
    import Event.Destoryable;
    import Event.Hitable;
    
    public class Wall extends Element implements Hitable, Blockable, Destoryable{
    
        //血量
        private int blood=3;
        
        /*
         * 含参数的构造函数
         */
        public Wall(int x, int y) {
            // TODO Auto-generated constructor stub
            super(x, y);
            
            //获取宽度,长度
            try {
                int size[]=DrawUtils.getSize("res/img/wall.gif");
                width=size[0];
                hight=size[1];
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
        /*
         *绘制
         * @see domain.Element#draw()
         */
        @Override
        public void draw() {
            try {
                DrawUtils.draw("res/img/wall.gif", x, y);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    
        /*
         * 挨打
         * Blast爆炸类
         */
        public Blast showAttack() {
            blood--;        //挨打一次血量减少
            return new Blast(this, true);
        }
        
        /*
         * 销毁判断,血量小于等于0时,就销毁
         */
        public boolean isDestoryable() {return blood<=0;}
        
        /*
         * 销毁响应动作
         */
        public Blast showDestory() {return new Blast(this);}
    
    }
    package domain;
    
    import java.io.IOException;
    
    import org.itheima.game.utils.DrawUtils;
    
    import Event.Blockable;
    
    public class Water extends Element implements Blockable{
    
        public Water(int x, int y) {
            super(x, y);
            try {
                int size[]=DrawUtils.getSize("res/img/water.gif");
                width=size[0];    hight=size[1];
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
        }
        @Override
        public void draw() {
            try {
                DrawUtils.draw("res/img/water.gif", x, y);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    package Grame;
    
    public class APP {
            /*
             * 游戏的主入口,所有代码的主入口
             */
        public static void main(String[] args) {
            //绘制窗口
            MyWindows gr=new MyWindows(config.TITLE, config.WIDTH, config.HIGHT, config.PFS);
            
            //开始游戏
            gr.start();
            
        }
        
    }
    
    
    package Grame;
    
    public interface config {
        String TITLE="坦克大战";
        int WIDTH=64*15;
        int HIGHT=64*10;
        int PFS=50;
    }
    package Grame;
    
    import java.awt.HeadlessException;
    import java.awt.Window;
    import java.io.IOException;
    import java.nio.file.Watchable;
    import java.util.Comparator;
    import java.util.concurrent.CopyOnWriteArrayList;
    
    import org.itheima.game.utils.DrawUtils;
    import org.itheima.game.utils.SoundUtils;
    import org.lwjgl.input.Keyboard;
    import org.omg.PortableServer.ID_ASSIGNMENT_POLICY_ID;
    
    import Event.Attackable;
    import Event.Blockable;
    import Event.Destoryable;
    import Event.Hitable;
    import Event.Moveable;
    import domain.Blast;
    import domain.Bullet;
    import domain.Direction;
    import domain.Element;
    import domain.EnemyTank;
    import domain.Grass;
    import domain.Mytank;
    import domain.Steel;
    import domain.Tank;
    import domain.Wall;
    import domain.Water;
    
    
    /*
     * 游戏窗口类
     * 
     */
    public class MyWindows extends org.itheima.game.Window{
    
        //定义:集合,存储元素
                //CopyOnWeiteArrayList 可以解决并发修改异常的集合
                CopyOnWriteArrayList<Element>list=new CopyOnWriteArrayList<>();
                //创建坦克对象
                Mytank mt;
                //创建敌方坦克
                EnemyTank et1;
                EnemyTank et2;
        
        public MyWindows(String title, int width, int height, int fps) {super(title, width, height, fps);}
    
        /*
         * 绘制窗口时运行
         */
        @Override
        protected void onCreate() {
            //播放开始音乐
            try {
                SoundUtils.play("res/snd/start.wav");
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            
            //创建砖墙
            for(int i=0;i<config.WIDTH/64-1;++i) {
                Wall wall=new Wall(i*64, 64);
                addElement(wall);
            }
            //创建水墙
            for(int i=1;i<config.WIDTH/64;++i) {
                Water water=new Water(i*64, 64*3);
                addElement(water);
            }
            //绘制铁墙
            for(int i=0;i<config.WIDTH/64-1;++i) {
                Steel steel=new Steel(i*64, 64*5);
                addElement(steel);
            }
            //创造草坪
            for(int i=1;i<config.WIDTH/64;++i) {
                Grass grass=new Grass(i*64, 64*7);
                addElement(grass);
            }
            
            
            //创造己方坦克
            mt=new Mytank(config.WIDTH/2-32, config.HIGHT-64);
            addElement(mt);
            //创建敌方坦克
            et1=new EnemyTank(0, 0);
            et2=new EnemyTank(config.WIDTH-64, 0);
            addElement(et1);
            addElement(et2);
        }
    
        //鼠标事件
        @Override
        protected void onMouseEvent(int key, int x, int y) {
            // TODO Auto-generated method stub
            
        }
    
        //键盘事件
        @Override
        protected void onKeyEvent(int key) {
            // TODO Auto-generated method stub
            switch (key) {
            case Keyboard.KEY_UP:
                mt.move(Direction.UP);
                break;
            case Keyboard.KEY_DOWN:
                mt.move(Direction.DOWN);
                break;
            case Keyboard.KEY_LEFT:
                mt.move(Direction.LEFT);
                break;
            case Keyboard.KEY_RIGHT:
                mt.move(Direction.RIGHT);
                break;
            case Keyboard.KEY_SPACE:    //回车键
                Bullet shot=mt.shot();        //发射子弹
                //对子弹进行非空校验
                if(shot!=null) {
                    addElement(shot);
                }
                break;
            default:
                break;
            }
        }
    
        //事实刷新
        @Override
        protected void onDisplayUpdate() {
            // TODO Auto-generated method stub
            //如果己方坦克已经销毁,或者敌方坦克都销毁,则游戏结束
            if(mt.isDestory()||(et1.isDestory()&&et2.isDestory())) {
                list.clear();
                //绘制结束图片
                try {
                    DrawUtils.draw("res/img/gameover.gif", (config.WIDTH-96)/2, (config.HIGHT-96)/2);
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }
                //停止所有音乐
                SoundUtils.stop("res/snd/fire.wav");
                
                return;
            }
            
            //绘制元素
            for(Element e:list) {
                e.draw();
            }
            
            //调用敌方坦克的随机移动的功能
            for(Element e:list) {
                if(e instanceof EnemyTank) {
                    //如果是敌方坦克,就随机移动
                    ((EnemyTank)e).move();
                    
                    //如果是敌方坦克,就调用其发射子弹的能力
                    Bullet shot=((EnemyTank)e).shot();
                    if(shot!=null) {
                        addElement(shot);
                    }
                }
            }
            
            //销毁出界子弹
            for(Element e:list) {
                //如果是子弹
                if(e instanceof Bullet) {
                    //判断子弹是否出界
                    boolean flag=((Bullet)e).isDestoryable();
                    if(flag) {
                        list.remove(e);
                    }
                }
            }
            
            //销毁所有需要销毁的实物
            for(Element e:list) {
                //判断事物是否需要销毁
                if( e instanceof Destoryable) {
                boolean blast=((Destoryable)e).isDestoryable();
                if(blast) {
                    //说明事物需要销毁
                    //1.绘制销毁时的爆炸物
                    Blast blast2=((Destoryable)e).showDestory();
                    if(blast2!=null) {
                        addElement(blast2);
                    }
                    
                    //消除该事物
                    list.remove(e);
                    }
                }
            }
            
            /*
             * 校验:运动物体 与 障碍物 的碰撞
             */
            for(Element e1:list) {
                for(Element e2:list) {
                    if(e1!=e2&&e1 instanceof Moveable&&e2 instanceof Blockable) {
                        //说明 e1运动物  与 e2 障碍物 
                        boolean flag=((Moveable)e1).checkHit((Blockable)e2);
                        if(flag) {        //说明碰撞了
                            break;
                        }
                    }
                }
            }
            
            /*
             * 攻击者 与 被攻击者 是否碰撞
             */
            for(Element e1: list) {
                for(Element e2: list) {
                    if(e1 instanceof Attackable&&e2 instanceof Hitable) {
                        //说明  e1 攻击者 e2 被攻击者
                        boolean flag=((Attackable)e1).checkAttack((Hitable)e2);
                        if(flag) {
                            //校验:是己方坦克发过来的子弹,是则不能攻击,否则能产生攻击
                            if(((Bullet)e1).getTank().getClass()==e2.getClass()) {
                                continue;
                            }
                            
                            //校验:能不能攻击敌军
                            //子弹销毁
                            list.remove(e1);
                            //被攻击者受到攻击,绘制出爆炸物
                            Blast blast=((Hitable)e2).showAttack();
                            addElement(blast);
                        }
                    }
                }
            }
            
        }
    
        
        
        /*
         * 添加元素
         */
        public void addElement(Element e) {
            list.add(e);
            
            //对集合按照渲染级别进行排序
            list.sort(new Comparator<Element>() {
    
                @Override
                public int compare(Element o1, Element o2) {
                    // TODO Auto-generated method stub
                    return o1.getOrder()-o2.getOrder();
                }
            });
        }
    
        
    }
    
    

  • 相关阅读:
    javaHTTP请求工具类-使用HttpURLConnection实现
    windows 无法启动redis 服务(位于本地计算机上)错误1053 服务没有及时响应启动或控制请求
    Redis 教程
    谢娜离开《快本》103天,暴露了芒果一姐的假相:有一种天真,叫错把平台当本事
    Api 在线文档目录:java8 中文、java11中文
    Linux关闭防火墙命令red hat/CentOs7
    Win10使用RedisDesktopManager工具连接虚拟机(CentOS 7)Redis
    如何win10 上访问虚拟机(linux)上redis方法
    汽车车牌JS正则表达式验证(含新能源车牌)
    vue 直接输入路由地址进入_vue地址栏直接输入路由无效问题
  • 原文地址:https://www.cnblogs.com/ALINGMAOMAO/p/9862239.html
Copyright © 2020-2023  润新知