用户界面编程-基于坦克大战情景

作者: MoBaiGeneral 分类: 用户编程 发布时间: 2021-08-31 21:37 访问量:13,700
FavoriteLoading收藏

本文基于java环境编写一款简易的坦克大战应用程序,程序详情可参见java源码

程序的重要构成元素包括以下几个方面:

坦克对象

通过定义坦克类对象可以简单清晰地包装其所附带的各个属性。该类所定义的属性主要由三个部分:驾驶员属性主要包括坦克驾驶员生命值、复活等待时长与姓名;坦克属性主要包括坦克的外观、前行速度、可前进方向;坦克发射炮弹属性主要包括其外观、速度以及伤害值。值得注意的是,对外观的定义可通过Panel.class.getResource函数实例化ImageIcon,以加载图片的方式实现。此外,每一个坦克对象还配置一个进度条属性,用以可视化其坦克驾驶员的生命值。坦克对象的定义如下所示:

class Tank
{
    public int width=50,height=50;
    public int moveSpeed = 15,spotHurt=5,fireSpeed=30;//移动速度
    public int x,y,attackRange=50;
    public int lifeFull=100,lifeValue=100;
    public Timer mt;
    public int state=1;
    public boolean pressed=false;
    public JProgressBar lifeBar;
    public ImageIcon bodyIcon[],ballIcon[];;
    public JLabel body;
    public int resurrection=6000;
    public String name="";
    public Tank(Color foreground,String name,int x,int y,String imgString[])
    {
        this.x=x;
        this.y=y;
        this.name=name;
        mt=new Timer();
        lifeBar=new JProgressBar();
        lifeBar.setStringPainted(true);//设置进度条显示提示信息
        lifeBar.setForeground(foreground);
        lifeBar.setFont(new Font("SansSerif",Font.BOLD,20));
        lifeBar.setValue(lifeValue);
        String sbase="image/";
        bodyIcon=new ImageIcon[4];
        for(int i=0;i<4;i++)
        {
            URL url=Panel.class.getResource(sbase+imgString[i]);  
            bodyIcon[i]=new ImageIcon(url);
            bodyIcon[i].setImage(bodyIcon[i].getImage().getScaledInstance(width, height,Image.SCALE_DEFAULT));
        }
        body=new JLabel();
        body.setIcon(bodyIcon[0]);
        body.setBounds(x, y, width, height);
        ballIcon=new ImageIcon[4];
        String ballname[]= {"ballW.png","ballN.png","ballE.png","ballS.png"};
        for(int i=0;i<ballIcon.length;i++)
        {
            URL url=Panel.class.getResource(sbase+ballname[i]);  
            ballIcon[i]=new ImageIcon(url);
        }
    }
}

   

键盘监听

通过复写keyReleased与keyPressed函数获得用户输入操作,规定键盘上up、down等四个箭头为一个坦克对象的控制器,W、S、A、D为另一个坦克对象的控制器。四个控制器分别对应了坦克的四个行驶方向,对控制器的应答主要包括坦克方向状态的更新、驾驶员生命值的更新、炮弹的发射方向更新以及战场边界的限制。

炮弹对象

虽然炮弹属于坦克的一项属性,并未将炮弹封装在坦克对象之中,仅仅是在坦克对象内封装了炮弹外观等简单属性,这是因为每一个炮弹都可以作为一个独立的个体,在程序中具有较短的生命周期,更新间隔快,始终处在不停地创建和回收的动态过程之中。炮弹对象同样是通过加载图像方式可视化,但是由于炮弹一经坦克发出,其状态便要时刻更新,根据炮弹的发射方向的不同,定义两个炮弹类,其一是南北方向的炮弹,其二是东西方向的炮弹。为了有效实现炮弹的动态更新,可通过schedule函数为Timer设置TimerTask,任务中令炮弹于一定周期后更新状态,而状态更新的终点便是炮弹处于战场边界的时刻。届时则需回收定时器与炮弹对象。值得注意的是,在炮弹的行进过程中,需要判断子弹是否击中敌机,在击中情况下为敌机的生命值做更新操作,当敌军的生命值为零时,程序中会给敌军复活的机会,复活完成后,双方的生命值均回到最初。以东西方向的炮弹对象为例,其定义如下:

class BulletInX
    {
        public BulletInX(int startx,int y,int orienta,Tank tank,Tank target,JPanel obj)
        {
            final int speed=tank.fireSpeed*orienta;
            JLabel label=new JLabel();
            label.setBounds(startx, y, 30, 15);
            if(orienta>0)
                label.setIcon(tank.ballIcon[2]);
            else 
                label.setIcon(tank.ballIcon[0]);
            obj.add(label);
            Timer timer=new Timer();
            timer.schedule(new TimerTask() {
                int x=startx;
                @Override
                public void run() {
                    // TODO Auto-generated method stub
                    x+=speed;
                    label.setLocation(x, y);
                    if(x<borderW||x>borderE)
                    {
                        timer.cancel();
                        obj.remove(label);
                    }
                    if(Math.abs(x-target.x)<target.attackRange&&Math.abs(y-target.y)<target.attackRange)
                    {
                        target.lifeValue-=tank.spotHurt;
                        target.lifeBar.setValue(target.lifeValue);
                        if(target.lifeValue<0)
                        {
                            //Dialog tip = new 
                            showInfo.setText(tank.name+" WIN");
                            Timer pausetimer=new Timer();
                            pausetimer.schedule(new TimerTask() {
                                @Override
                                public void run() {
                                    // TODO Auto-generated method stub
                                    showInfo.setText("PK");
                                    target.lifeValue=target.lifeFull;
                                    target.lifeBar.setValue(target.lifeFull);
                                    tank.lifeValue=tank.lifeFull;
                                    tank.lifeBar.setValue(tank.lifeFull);
                                }   
                            },target.resurrection);
                        }
                    }
                }
            }, 0, 100);
        }
    }

效果再现

Attachments

     

如果觉得小墨的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!

一条评论

发表评论