千家信息网

Java实现经典坦克大战游戏代码怎么写

发表于:2024-09-23 作者:千家信息网编辑
千家信息网最后更新 2024年09月23日,今天小编给大家分享一下Java实现经典坦克大战游戏代码怎么写的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面
千家信息网最后更新 2024年09月23日Java实现经典坦克大战游戏代码怎么写

今天小编给大家分享一下Java实现经典坦克大战游戏代码怎么写的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。

引言

90坦克大战,很经典的一款游戏,当年与小伙伴一人一个手柄,搬上小板凳坐在电视机前,身体时不时跟随手柄摇晃着,时而表情严肃、眉头紧锁,时而欢呼雀跃、喜笑颜开,全身心投入到游戏中,在消灭一只只坦克、守住关卡、坦克升级、晋级通关的时候,更是手舞足蹈、击掌庆祝,如今想想也是记忆犹新、回味无穷!于是乎就我就自己用java写了一个,找一下当年的感觉,顺便虐一下电脑,嘻嘻嘻嘻嘻(ming式笑声)。

实现

绘图时将这个鹰的图标用 g.drawImage 的方式绘制在界面中央最下方,然后用drawImage的方式用土墙把它围起来,受到敌人进攻的时候,可以抵挡一波,但是土墙很脆弱。

创建Wall类,属性x、y是坐标,属性width、height为长宽,属性type为类型,土墙值为0 、钢墙值为1、家(那只老鸟)为2。这3个共用这个类,创建的都是Wall的实例对象,传入不同type值,创建不同的墙。

程序员解析:就是玩!要将下图中 5这种小墙拼成 6这种厚墙需要4小块(放成2行2列),小块的长宽都是30像素。

//第1列int x1=60;int x2=90;int width=30;int height=30;int oy=60;int y=0;int count=6;for (int i = 0; i < count; i++) {    y=oy+i*30;    wall = new Wall(wallImage,x1,y,width,height,0);    walls.add(wall);    wall = new Wall(wallImage,x2,y,width,height,0);    walls.add(wall);}

上述代码中,2行6列,x1是第1列x坐标,x2是第2列x坐标,oy是y方向初始坐标,然后依次按30递增,这样就定义好Wall对象了,然后将wall实例对象放到集合中,方便绘制。

创建抽象Tank类,定义几个主要的方法(fire开火、move移动等),PTank 是玩家坦克类继承了Tank,实现了相关的方法。

添加键盘事件,上下左右为方向移动事件(上对应数字1,右对应数字2,下对应3,左对应4),F键和空格设定为开火事件(开火也要根据这些数字来确定炮弹的方向)。

//按下键盘@Overridevoid keyPressed(KeyEvent e) {        int key = e.getKeyCode();        switch (key) {                case KeyEvent.VK_F:                case KeyEvent.VK_SPACE:                        fire();                        break;                                case KeyEvent.VK_UP:                case KeyEvent.VK_W:                        setDir(1);                        move();                        break;                                        case KeyEvent.VK_RIGHT:                case KeyEvent.VK_D:                        setDir(2);                        move();                        break;                                case KeyEvent.VK_DOWN:                case KeyEvent.VK_S:                        setDir(3);                        move();                        break;                                case KeyEvent.VK_LEFT:                case KeyEvent.VK_A:                        setDir(4);                        move();                        break;        }}

move方法开始做的是键盘按一下移动10像素,感觉一卡卡的,并且很容易有过道会卡住,为了更丝滑,改造为监听到一次移动事件就移动30像素,用线程分3次执行每次10像素,在坦克移动过程中键盘的移动指令暂时失效,坦克移动完毕后移动指令恢复。

void doMove(){//总共30,分3次走每次 10,用线程        if(!alive) return ;        if(isMove) return ;                isMove=true;        new Thread(new Runnable() {                @Override                public void run() {                        while (isMove){                                count++;                                go();                                if(count==3){                                        count=0;                                        isMove=false;                                }                                try {                                        Thread.sleep(50);                                } catch (InterruptedException e) {                                        e.printStackTrace();                                }                        }                }        }).start();}//执行位移void go(){        //设定位移        switch (dir) {                case 1:                        y-=speed;                        break;                                case 2:                        x+=speed;                        break;                                        case 3:                        y+=speed;                        break;                                case 4:                        x-=speed;                        break;        }}

判断边界很好处理,只要坦克的坐标x<0或者y<0或者x+width>游戏区域的宽 或者 y+height>游戏区域的高就认定为出界,不允许移动即可。

//判断左边界、上边界if(tank.getX()<0||tank.getY()<0){        return false;//不能移动}//判断右边界、下边界if(tank.getX()+tank.getWidth()>gameWidth||tank.getY()+tank.getHeight()>gameHeight){        return false;//不能移动}

坦克与墙体的碰撞检查:

1.判断每一块小墙体的4个点是否在tank的范围内(因为墙体比坦克小),只要有一个点满足条件则判定为不能移动,否则可以移动。

2.如果不能移动则需要恢复坦克这次所移动的位置,以保持坦克没有移动(因为设定了预移动,方便计算位置,下方的图都是经过预移动的)

(1).一个点在区域内

(2)两个点在区域内

(3)4个点都在区域内

以下代码是取到墙体4个角的坐标,采用 || 或的方式,有一个满足条件则返回不可以移动。

//判断墙体与坦克是否碰撞@Overrideboolean isPoint(Wall wall) {        //因为墙比坦克小,所以只需要判断墙的4个点是否在 坦克范围内,如果有则表示碰撞了        //左上角        int x1 = wall.getX();        int y1 = wall.getY();        //右上角        int x2 = wall.getX()+wall.getWidth();        int y2 = wall.getY();        //右下角        int x3 = wall.getX()+wall.getWidth();        int y3 = wall.getY()+wall.getHeight();        //左下角        int x4 = wall.getX();        int y4 = wall.getY()+wall.getHeight();        //只要有一个点在范围内,则判断为碰撞        if(comparePoint(x1,y1)|| comparePoint(x2,y2)||comparePoint(x3,y3)||comparePoint(x4,y4) ){                return true;        }        return false;} boolean comparePoint(int x,int y){        //大于左上角,小于右下角的坐标则肯定在范围内        if(x>this.x && y >this.y                && x

如何开炮:

开炮后执行一个线程,并进行休眠,休眠一定时间后才允许再次开炮,炮弹装填是有时间的,这里用线程休眠来模拟。

开炮时创建一个炮弹对象,是类 Missile的实例, 此类除了坐标,长宽等一般的属性,有属性type来区分是右方炮弹(my)还是敌方炮弹(enemy),敌我双方 的炮弹可以互相击毁坦克,但敌方与敌方之间、右方与右方之间均无法相互摧毁。

炮弹在创建后会启动移动线程,根据发射的方向移动,当碰撞到物体或者出界后,炮弹对象销毁,然后从炮弹数组中移出。

判断击中玩家坦克(玩家拥有4点生命值,中一发炮弹减一,归零则游戏失败)

//判断击中玩家坦克private boolean hitTank() {        Tank pTank= null;        List pTanks = gamePanel.pTanks;        for (int i = 0; i < pTanks.size(); i++) {                pTank = (Tank)pTanks.get(i);                if(this.isPointTank(pTank)){                        //删除当前子弹                        removeMissile();                        //移除当前已方坦克                        int hp = pTank.getHp();                        hp--;                        pTank.setHp(hp);                        if(pTank.getHp()==0){                                pTank.setAlive(false);                                pTanks.remove(pTank);                                pTank=null;                                if(pTanks.size()==0){                                        gamePanel.gameOver();                                        break;                                }                        }                        return true;                }        }        return false;}

判断击中敌方坦克(敌方坦克中一发炮弹就报废)

//判断击中敌人坦克private boolean hitEnemyTank() {        Tank eTank=null;        List eTanks = gamePanel.eTanks;        for (int i = 0; i < eTanks.size(); i++) {                eTank = (Tank)eTanks.get(i);                if(this.isPointTank(eTank)){                        //删除当前子弹                        removeMissile();                        //移除当前敌方坦克                        int hp = eTank.getHp();                        hp--;                        eTank.setHp(hp);                        if(eTank.getHp()==0){                                eTank.setAlive(false);                                eTanks.remove(eTank);                                eTank=null;                                gamePanel.killEnemy++;                                if(gamePanel.killEnemy>=gamePanel.killEnemyCount){                                        //胜利                                        gamePanel.gameWin();                                        break;                                }                        }                        return true;                }        }        return false;}

判断击中墙体(土墙直接消失、钢墙则仅仅炮弹消失、击中家的话GG思密达)

private boolean hitWall(){        //判断是否击中墙        Wall wall=null;        List walls = gamePanel.walls;        for (int i = 0; i < walls.size(); i++) {                wall = (Wall)walls.get(i);                if(this.isPoint(wall)){                        //删除当前子弹                        removeMissile();                        if(wall.getType()==0){//普通墙被销毁                                //删除当前墙                                removeWall(wall);                        }                        return true;                }        }        return false;}

敌坦克类 ETank与 PTank很相似,区别是敌方坦克是自行移动,自动开炮,而我方是自己控制。

敌方坦克移动规则(我定的 ):

1..用线程控制移动,每次移动判断是否能移动,如果能移动则一直朝着一个方向动。

2.如果不能移动,则随机获取除当前方向外的3个方向之一。

3.随机的时候,取到方向下的几率较高(程序员常用的作弊方式),因为坦克要进攻,家在下方,不然没得玩,其中3就是向下。

private int[] dirs= new int[]{1,2,3,3,3,4};//向下几率高
@Overridevoid move() {        if(!alive) return ;        //设定位移和图片        switch (dir) {                case 1:                        y-=speed;                        setImage((BufferedImage)tankImageMap.get(key+"U"));                        //判断是否能移动                        if(!panel.canMove(this)){//不能移动                                y+=speed;                                dir = dirs[getRandom(dir)];                        }                        break;                                case 2:                        x+=speed;                        setImage((BufferedImage)tankImageMap.get(key+"R"));                        //判断是否能移动                        if(!panel.canMove(this)){//不能移动                                x-=speed;                                dir = dirs[getRandom(dir)];                        }                        break;                                        case 3:                        y+=speed;                        setImage((BufferedImage)tankImageMap.get(key+"D"));                        //判断是否能移动                        if(!panel.canMove(this)){//不能移动                                y-=speed;                                dir = dirs[getRandom(dir)];                        }                        break;                                case 4:                        x-=speed;                        setImage((BufferedImage)tankImageMap.get(key+"L"));                        //判断是否能移动                        if(!panel.canMove(this)){//不能移动                                x+=speed;                                dir = dirs[getRandom(dir)];                        }                        break;        }}

开炮采用线程定时执行

@Overridevoid fire() {        BufferedImage image = (BufferedImage)imageMap.get("tankmissile");        int x =0;        int y =0;        int w=6;        int h=6;        if(dir==1){                x = this.x+width/2-w/2;                y = this.y;        }else if(dir==2){                x = this.x+width;                y = this.y+height/2-h/2;        }else if(dir==3){                x = this.x+width/2-w/2;                y = this.y+height;        }else if(dir==4){                x = this.x;                y = this.y+height/2-h/2;        }        Missile missile = new Missile(panel,image, x, y, w, h, dir, 6, "enemy");        panel.missiles.add(missile);                missile.doMove();}

定时创建敌方坦克

//创建定时加入敌方坦克的线程new Thread(new Runnable() {        @Override        public void run() {                while (startFlag) {                        try {                                createEnemyTank();                                Thread.sleep(5000);                        } catch (InterruptedException e) {                                e.printStackTrace();                        }                }        }}).start();        private void createEnemyTank(){int index = new Random().nextInt(3)+1;//随机敌方坦克int x=0;int y=0;int w=60;int h=60;int fireTime=2000;//开火间隔Tank et  = new ETank(this,imageMap,tankImageMap,x,y,w,h,fireTime,"enemy"+index);eTanks.add(et);}

重新开始游戏,重新设置相关参数即可

//创建定时加入敌方坦克的线程new Thread(new Runnable() {        @Override        public void run() {                while (startFlag) {                        try {                                createEnemyTank();                                Thread.sleep(5000);                        } catch (InterruptedException e) {                                e.printStackTrace();                        }                }        }}).start();        private void createEnemyTank(){int index = new Random().nextInt(3)+1;//随机敌方坦克int x=0;int y=0;int w=60;int h=60;int fireTime=2000;//开火间隔Tank et  = new ETank(this,imageMap,tankImageMap,x,y,w,h,fireTime,"enemy"+index);eTanks.add(et);}

以上就是"Java实现经典坦克大战游戏代码怎么写"这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注行业资讯频道。

移动 坦克 敌方 炮弹 线程 坐标 方向 墙体 区域 对象 属性 碰撞 代码 事件 像素 方式 玩家 知识 篇文章 范围 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 拉萨短视频软件开发服务商 那种软件开发模式具有抗风险 怎么设置网络安全密钥是 网络安全系统集成商排行 mysql数据库 路径 世界最牛数据库 奉贤区常规软件开发报价供应商 海外美国服务器租用 税务网络安全保障重要性 河北软件开发定制招商加盟 安徽综合软件开发技术规范 信息网络安全设计最佳实践 vip线路服务器验证怎么破解 百度服务器原理 南京网络安全准入控制系统价格 硅谷网络安全模式 服务器和手机时间同步 浙江人工智能软件开发公司 维护网络安全宣传图片 智能化软件开发价格实惠 未来数据库设计操作题 tcp怎么创建服务器 杨浦区创新数据库服务价格查询 济宁大学生诚信积分管理软件开发 高斯数据库版本查询 孝感专业的软件开发团队 数据库怎么查询字段的类型 武汉工业能源管理系统软件开发 房山良乡软件开发培训 web镜像服务器
0