7

基于Java UI开发的小游戏—推箱子(上)

 1 year ago
source link: https://www.51cto.com/article/743260.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

基于Java UI开发的小游戏—推箱子(上)

作者:木棉花BlueStar 2022-12-27 14:39:38
笔者在进行开发的过程中,并不是写完一个界面的内部逻辑,就开始对界面进行美化,而是先让所有的东西可以正常地跑起来,再谈美化。
331a13e205754a7ce4e281ad9ce03938f45e65.png

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

在​​上期文章​​中,分享了关于项目的效果预览图,从这一期开始,将逐步分享这个项目的构建流程。实际上,笔者在进行开发的过程中,并不是写完一个界面的内部逻辑,就开始对界面进行美化,而是先让所有的东西可以正常地跑起来,再谈美化。因此本系列文章前半部分会重点讨论游戏以及界面之间的核心逻辑,后半部分则会分享美化界面的部分。

打开DevEco Studio,创建一个新项目,选择JAVA作为开发语言,将项目保存至合适的位置。

【木棉花】基于JAVA UI开发的小游戏——推箱子(上)-开源基础软件社区

根据上期分享的开发思路,先完成UI交互部分的框架。

【木棉花】基于JAVA UI开发的小游戏——推箱子(上)-开源基础软件社区

可以看到,这里需要新建三个Slice(原本自带一个MainAbilitySlice):

【木棉花】基于JAVA UI开发的小游戏——推箱子(上)-开源基础软件社区

下面对四个。

MainAbilitySlice:打开应用时,首先显示的界面,也就是用户主界面。

【木棉花】基于JAVA UI开发的小游戏——推箱子(上)-开源基础软件社区

SelectSlice:关卡选择界面,用户可以在这个界面选择将要跳转的关卡。

【木棉花】基于JAVA UI开发的小游戏——推箱子(上)-开源基础软件社区

InitSlice:加载界面。当用户选择关卡之后,会进入加载界面,仿照游戏加载资源。(实际上啥都没干)。

【木棉花】基于JAVA UI开发的小游戏——推箱子(上)-开源基础软件社区

GameSlice:最后一个界面,也就是这个游戏的核心界面,所有的游戏逻辑都将在这个页面中进行,因此它将是本篇文章的核心讲解部分。

【木棉花】基于JAVA UI开发的小游戏——推箱子(上)-开源基础软件社区

至此,我们可以简单地梳理一下四个界面以及他们包含的组件之间的关系:用户进入MainAbilitySlice之后,通过“开始游戏”按键进入SelectSlice,在SelectSlice中有三个按键,会对应跳转到三个不同的关卡,但是进入关卡之前会先进入InitSlice,加载过后在进入最后的GameSlice,从而开始游戏。以上就是开发的时候要理清楚的页面跳转关系。

核心代码分析

MainAbilitySlice

里面有四个按钮,那可以简单的给他们分个类,例如:开始游戏的按钮要实现的功能是页面跳转,直接与其他界面关联,分为一类;历史记录与关于游戏可以用弹出窗口来实现,不需要额外界面,归为一类;退出游戏按钮直接结束应用进程,也是单独一类。明确之后,就可以给各个按钮添加点击事件了:

//开始游戏按钮
        startBtn.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {//页面跳转
                present(new SelectSlice(),new Intent());
            }
        });
        //历史记录按钮
        recordBtn.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {    
                //历史记录弹窗
            }
        });
        //关于游戏按钮
        aboutBtn.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                //关于游戏弹窗
            }
        });
        //退出游戏按钮
        exitBtn.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {//退出游戏提示
                CommonDialog commonDialog = new CommonDialog(getContext());
                commonDialog.setTitleText("提示");
                commonDialog.setContentText("是否退出游戏");
                commonDialog.setButton(1, "确定", new IDialog.ClickedListener() {
                    @Override
                    public void onClick(IDialog iDialog, int i) {
                        terminateAbility();
                    }
                });
                commonDialog.setButton(2, "取消", new IDialog.ClickedListener() {
                    @Override
                    public void onClick(IDialog iDialog, int i) {
                        commonDialog.destroy();
                    }
                });
                commonDialog.show();
            }
        });

在开发中,由于历史记录跟关于游戏这两个功能并不是核心,因此,最开始也只是做个壳子放在这,以便自己能专注于游戏主逻辑的开发,这也是我想分享的一种思路:先搭壳子再填东西。因此,阅读本系列时,如果碰到代码中只有注释,没有实现内容时,那是因为当时做到这一步的时候,并不会去关注具体如何实现,只会想个大概,先放着。

到这里之后,实际上已经完成了游戏的退出以及从MainAbilitySlice页面到SelectSlice页面的导航,便可进行到我们的下一步。

SelectSlice

这一个界面主要有三个按钮,如何实现按下不同的按钮,跳转到同一个加载界面,但是加载完后又跳转到不同的游戏界面?这里使用Intent对跳转时的数据进行打包传输,具体实现如下:

firstBtn.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                Intent i = new Intent();
                i.setParam("关卡",1);
                present(new InitSlice(),i);
            }
        });
        secondBtn.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                Intent i = new Intent();
                i.setParam("关卡",2);
                present(new InitSlice(),i);
            }
        });
        thirdBtn.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                Intent i = new Intent();
                i.setParam("关卡",3);
                present(new InitSlice(),i);
            }
        });

这里Intent的key都是“关卡”,但是有不同的value,对应不同的关卡。实际上,到这里SelectSlice已经完成了它的功能了。接下来进入InitSlice。

InitSlice

在加载界面中,我预想的是一个动态的画面,然后加上一个进度条,因此我可能需要用到能够播放gif的组件,以及进度条组件。那要怎么实现加载的时候进度条跟进?我的实现方式是使用两个定时器(其实用一个也完全能搞定)。

//onStart外定义
    Timer t1 = new Timer();
    Timer t2 = new Timer();
//onStart内
        TimerTask task1 = new TimerTask() {
            @Override
            public void run() {//页面跳转
                present(new GameSlice(),intent);
            }
        };
        TimerTask task2 = new TimerTask() {
            @Override
            public void run() {//进度条更新
                int value = progressBar.getProgress();
                progressBar.setProgressValue(value+20);
            }
        };
        t1.schedule(task1, 5000);
        t2.schedule(task2,0,1000);

关于如何播放gif,本不应该在此讲解,因为与主线任务无关,但是这里用到的第三方组件,后面游戏界面频繁使用,因此在这进行介绍。

int imageResourceId = ResourceTable.Media_gifimg;
        Glide.with(this)
                .asGif()
                .load(imageResourceId)
                .into(draweeView);

至此,从InitSlice跳转到GameSlice的逻辑也写好了,并且携带着从SelectSlice打包过来的数据,接下来重点讲解游戏界面的实现。

GameSlice

制作一个可以玩的游戏界面最首要的任务就是绘制地图,因此定义了一个JAVA类GameMap用于地图的绘制。

在说明如何实现GameMap之前,我想先简单阐述一下推箱子游戏的实现逻辑:实际上每一次操作的都是图片,逻辑判断依赖的是图片所绑定的属性值(只涉及加减运算),举个例子:我在程序中将路设置为0,将墙体设置为1,将宝可梦设置为2和3,将空球设置为4,那收服之后的球应该设置为:2+4=6、3+4=7,这样就实现了你把空球推向宝可梦时,显示的是已经收复的球的状态;而如果将人设置为8,那8+2=10、8+3=11也必须是人,这样才能实现你移动到宝可梦上面时,是以原人物的方式呈现。这是在设置属性值需要注意的,其他方面,例如怎么判断墙体之类的,只需要if语句判断即可。

还有一点,如果我们要实现回退功能,就需要用到栈的一些相关操作。

核心代码如下:

//GameMap继承于PositionLayout布局,方便对图片进行渲染
public class GameMap extends PositionLayout{
    private final static int size = 110;
    //用二维数组来存储地图
    private Integer[][] gameMap;//定义x,y坐标
    private Pair<Integer,Integer> map_position;//标识是否绘制过地图(画过一次后,后面所有的操作都只能是进行刷新,防止重复生成对象)
    private Boolean isDrew = Boolean.FALSE;//定义移动方式枚举,方便外部调用进行选择
    public enum MOVE_WAY{
        MOVE_UP,
        MOVE_DOWN,
        MOVE_LEFT,
        MOVE_RIGHT
    }
    //设置每种物体的属性值
    private final static int ROAD = 0;
    private final static int WALL = 1;

    private final static int LABA = 2;
    private final static int YIBU = 3;
    private final static int BOBO = 4;
    private final static int MINI = 5;
    private final static int MIAO = 6;

    private final static int BALL_EMPTY = 7;
    private final static int BALL_FULL1 = 9;
    private final static int BALL_FULL2 = 10;
    private final static int BALL_FULL3 = 11;
    private final static int BALL_FULL4 = 12;
    private final static int BALL_FULL5 = 13;
    private final static int PEOPLE1 = 14;
    private final static int PEOPLE2 = 16;
    private final static int PEOPLE3 = 17;
    private final static int PEOPLE4 = 18;
    private final static int PEOPLE5 = 19;
    private final static int PEOPLE6 = 20;//定义存储地图用的栈
    private Stack<Integer[][]> stack;//可使用此构造函数绘制不同大小的地图,这个是预留的接口,项目中使用的是直接在xml文件中加入这个组件(因为继承了PositionLayout所以可以在xml文件中使用),当然也可以直接用构造函数创建,留给读者自己发挥。
    public GameMap(Context context,Integer[][] map,int x,int y) {
        super(context);
        gameMap = map;
        map_position = new Pair<>(x,y);
    }//外部设置地图接口
    public void setMap(Integer[][] map) {
        gameMap = map;
        map_position = new Pair<>(map.length,map[0].length);
        stack = new Stack<>();
    }//绘制地图接口
    public void drawMap() {
        setHeight(size * map_position.s);
        setWidth(size * map_position.f);
        for (int i = 0; i < map_position.f; i++) {
            for (int j = 0; j < map_position.s; j++) {
                DraweeView draweeView = new DraweeView(getContext());
                draweeView.setComponentSize(size,size);
                draweeView.setContentPosition(size * j, size * i);
                int index = gameMap[i][j];
                switch (index) {
                    case ROAD:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_road)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case WALL:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_wall)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case LABA:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_laba)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case YIBU:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_yibu)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case BOBO:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_bobo)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case MINI:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_mini)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case MIAO:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_miao)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case BALL_EMPTY:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_ballEmpty)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case BALL_FULL1:
                    case BALL_FULL2:
                    case BALL_FULL3:
                    case BALL_FULL4:
                    case BALL_FULL5:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_ballFull)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case PEOPLE1:
                    case PEOPLE2:
                    case PEOPLE3:
                    case PEOPLE4:
                    case PEOPLE5:
                    case PEOPLE6:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_people)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                }

                this.addComponent(draweeView);
            }
        }
        isDrew = Boolean.TRUE;
    }//外部刷新地图接口
    public void flushMap(){
        for (int i = 0; i < map_position.f; i++) {
            for (int j = 0; j < map_position.s; j++) {
                DraweeView draweeView = (DraweeView) getComponentAt(i * map_position.s + j);
                draweeView.setComponentSize(size,size);
                draweeView.setContentPosition(size * j, size * i);
                int index = gameMap[i][j];
                switch (index) {
                    case ROAD:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_road)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case WALL:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_wall)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case LABA:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_laba)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case YIBU:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_yibu)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case BOBO:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_bobo)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case MINI:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_mini)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case MIAO:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_miao)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case BALL_EMPTY:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_ballEmpty)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case BALL_FULL1:
                    case BALL_FULL2:
                    case BALL_FULL3:
                    case BALL_FULL4:
                    case BALL_FULL5:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_ballFull)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                    case PEOPLE1:
                    case PEOPLE2:
                    case PEOPLE3:
                    case PEOPLE4:
                    case PEOPLE5:
                    case PEOPLE6:
                        Glide.with(getContext())
                                .load(ResourceTable.Media_people)
                                .diskCacheStrategy(DiskCacheStrategy.NONE)
                                .skipMemoryCache(true)
                                .into(draweeView);
                        break;
                }

            }
        }
    }//获取当前操作的人物坐标
    public Pair<Integer,Integer> getMyPosition(){
        for (int i = 0; i < map_position.f; i++)
        {
            for (int j = 0; j < map_position.s; j++)
            {
                if (gameMap[i][j] == PEOPLE1 || gameMap[i][j] == PEOPLE2 ||
                        gameMap[i][j] == PEOPLE3 || gameMap[i][j] == PEOPLE4 ||
                        gameMap[i][j] == PEOPLE5 || gameMap[i][j] == PEOPLE6)
                {
                    return new Pair<>(i,j);
                }

            }
        }
        return new Pair<>(-1,-1);
    }//给地图里任意一张图设置对应的值,移动的时候需要此接口
    protected void setValue(int x,int y,int value){
        gameMap[x][y] += value;
    }//判断是否能够移动
    protected Boolean isMove(int i,int j){
        if (gameMap[i][j] == ROAD || gameMap[i][j] == LABA ||
                gameMap[i][j] == YIBU || gameMap[i][j] == BOBO ||
                gameMap[i][j] == MINI || gameMap[i][j] == MIAO)
            return Boolean.TRUE;
        return Boolean.FALSE;
    }//判断是不是球
    protected Boolean isBall(int i,int j){
        if (gameMap[i][j] == BALL_EMPTY || gameMap[i][j] == BALL_FULL1 ||
                gameMap[i][j] == BALL_FULL2 || gameMap[i][j] == BALL_FULL3 ||
                gameMap[i][j] == BALL_FULL4 || gameMap[i][j] == BALL_FULL5)
        {
            return true;
        }
        return Boolean.FALSE;
    }//外部接口,每一次移动完判断游戏是否结束
    public Boolean isWin(){
        for (int i = 0; i < map_position.f; i++)
        {
            for (int j = 0; j < map_position.s; j++)
            {
                if (gameMap[i][j] == LABA || gameMap[i][j] == YIBU ||
                        gameMap[i][j] == BOBO || gameMap[i][j] == MINI ||
                        gameMap[i][j] == MIAO) return Boolean.FALSE;
            }
        }
        return Boolean.TRUE;
    }//外部移动接口
    public void move(@NotNull MOVE_WAY move_way){
        Pair<Integer,Integer> position = getMyPosition();
        Integer[][] oldMap = new Integer[map_position.f][map_position.s];
        for (int i = 0; i < map_position.f; i++) {
            if (map_position.s >= 0) System.arraycopy(gameMap[i], 0, oldMap[i], 0, map_position.s);
        }

        stack.push(oldMap);
        switch (move_way){
            case MOVE_UP:
                if (this.isMove(position.f - 1, position.s))
                {
                    this.setValue(position.f, position.s, -PEOPLE1);
                    this.setValue(position.f - 1, position.s, PEOPLE1);
                }
                if (this.isBall(position.f - 1, position.s))
                {
                    if (this.isMove(position.f - 2, position.s))
                    {
                        this.setValue(position.f, position.s, -PEOPLE1);
                        this.setValue(position.f - 1, position.s, BALL_EMPTY);
                        this.setValue(position.f - 2, position.s, BALL_EMPTY);
                    }
                }
                break;
            case MOVE_DOWN:
                if (this.isMove(position.f + 1, position.s))
                {
                    this.setValue(position.f, position.s, -PEOPLE1);
                    this.setValue(position.f + 1, position.s, PEOPLE1);
                }
                if (this.isBall(position.f + 1, position.s))
                {
                    if (this.isMove(position.f + 2, position.s))
                    {
                        this.setValue(position.f, position.s, -PEOPLE1);
                        this.setValue(position.f + 1, position.s, BALL_EMPTY);
                        this.setValue(position.f + 2, position.s, BALL_EMPTY);
                    }
                }
                break;
            case MOVE_LEFT:
                if (this.isMove(position.f, position.s - 1))
                {
                    this.setValue(position.f, position.s, -PEOPLE1);
                    this.setValue(position.f, position.s - 1, PEOPLE1);
                }
                if (this.isBall(position.f, position.s - 1))
                {
                    if (this.isMove(position.f, position.s - 2))
                    {
                        this.setValue(position.f, position.s, -PEOPLE1);
                        this.setValue(position.f, position.s - 1, BALL_EMPTY);
                        this.setValue(position.f, position.s - 2, BALL_EMPTY);
                    }
                }
                break;
            case MOVE_RIGHT:
                if (this.isMove(position.f, position.s + 1))
                {
                    this.setValue(position.f, position.s, -PEOPLE1);
                    this.setValue(position.f, position.s + 1, PEOPLE1);
                }
                if (this.isBall(position.f, position.s + 1))
                {
                    if (this.isMove(position.f, position.s + 2))
                    {
                        this.setValue(position.f, position.s, -PEOPLE1);
                        this.setValue(position.f, position.s + 1, BALL_EMPTY);
                        this.setValue(position.f, position.s + 2, BALL_EMPTY);
                    }
                }
                break;
        }
        flushMap();
    }//外部回退原先地图接口
    public void back(){
        if(stack.empty()) return;
        Integer[][] temp = stack.peek();
        for (int i = 0; i < map_position.f; i++) {
            if (map_position.s >= 0) System.arraycopy(temp[i], 0, gameMap[i], 0, map_position.s);
        }
        flushMap();
        stack.pop();
    }

    public Boolean getIsDrew(){
        return isDrew;
    }

    public GameMap(Context context) {
        super(context);
    }

    public GameMap(Context context, AttrSet attrSet) {
        super(context, attrSet);
    }

    public GameMap(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
    }
}

至此,完成了地图类的代码,可以开始绘制GameSlice了。在预览图中看到,核心部分有很多:一个退出界面按钮,一个设置按钮,一个倒计时器,还有一张地图,一个后退地图操作的按钮,按照我自己的想法先进行分类。后退地图操作的按钮和地图是刚需,优先实现,代码如下:

//在外部定义变量
    float start_x;
    float start_y;

    Integer[][] map;
    Integer[][] map1 = {
            {1, 1, 1, 1, 1, 1, 1, 1, 1},
            {1, 0, 0, 0, 1, 0, 0, 1, 1},
            {1, 0, 1, 0, 1, 7, 2, 1, 1},
            {1, 0, 0, 0, 0, 7, 3, 1, 1},
            {1, 0, 1, 0, 1, 7, 4, 1, 1},
            {1, 0, 0, 0, 1, 0, 0, 1, 1},
            {1, 1, 1, 1, 1, 0, 14, 1, 1},
            {1, 1, 1, 1, 1, 1, 1, 1, 1},
            {1, 1, 1, 1, 1, 1, 1, 1, 1}
    };
    Integer[][] map2 = {
            {1, 1, 1, 1, 1, 1, 1, 1, 1},
            {1, 1, 1, 1, 1, 1, 1, 1, 1},
            {1, 1, 0, 0, 0, 3, 0, 1, 1},
            {1, 1, 0, 1, 0, 1, 0, 1, 1},
            {1, 1, 0, 7, 14, 7, 0, 1, 1},
            {1, 1, 0, 1, 0, 1, 5, 1, 1},
            {1, 1, 0, 7, 6, 0, 0, 1, 1},
            {1, 1, 1, 1, 1, 1, 1, 1, 1},
            {1, 1, 1, 1, 1, 1, 1, 1, 1}
    };
    Integer[][] map3 = {
            {1, 1, 1, 1, 1, 1, 1, 1, 1},
            {1, 1, 1, 1, 1, 1, 1, 1, 1},
            {1, 0, 2, 0, 7, 0, 1, 1, 1},
            {1, 1, 0, 7, 6, 7, 0, 1, 1},
            {1, 3, 4, 5, 1, 0, 5, 1, 1},
            {1, 0, 1, 7, 0, 7, 0, 1, 1},
            {1, 0, 7, 0, 1, 2, 7, 1, 1},
            {1, 0, 14, 0, 0, 0, 0, 1, 1},
            {1, 1, 1, 1, 1, 1, 1, 1, 1}
    };

//onStart方法内

    switch (intent.getIntParam("关卡",0))
        {
            case 1:
                map = map1;
                break;
            case 2:
                map = map2;
                break;
            case 3:
                map = map3;
                break;
        }
        gameMap.setMap(map);
        if(!gameMap.getIsDrew()) gameMap.drawMap();
        else gameMap.flushMap();

    //滑动屏幕移动角色
        gameMap.setTouchEventListener(new Component.TouchEventListener() {
            @Override
            public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
                int action = touchEvent.getAction();
                switch (action) {
                    case TouchEvent.PRIMARY_POINT_DOWN:
                        MmiPoint startPoint = touchEvent.getPointerPosition(0);
                        start_x = startPoint.getX();
                        start_y = startPoint.getY();
                        break;
                    case TouchEvent.PRIMARY_POINT_UP:
                        MmiPoint endPoint = touchEvent.getPointerPosition(0);
                        if(endPoint.getX() > start_x && Math.abs(endPoint.getY() - start_y) < 100){//right
                            gameMap.move(GameMap.MOVE_WAY.MOVE_RIGHT);
                        }
                        else if(endPoint.getX() < start_x && Math.abs(endPoint.getY() - start_y) < 100){//left
                            gameMap.move(GameMap.MOVE_WAY.MOVE_LEFT);
                        }
                        else if(endPoint.getY() < start_y && Math.abs(endPoint.getX() - start_x) < 100){//up
                            gameMap.move(GameMap.MOVE_WAY.MOVE_UP);
                        }
                        else if(endPoint.getY() > start_y && Math.abs(endPoint.getX() - start_x) < 100){//down
                            gameMap.move(GameMap.MOVE_WAY.MOVE_DOWN);
                        }
                        if(gameMap.isWin()){
                            //赢了之后该干嘛

                        }
                        break;
                }
                return true;
            }

        });
        stackBtn.setClickedListener(new Component.ClickedListener() {
            @Override
            public void onClick(Component component) {
                gameMap.back();
            }
        });

游戏整体框架(不包括数据存储)大概就是这些,至此,已经实现了这个游戏最基础的功能了,从开始界面到游戏界面,以及各种游戏操作,接下来的事情就是对这些零零散散的组件,用一个漂亮的布局整合起来,再根据自己的兴趣添加一些其他功能,下篇将重点给出美化UI交互界面的代码,敬请期待!

​想了解更多关于开源的内容,请访问:​

​51CTO 开源基础软件社区​

​https://ost.51cto.com​

责任编辑:jianghua 来源: 51CTO 开源基础软件社区

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK