Java之详解坦克大战游戏(六)

现在代码已经越写越多了,这里我们又新建一个包com.TankGame4,复制原来的两个java文件,首先我们来实现一个功能:防止敌人的坦克重叠运动。我们把判断是否碰撞的函数写到EnemyTank类中
Members.java

//敌人的坦克,把敌人做成线程类
class EnemyTank extends Tank implements Runnable
{
    //定义一个向量,可以访问到MyPanel上所有敌人的坦克
    Vector ets = new Vector();
    //.......
    //得到MyPanel的敌人坦克向量
    public void setEts(Vector vv)
    {
        this.ets=vv;
    }
    //.....
}

接下来到MyPanel类的构造函数

public MyPanel()
    {//...
        //初始化敌人的坦克
        for(int i=0;i...
        }

接下来大概计算我们的坦克与敌人坦克相遇的各种情形时的距离
Java之详解坦克大战游戏(六)_第1张图片
根据这四种情况写代码(代码虽然多,但是思路差不多)
在EnemyTank类写isTouchOtherEnemy()函数

//判断是否碰到了敌人的坦克
    public boolean isTouchOtherEnemy()
    {
        boolean b=false;

        switch(this.direct)
        {
            case 0:
                //我的坦克向上
                //取出所有的敌人坦克
                for(int i=0;i//取出第一个坦克
                    EnemyTank et = ets.get(i);
                    //如果不是自己
                    if(et!=this)
                    {
                        //如果敌人的方向是向下或者向上
                        if(et.direct==0 || et.direct==2)
                        {
                            //左点
                            if(this.x>=et.x && this.x<=et.x+20 && this.y>=et.y && this.y<=et.y+30)
                            {
                                return true;
                            }
                            if(this.x+20>=et.x && this.x+20<=et.x+20 && this.y>=et.y && this.y<=et.y+30)
                            {
                                return true;
                            }
                        }
                        if(et.direct==3 || et.direct==1)
                        {
                            if(this.x>=et.x && this.x<=et.x+30 && this.y>=et.y && this.y<=et.y+20)
                            {
                                return true;
                            }
                            if(this.x+20>=et.x && this.x+20<=et.x+30 && this.y>=et.y && this.y<=et.y+20)
                            {
                                return true;
                            }
                        }
                    }
                }
                break;
            case 1:
                //坦克向右
                //取出所有的敌人坦克
                for(int i=0;i//取出第一个坦克
                    EnemyTank et = ets.get(i);
                    //如果不是自己
                    if(et!=this)
                    {
                        //如果敌人的方向是向下或者向上
                        if(et.direct==0 || et.direct==2)
                        {
                            //上点
                            if(this.x+30>=et.x && this.x+30<=et.x+20 && this.y>=et.y && this.y<=et.y+30)
                            {
                                return true;
                            }
                            //下点
                            if(this.x+30>=et.x && this.x+30<=et.x+20 && this.y+20>=et.y && this.y+20<=et.y+30)
                            {
                                return true;
                            }
                        }
                        if(et.direct==3 || et.direct==1)
                        {
                            if(this.x+30>=et.x && this.x+30<=et.x+30 && this.y>=et.y && this.y<=et.y+20)
                            {
                                return true;
                            }
                            if(this.x+30>=et.x && this.x+30<=et.x+30 && this.y+20>=et.y && this.y+20<=et.y+20)
                            {
                                return true;
                            }
                        }
                    }
                }
                break;

            case 2:
                //坦克向下 
                //取出所有的敌人坦克
                for(int i=0;i//取出第一个坦克
                    EnemyTank et = ets.get(i);
                    //如果不是自己
                    if(et!=this)
                    {
                        //如果敌人的方向是向下或者向上
                        if(et.direct==0 || et.direct==2)
                        {
                            //我的左点
                            if(this.x>=et.x && this.x<=et.x+20 && this.y+30>=et.y && this.y+30<=et.y+30)
                            {
                                return true;
                            }
                            //我的右点
                            if(this.x+20>=et.x && this.x+20<=et.x+20 && this.y+30>=et.y && this.y+30<=et.y+30)
                            {
                                return true;
                            }
                        }
                        if(et.direct==3 || et.direct==1)
                        {
                            if(this.x>=et.x && this.x<=et.x+30 && this.y+30>=et.y && this.y+30<=et.y+20)
                            {
                                return true;
                            }
                            if(this.x+20>=et.x && this.x+20<=et.x+30 && this.y+30>=et.y && this.y+30<=et.y+20)
                            {
                                return true;
                            }
                        }
                    }
                }
                break;
            case 3:
                //向左
                //取出所有的敌人坦克
                for(int i=0;i//取出第一个坦克
                    EnemyTank et = ets.get(i);
                    //如果不是自己
                    if(et!=this)
                    {
                        //如果敌人的方向是向下或者向上
                        if(et.direct==0 || et.direct==2)
                        {
                            if(this.x>=et.x && this.x<=et.x+20 && this.y>=et.y && this.y<=et.y+30)
                            {
                                return true;
                            }
                            if(this.x>=et.x && this.x<=et.x+20 && this.y+20>=et.y && this.y+20<=et.y+30)
                            {
                                return true;
                            }
                        }
                        if(et.direct==3 || et.direct==1)
                        {
                            if(this.x>=et.x && this.x<=et.x+30 && this.y+20>=et.y && this.y+20<=et.y+20)
                            {
                                return true;
                            }
                            if(this.x>=et.x && this.x<=et.x+30 && this.y+20>=et.y && this.y+20<=et.y+20)
                            {
                                return true;
                            }
                        }
                    }
                }
                break;
        }
        return b;
    }

好像有点乱哦,但仔细分析还是根据前几篇所说的矩形左上角或右上角的来确定是否碰撞
接下来我们需要去增加一个条件,我们之前在run函数写过

public void run() {
        while(true)
        {
            switch(this.direct)
            {
            case 0:
                //说明坦克正在向上移动
                for(int i=0;i<30;i++)
                {   //保证坦克不出边界
                    if(y>0)
                    {
                        y-=speed;
                    }
                    //......

if语句我们需要再增加一个条件,敌人坦克当快相撞时会停止继续运动,即

if(y>0 &&!this.isTouchOtherEnemy())

将其他if语句全部加上这个条件,这样坦克不重叠的工作就做好了
下一步继续完善游戏,我们给游戏设置分关:
1.做一个开始的Panel 2.闪烁效果
在TankGame4.java文件写MyStartPanel类
先在TankGame4类定义:

//定义一个开始的面板
MyStartPanel msp=null;

再到它的构造函数初始化

        msp=new MyStartPanel();
        this.setSize(600, 500);  //设大一点,下面有用途
        this.add(msp);//作为刚运行时界面
//就是一个提示作用
class MyStartPanel extends JPanel implements Runnable
{
    int times=0;

    //定义开始
    public void paint(Graphics g)
    {
        super.paint(g);
        g.fillRect(0, 0, 400, 300);

        if(times%2==0)
        {
            g.setColor(Color.yellow);
            //开关信息的字体
            Font myFont=new Font("华文新魏",Font.BOLD,30);
            g.setFont(myFont);
            g.drawString("stage: 1", 150, 150);
        }
    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(true)
        {
            //休眠
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                times++;
                //重画
                this.repaint();
        }
    }
}

上面的闪烁文字效果是靠实现接口的方式的,所以我们还需要在MyPanel构造函数启动线程

        Thread t =new Thread(msp); 
        t.start();                

这里还需要把原来TankGame4构造函数的代码注释掉(最好先复制)

        /*  mp=new MyPanel();
            Thread t = new Thread(mp);
            t.start();
            this.addKeyListener(mp);//注册监听
            this.add(mp);
            this.setVisible(true);  */

运行程序,效果如图
Java之详解坦克大战游戏(六)_第2张图片
接下来我们要做的是给游戏添加选项菜单,如开始游戏,退出游戏等等…
在TankGame4类定义

    //作出我需要的菜单
    JMenuBar jmb=null;
    //开始游戏
    JMenu jm1=null;
    JMenuItem jmi1=null;

再到它的构造函数里

        //创建菜单和菜单选项
        jmb=new JMenuBar();
        jm1=new JMenu("游戏(G)");
        //设置快捷方式
        jm1.setMnemonic('G');
        jmi1=new JMenuItem("开始新游戏(N)");
        jm1.add(jmi1);
        jmb.add(jm1);
        this.setJMenuBar(jmb);

效果如图:Java之详解坦克大战游戏(六)_第3张图片
既然是我们可以选择的,我们应该给它一个监听的机制
第一步依然实现接口和实现它的抽象方法,这里还要写下刚才上面说的复制的代码

public class TankGame4 extends JFrame implements ActionListener
{
    //........
    public void actionPerformed(ActionEvent e) {
        // TODO Auto-generated method stub
        //判断对用户不同的点击作出不同的处理
        if(e.getActionCommand().equals("newgame"))
        {   //创建战场面板
            mp=new MyPanel();
            Thread t = new Thread(mp);
            t.start();
            //先删除旧的开始面板
            this.remove(msp);
            this.addKeyListener(mp);//注册监听
            this.add(mp);
            //显示,刷新
            this.setVisible(true);
        }
    }
}

这样还不能监听哦。还需到TankGame4函数添加如下代码

        //对jmi1响应
        jmi1.addActionListener(this);
        jmi1.setActionCommand("newgame");

这些搞定,下面我们要完成这样一个页面
Java之详解坦克大战游戏(六)_第4张图片
我们需要在Members.java定义一个类

//记录类,同时也可以保存玩家的设置
class Recorder
{
    //记录每关有多少敌人
    private static int enNum=20;
    //设置我有多少可以用的人
    private static int myLife=3;
    //记录总共消灭了多少敌人
    private static int allEnNum=0;
    public static int getAllEnNum() {
        return allEnNum;
    }
    public static void setAllEnNum(int allEnNum) {
        Recorder.allEnNum = allEnNum;
    }
    public static int getEnNum() {
        return enNum;
    }
    public static void setEnNum(int enNum) {
        Recorder.enNum = enNum;
    }
    public static int getMyLife() {
        return myLife;
    }
    public static void setMyLife(int myLife) {
        Recorder.myLife = myLife;
    }

    //减掉敌人数
    public static void reduceEnNum()
    {
        enNum--;
    }
    //消灭敌人
    public static void addEnNumRec()
    {
        allEnNum++;
    }
}

基本内容写好了,下一步就是画出来,在MyPanel类写一个函数

//画出提示信息
    public void showInfo(Graphics g)
    {
        //画出提示坦克信息坦克(该坦克不参与战斗)
        this.drawTank(80, 330, g, 0, 0);
        g.setColor(Color.BLACK);
        g.drawString(Recorder.getEnNum()+"", 110, 350);
        this.drawTank(130, 330, g, 0, 1);
        g.setColor(Color.BLACK);
        g.drawString(Recorder.getMyLife()+"", 165, 350);

        //画出玩家的总成绩
        g.setColor(Color.black);
        Font f= new Font("宋体", Font.BOLD, 20);
        g.setFont(f);
        g.drawString("你的总成绩", 420, 30);

        this.drawTank(420, 60, g, 0, 0);

        g.setColor(Color.black);
        g.drawString(Recorder.getAllEnNum()+"", 460, 80);
    }

然后再适当位置添加就行了…

由于一些因素,游戏讲解写到这里,可能由于经验不足时间因素,第一次写这种类型的,表达不是很好,代码也仍不是很完善,不过,下次写项目文章的时候,我一定会保证认真对待文章的表达和完整性,我想每个人都有自己薄弱的地方,所以仍需努力,Java的路仍要继续往前走,努力!!!
在此推荐一位老师:韩顺平,本次写坦克大战游戏的来源,百度一下,你就知道..
需要完整源码的可以到我的资源那里零积分下载…

你可能感兴趣的:(Java项目实战)