基于Java实现的坦克大战小游戏

选题目的和意义:

    随着人们精神文化生活的日益丰富,为了让我们在闲暇的时间多方面发展个人的兴趣爱好,为了更好地开发个人智力,游戏成为人们生活中不可缺少的一部分。游戏产业促动高科技技术不断升级,作为经济增长的一大支撑点,已经成为经济腾飞的“第四产业”。作为休闲游戏的起源应该追溯到早期的俄罗斯方块和坦克大战,坦克大战是童年经常玩的游戏,也是一款经典游戏。《坦克大战》游戏几乎家喻户晓,对我们80后90后而言,是童年最珍贵的回忆。此款游戏是一款以红白机为平台操作射击游戏,玩家可以控制自己的坦克,以歼灭对方的坦克,其操作方式及其简单,是一款男女老少皆宜的游戏。为了满足人们的个性化需求,使玩家在游戏的过程中,更能体验游戏本身的乐趣,也为了满足更好的用户体验。

1 环境要求

操作系统:Windows 7(SP1)以上

JAVA虚拟机:JDK1.8以上

开发环境:Eclipse(4.5以上)

2 角色设定

用户在系统中扮演的角色,以及可以执行的职责。

玩 家 操纵玩家坦克,与敌方坦克作战,同时保护本基地。敌方坦克随机移动,发射子弹。

3 设定玩家(玩家一,玩家二,即一个人玩还是两个人玩),我方坦克的方向和子弹由用户控制,所有墙块都可以打碎,但是铁墙是打不碎的,草地不能阻止坦克和子弹的前进,河流能阻止坦克前进,但是不能阻止子弹前进。我方基地被毁则游戏结束,自己的坦克被毁游戏也结束,唯一赢得方式是消灭所有的敌方坦克,则可以进入下一关。一关比一关的难度大,通过地图来实现。

Wall:

Visible:

git提交截图

关键代码

Map类

1.GameMap

public class GameMap {

    public static final int MAP_X = Tank.RADIUS*3;
    public static final int MAP_Y = Tank.RADIUS*3 + GameFrame.titleBarH;
    public static final int MAP_WIDTH = Constant.FRAME_WIDTH-Tank.RADIUS*6;
    public static final int MAP_HEIGHT = Constant.FRAME_HEIGHT-Tank.RADIUS*8-GameFrame.titleBarH;

    //地图元素块的容器
    private List<MapTile> tiles = new ArrayList<>();

    //大本营
    private TankHouse house;

    public GameMap() {}
    /**
     * 初始化地图元素块,level : 第几关
     */
    public void initMap(int level){
        tiles.clear();
        try {
            loadLevel(level);
        } catch (Exception e) {
            e.printStackTrace();
        }

        //初始化大本营
        house = new TankHouse();
        addHouse();
    }

    /**
     * 加载关卡信息
     * @param level
     */
    private void loadLevel(int level) throws Exception{
        //获得关卡信息类的唯一实例对象
        LevelInof levelInof = LevelInof.getInstance();
        levelInof.setLevel(level);

        Properties prop = new Properties();
        prop.load(new FileInputStream("level/lv_"+level));
        //将所有的地图信息都加载进来
        int enemyCount = Integer.parseInt(prop.getProperty("enemyCount"));
        //设置敌人数量
        levelInof.setEnemyCount(enemyCount);

        //0,1 对敌人类型解析
        String[] enemyType = prop.getProperty("enemyType").split(",");
        int[] type = new int[enemyType.length];
        for (int i = 0; i < type.length; i++) {
            type[i] = Integer.parseInt(enemyType[i]);
        }
        //设置敌人类型
        levelInof.setEnemyType(type);
        //关卡难度
        //如果没有设计游戏难度,那么就当默认的处理
        String levelType = prop.getProperty("levelType");
        levelInof.setLevelType(Integer.parseInt(levelType==null? "1" : levelType));

        String methodName = prop.getProperty("method");
        int invokeCount = Integer.parseInt(prop.getProperty("invokeCount"));
        //把实参都读取到数组中来。
        String[] params = new String[invokeCount];
        for (int i = 1; i <=invokeCount ; i++) {
            params[i-1] = prop.getProperty("param"+i);
        }
        //使用读取到的参数,调用对应的方法。
        invokeMethod(methodName,params);
    }

    //根据方法的名字和参数调用对应的方法
    private void invokeMethod(String name,String[] params){
        for (String param : params) {
            //获得每一行的方法的参数,解析。
            String[] split = param.split(",");
            //使用一个int 数组保存解析后的内容
            int[] arr = new int[split.length];
            int i;
            for (i = 0; i < split.length-1; i++) {
                arr[i] = Integer.parseInt(split[i]);
            }
            //块之间的间隔是地图块的倍数
            final int DIS = MapTile.tileW ;

            //解析最后一个double值
            int dis = (int)(Double.parseDouble(split[i])*DIS);
            switch(name){
                case "addRow":
                    addRow(MAP_X+arr[0]*DIS,MAP_Y+arr[1]*DIS,
                            MAP_X+MAP_WIDTH-arr[2]*DIS,arr[3],dis);
                    break;
                case "addCol":
                    addCol(MAP_X+arr[0]*DIS,MAP_Y+arr[1]*DIS,
                            MAP_Y+MAP_HEIGHT-arr[2]*DIS,
                            arr[3],dis);
                    break;
                case "addRect":
                    addRect(MAP_X+arr[0]*DIS,MAP_Y+arr[1]*DIS,
                            MAP_X+MAP_WIDTH-arr[2]*DIS,
                            MAP_Y+MAP_HEIGHT-arr[3]*DIS,
                            arr[4],dis);
                    break;
            }
        }
    }

    //将老巢的所有的元素块添加到地图的容器中
    private void addHouse(){
        tiles.addAll(house.getTiles());
    }

    /**
     * 某一个点确定的地图块。是否和 tiles 集合中的所有的块 有重叠的部分
     * @param tiles
     * @param x
     * @param y
     * @return 有重叠返回 true,否则 false
     */
    private boolean isCollide(List<MapTile> tiles, int x ,int y){
        for (MapTile tile : tiles) {
            int tileX = tile.getX();
            int tileY = tile.getY();
            if(Math.abs(tileX-x) < MapTile.tileW && Math.abs(tileY-y) < MapTile.tileW){
                return true;
            }
        }
        return false;
    }

    /**
     * 只对没有遮挡效果的块进行绘制
     * @param g
     */
    public void drawBk(Graphics g){
        for (MapTile tile : tiles) {
            if(tile.getType() != MapTile.TYPE_COVER)
                tile.draw(g);
        }
    }

    /**
     * 只绘制有遮挡效果的块
     * @param g
     */
    public void drawCover(Graphics g){
        for (MapTile tile : tiles) {
            if(tile.getType() == MapTile.TYPE_COVER)
                tile.draw(g);
        }
    }

    public List<MapTile> getTiles() {
        return tiles;
    }

    /**
     * 将所有的不可见的地图块从容器中移除
     */
    public void clearDestroyTile(){
        for (int i = 0; i < tiles.size(); i++) {
            MapTile tile = tiles.get(i);
            if(!tile.isVisible())
                tiles.remove(i);
        }
    }

    /**
     *往地图块容器中添加一行指定类型的地图块
     * @param startX 添加地图块的起始的x坐标
     * @param startY 添加地图块的起始的Y坐标
     * @param endX 添加地图块的结束的x坐标
     * @param type 地图块的类型
     * @param DIS 地图块之间的中心点的间隔 如果是块的宽度 意味着是连续的,
     *            如果大于块的宽度就是不连续的
     */
    public void addRow(int startX,int startY, int endX, int type, final int DIS){
        int count  = (endX - startX +DIS )/(MapTile.tileW+DIS);
        for (int i = 0; i <count ; i++) {
            MapTile tile = MapTilePool.get();
            tile.setType(type);
            tile.setX(startX + i * (MapTile.tileW+DIS));
            tile.setY(startY);
            tiles.add(tile);
        }
    }

    /**
     * 往地图元素块容器中添加一列 元素。
     * @param startX  该列的起始x坐标
     * @param startY 该列的起始y坐标
     * @param endY  改了的结束y坐标
     * @param type 元素类型
     * @param DIS 相邻元素中心点的间距
     */
    public void addCol(int startX,int startY, int endY, int type, final int DIS){
        int count  = (endY - startY +DIS)/(MapTile.tileW+DIS);
        for (int i = 0; i <count ; i++) {
            MapTile tile = MapTilePool.get();
            tile.setType(type);
            tile.setX(startX );
            tile.setY(startY + i * (MapTile.tileW+DIS));
            tiles.add(tile);
        }
    }

    //对指定的矩形区域添加元素块
    public void addRect(int startX,int startY,int endX, int endY, int type, final int DIS){
        int rows = (endY-startY+DIS)/(MapTile.tileW+DIS);
        for (int i = 0; i <rows ; i++) {
            addRow(startX,startY+i*(MapTile.tileW+DIS),endX,type,DIS);
        }
    }


}

2.TankHouse

public class TankHouse {
    //老巢的xy坐标
    public static final int HOUSE_X = (Constant.FRAME_WIDTH-3*MapTile.tileW >> 1)+2;
    public static final int HOUSE_Y = Constant.FRAME_HEIGHT-2 *MapTile.tileW;

    //一共六块地图块
    private List<MapTile> tiles = new ArrayList<>();
    public TankHouse() {
        tiles.add(new MapTile(HOUSE_X,HOUSE_Y));
        tiles.add(new MapTile(HOUSE_X,HOUSE_Y+MapTile.tileW));
        tiles.add(new MapTile(HOUSE_X+MapTile.tileW,HOUSE_Y));

        tiles.add(new MapTile(HOUSE_X+MapTile.tileW*2,HOUSE_Y));
        tiles.add(new MapTile(HOUSE_X+MapTile.tileW*2,HOUSE_Y+MapTile.tileW));
        //有文字的块
        tiles.add(new MapTile(HOUSE_X+MapTile.tileW,HOUSE_Y+MapTile.tileW));
        //设置老巢地图块的类型
        tiles.get(tiles.size()-1).setType(MapTile.TYPE_HOUSE);
    }

    public  void draw(Graphics g){
        for (MapTile tile : tiles) {
            tile.draw(g);
        }
    }

    public List<MapTile> getTiles() {
        return tiles;
    }
}


3.MapTile

public class MapTile {

    public static final int TYPE_NORMAL = 0;
    public static final int TYPE_HOUSE = 1;
    public static final int TYPE_COVER = 2;
    public static final int TYPE_HARD = 3;


    public static int tileW = 40;
    public static int radius = tileW >> 1;
    private int type = TYPE_NORMAL;

    private static Image[] tileImg;
    static{
        tileImg = new Image[4];
        tileImg[TYPE_NORMAL] = MyUtil.createImage("res/tile.png");
        tileImg[TYPE_HOUSE] = MyUtil.createImage("res/house.png");
        tileImg[TYPE_COVER] = MyUtil.createImage("res/cover.png");
        tileImg[TYPE_HARD] = MyUtil.createImage("res/hard.png");

        if(tileW <=0){
            tileW = tileImg[TYPE_NORMAL].getWidth(null);
        }
    }

    //图片资源的左上角
    private int x,y;
    private boolean visible = true;

    public MapTile() {
    }

    public MapTile(int x, int y) {
        this.x = x;
        this.y = y;
        if(tileW <=0){
            tileW = tileImg[TYPE_NORMAL].getWidth(null);
        }
    }

    public void draw(Graphics g){
        if(!visible)
            return;

        if(tileW <=0){
            tileW = tileImg[TYPE_NORMAL].getWidth(null);
        }

        g.drawImage(tileImg[type],x,y,null);

    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public boolean isVisible() {
        return visible;
    }

    public void setVisible(boolean visible) {
        this.visible = visible;
    }

    public int getType() {
        return type;
    }

    public void setType(int type) {
        this.type = type;
    }

    /**
     * 地图块和若干个子弹是否有碰撞
     * @param bullets
     * @return
     */
    public boolean isCollideBullet(List<Bullet> bullets){
        if(!visible || type == TYPE_COVER)
            return false;
        for (int i = 0; i < bullets.size(); i++) {
            Bullet bullet = bullets.get(i);
//        }
//        for (Bullet bullet : bullets) {
            int bulletX = bullet.getX();
            int bulletY = bullet.getY();
            boolean collide = MyUtil.isCollide(x + radius, y + radius, radius, bulletX, bulletY);
            if(collide){
                //子弹的销毁
                bullet.setVisible(false);
                BulletsPool.theReturn(bullet);
                return true;
            }
        }
        return false;
    }

    //判断当前的地图块是否是老巢
    public boolean isHouse(){
        return type == TYPE_HOUSE;
    }

    @Override
    public String toString() {
        return "MapTile{" +
                "x=" + x +
                ", y=" + y +
                ", visible=" + visible +
                '}';
    }
}


 

  • 10
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
Java坦克大战小游戏是一款基于Java语言开发的经典游戏。在游戏中,玩家扮演一辆坦克,通过控制坦克的移动和射击来击败敌方坦克,完成各种任务。 要实现Java坦克大战小游戏,可以按照以下步骤进行: 1. 创建游戏窗口:使用Java的图形库(如AWT或Swing)创建一个窗口,作为游戏的显示界面。 2. 绘制游戏场景:在游戏窗口中绘制游戏场景,包括地图、坦克、子弹等元素。可以使用Java的图形绘制API(如Graphics类)来实现。 3. 实现坦克的移动:通过监听键盘事件,控制坦克的移动。根据按下的方向键来改变坦克的位置。 4. 实现坦克的射击:通过监听键盘事件,控制坦克的射击。根据按下的射击键来创建子弹对象,并将其添加到游戏场景中。 5. 实现敌方坦克的AI:为敌方坦克添加AI逻辑,使其能够自动移动和射击。可以使用简单的算法来实现敌方坦克的行为。 6. 碰撞检测:在游戏中实现碰撞检测,判断坦克和子弹之间是否发生碰撞。如果发生碰撞,根据游戏规则进行相应的处理。 7. 实现游戏逻辑:根据游戏规则,实现游戏的逻辑,包括判断胜负、计分等。 8. 添加音效和特效:为游戏添加音效和特效,增加游戏的趣味性和可玩性。 以上是实现Java坦克大战小游戏的一般步骤,具体的实现细节可以根据个人的需求和技术水平进行调整和扩展。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值