HarmonyOS(鸿蒙)手机第一个小游戏app——数字华容道

  • 前言
  • 概述
  • 正文
    • 创建项目
    • 实现初始界面布局
    • 实现数字的随机打乱
    • 实现滑动或点击调换数字
    • 实现游戏成功界面
  • 源代码
  • 结语

前言

2月16号HarmonyOS2.0手机开发者Beta版已经发布了,作为“1+8+N”战略的重要入口和生态核心,怎么能少得了手机应用开发呢,今天将由深鸿会深大学习小组(Zzt_01-23)从零基础开发第一个HarmonyOS手机小游戏——数字华容道(界面略丑陋,大佬别喷),此前已经在运动手表上成功开发了:HarmonyOS运动手表游戏合并、HarmonyOS手表游戏——数字华容道,同样是深鸿会深大小组学习完HarmonyOS后自行开发的一个鸿蒙demo,详细讲述了数字华容道在鸿蒙手机上开发思路。深鸿会深大学习小组是一群热衷于学习鸿蒙相关知识和开发鸿蒙相关应用的开发者们,我们的学习项目为:荔园Harmony,同时也欢迎与各位感兴趣的读者一起学习HarmonyOS开发,相互交流、共同进步。

概述

本个demo将从零基础开始完成鸿蒙小游戏APP在手机上的编译在项目中我们所使用到的软件为DevEco Studio,下载地址为:DevEco Studio下载、DevEco Studio安装教程,在项目中我们要实现的内容为数字华容道APP的开发。

  1. 打开引用首先为数字华容道的初始界面,点击开始游戏即会切换到数字华容道的游戏界面。
  2. 进入数字华容道的游戏界面显示4*4的方阵,方阵中分布有随意打乱的1至15的数字和一个空白方格,方阵下方显示一个“重新开始”的按钮和一个“返回”按钮,点击“重新开始”按钮即会重新生成随意打乱的1至15的数字和一个空白方格的方阵,点击“返回”按钮即会切换到数字华容道的初始界面,最下方有四个指示不同方向箭头的按钮,点击任一按钮或向上、下、左、右任一方向滑动,空白方格周围对应位置的方格便会随之向对应的方向移动一格。
  3. 经过若干次滑动或点击后,当所有的数字按顺序排列后,则会弹出游戏成功的界面,再滑动或点击也不会有任何变化。

正文

创建项目

DevEco Studio下载安装成功后,打开DevEco Studio,点击左上角的File,点击New,再选择New Project,选择Phone选项,选择默认的模板(java版),然后选择保存路径,将文件命名为MyPhoneApplication(文件名不能出现中文或者特殊字符,否则将无法成功创建项目文件),最后点击Finish。

实现初始界面布局

首先,我们要先实现数字华容道的初始界面,点击开始游戏即会切换到另一个空白的界面。

  1. 先在entry>src>main>config.json文件中最下方"launchType": “standard"的后面添加以下代码,并且将上方的“label”:“MyPhoneApplication”修改成"label”: “数字华容道”,这样就实现去掉应用上方的标题栏和将应用名称改为数字华容道了
    config.json最下面部分代码:
"orientation": "unspecified","name": "com.example.myphoneapplication.MainAbility","icon": "$media:icon","description": "$string:mainability_description","label": "数字华容道","type": "page","launchType": "standard","metaData": {"customizeData": [{"name": "hwc-theme","value": "androidhwext:style/Theme.Emui.Light.NoTitleBar","extra": ""}]}
  1. 先将我们事先准备好的图片复制粘贴到entry>src>main>resources>base>media文件夹中(ctrl+c、ctrl+v复制粘贴),并且命名为game,点击OK

    在entry>src>main>resources>base>layout>ability_main.xml中添加布局,先将事先存在的Text组件删去,添加Image图片组件,引入我们刚才复制粘贴的图片,再添加一个Button按钮组件,加入唯一标识符id并配置好其他相应的属性
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayoutxmlns:ohos="http://schemas.huawei.com/res/ohos"ohos:height="match_parent"ohos:width="match_parent"ohos:orientation="vertical"><Imageohos:height="match_parent"ohos:width="match_parent"ohos:image_src="$media:game"ohos:layout_alignment="center"/><Buttonohos:id="$+id:button_game"ohos:height="150"ohos:width="515"ohos:text_alignment="center"ohos:top_margin="-810"ohos:left_margin="250"/></DirectionalLayout>
  1. 在entry>src>main>java>com.example.myphoneapplication>slice中右键选择New>Java Class增加一个空白的类以用来后面编写数字华容道的游戏界面,并且命名为SecondAbilitySlice
    将entry>src>main>java>com.example.myphoneapplication>slice>SecondAbilitySlice中的代码修改成如下:
package com.example.myphoneapplication.slice;import com.example.myphoneapplication.ResourceTable;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;public class SecondAbilitySlice extends AbilitySlice {public void onStart(Intent intent) {super.onStart(intent);}@Overridepublic void onActive() {super.onActive();}@Overridepublic void onForeground(Intent intent) {super.onForeground(intent);}
}
  1. 在entry>src>main>java>com.example.myphoneapplication>slice>MainAbilitySlice中的onStart函数中添加一个按钮指向我们(2)中添加的按钮,按钮添加一个响应点击事件的函数,用parsent函数跳转到SecondAbilitySlice
package com.example.myphoneapplication.slice;import com.example.myphoneapplication.ResourceTable;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.Component;public class MainAbilitySlice extends ohos.aafwk.ability.AbilitySlice {@Overridepublic void onStart(Intent intent) {super.onStart(intent);super.setUIContent(ResourceTable.Layout_ability_main);Button button = (Button) findComponentById(ResourceTable.Id_button_game);button.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {present(new SecondAbilitySlice(),new Intent());}});}@Overridepublic void onActive() {super.onActive();}@Overridepublic void onForeground(Intent intent) {super.onForeground(intent);}
}

至此,这一部分就完成了。

实现数字的随机打乱

然后我们要在数字华容道的游戏界面生成随意打乱的1至15的数字和一个空白方格的方阵。

在entry>src>main>java>com.example.myphoneapplication>slice>SecondAbilitySlice编写代码
先定义个一个位置布局layout和一个二维数组grids,创建函数initializeinitialize()分别对其初始化,在onStart函数中调用函数initializeinitialize()

private float starX, starY, distanceX, distanceY;private DirectionalLayout layout;private int[][] grids;public void onStart(Intent intent) {super.onStart(intent);initialize();}public void initialize(){layout = new DirectionalLayout(this);grids = new int[][]{{1, 2, 3, 4}, {5, 6, 7, 8,}, {9, 10, 11, 12}, {13, 14, 15, 0}};}

然后定义函数drawGrids(int[][] grids)用于绘制4*4方阵和其二维数组对应的数字

public void drawGrids(int[][] grids){layout.setLayoutConfig((new ComponentContainer.LayoutConfig(ComponentContainer.LayoutConfig.MATCH_PARENT,ComponentContainer.LayoutConfig.MATCH_PARENT)));Component.DrawTask task=new Component.DrawTask() {public void onDraw(Component component, Canvas canvas) {Paint mPaint = new Paint();mPaint.setColor(Color.GRAY);RectFloat rect=new RectFloat(2,230,1078,1306);canvas.drawRect(rect,mPaint);for(int row = 0; row < 4; row++){for(int column = 0; column < 4; column++){mPaint.setColor(Color.CYAN);RectFloat rectFloat=new RectFloat(22+column*262,250+row*262,272+column*262,500+row*262);canvas.drawRect(rectFloat,mPaint);mPaint.setColor(Color.YELLOW);mPaint.setTextSize(125);if(grids[row][column]!=0){if(grids[row][column]<10){canvas.drawText(mPaint, String.valueOf(grids[row][column]),105+column*262,425+row*262);}else{canvas.drawText(mPaint, String.valueOf(grids[row][column]),65+column*262,425+row*262);}}}}}};layout.addDrawTask(task);setUIContent(layout);}

再定义函数changeGrids(int[][] grids,int direction),每次接收一个方向,2表示上移,-1表示左移,1表示右移,-2表示下移,找出空白方格所在位置对应的二维数组下标,对应的方格和空白方格对应的二维数组的数值对调

public void changeGrids(int[][] grids,int direction){int row_0 = 3;int column_0 = 3;int temp;for(int row = 0; row < 4; row++) {for (int column = 0; column < 4; column++) {if(grids[row][column] == 0){row_0 = row;column_0 = column;}}}if(direction == -1 && (column_0 + 1) <= 3){temp = grids[row_0][column_0 + 1];grids[row_0][column_0 + 1] = grids[row_0][column_0];grids[row_0][column_0] = temp;}else if (direction == 1 && (column_0 - 1) >= 0) {temp = grids[row_0][column_0 - 1];grids[row_0][column_0 - 1] = grids[row_0][column_0];grids[row_0][column_0] = temp;} else if (direction == 2 && (row_0 + 1) <= 3) {temp = grids[row_0 + 1][column_0];grids[row_0 + 1][column_0] = grids[row_0][column_0];grids[row_0][column_0] = temp;} else if (direction == -2 && (row_0 - 1) >= 0) {temp = grids[row_0 - 1][column_0];grids[row_0 - 1][column_0] = grids[row_0][column_0];grids[row_0][column_0] = temp;}}

定义函数createGrids(int[][] grids)用于随机生成一个表示方向的数字,循环调用函数changeGrids(grids,direction)用于随机打乱二维数组对应的数字

public void createGrids(int[][] grids){int[] array = {-1,-2,1,2};for(int i = 0; i < 100; i++){int random = (int)Math.floor(Math.random()*4);int direction = array[random];changeGrids(grids,direction);}}
最后在initialize()函数中调用createGrids(grids)函数和drawGrids(grids)函数public void initialize(){layout = new DirectionalLayout(this);grids = new int[][]{{1, 2, 3, 4}, {5, 6, 7, 8,}, {9, 10, 11, 12}, {13, 14, 15, 0}};createGrids(grids);drawGrids(grids);}

至此,这一部分完成了。

实现滑动或点击调换数字

添加“重新开始”和“返回”按钮,在最下方添加四个指示不同方向箭头的按钮,点击任一按钮或向上、下、左、右任一方向滑动,空白方格周围对应位置的方格便会随之向对应的方向移动一格。

在entry>src>main>java>com.example.myphoneapplication>slice>SecondAbilitySlice编写代码
先定义一个函数drawButton()用于绘制所有的按钮,四个指示不同方向箭头的按钮分别添加四个响应点击事件的函数,分别调用对应的changeGrids(grids,direction)函数实现空白方格周围对应位置的方格便会随之向对应的方向移动一格,并调用drawGrids(grids)函数用于绘制新的方阵

public void drawButton(){Button button=new Button(this);button.setText("重新开始");button.setTextSize(100);button.setTextAlignment(TextAlignment.CENTER);button.setTextColor(Color.WHITE);button.setMarginTop(1400);button.setMarginLeft(80);button.setPadding(20,20,20,20);ShapeElement background = new ShapeElement();background.setRgbColor(new RgbColor(174, 158, 143));background.setCornerRadius(100);button.setBackground(background);layout.addComponent(button);Button button0=new Button(this);button0.setText("返回");button0.setTextSize(100);button0.setTextAlignment(TextAlignment.CENTER);button0.setTextColor(Color.WHITE);button0.setMarginTop(-170);button0.setMarginLeft(680);button0.setPadding(20,20,20,20);button0.setBackground(background);layout.addComponent(button0);ShapeElement background0 = new ShapeElement();background0.setRgbColor(new RgbColor(174, 158, 143));background0.setCornerRadius(100);Button button1=new Button(this);button1.setText("↑");button1.setTextAlignment(TextAlignment.CENTER);button1.setTextColor(Color.WHITE);button1.setTextSize(100);button1.setMarginLeft(500);button1.setMarginTop(70);button1.setPadding(10,0,10,0);button1.setBackground(background0);button1.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {changeGrids(grids,2);}});layout.addComponent(button1);Button button2=new Button(this);button2.setText("←");button2.setTextAlignment(TextAlignment.CENTER);button2.setTextColor(Color.WHITE);button2.setTextSize(100);button2.setMarginTop(10);button2.setMarginLeft(400);button2.setPadding(10,0,10,0);button2.setBackground(background0);button2.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {changeGrids(grids,-1);}});layout.addComponent(button2);Button button3=new Button(this);button3.setText("→");button3.setTextAlignment(TextAlignment.CENTER);button3.setTextColor(Color.WHITE);button3.setTextSize(100);button3.setMarginLeft(600);button3.setMarginTop(-130);button3.setPadding(10,0,10,0);button3.setBackground(background0);button3.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {changeGrids(grids,1);}});layout.addComponent(button3);Button button4=new Button(this);button4.setText("↓");button4.setTextAlignment(TextAlignment.CENTER);button4.setTextColor(Color.WHITE);button4.setTextSize(100);button4.setMarginLeft(500);button4.setMarginTop(10);button4.setPadding(10,0,10,0);button4.setBackground(background0);button4.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {changeGrids(grids,-2);}});layout.addComponent(button4);drawGrids(grids);}

然后添加一个函数slideGrids()为布局layout添加一个滑动事件,并获取滑动开始与结束的坐标,并计算出大致的滑动方向,分别调用对应的changeGrids(grids,direction)函数实现空白方格周围对应位置的方格便会随之向对应的方向移动一格,并调用drawGrids(grids)函数用于绘制新的方阵,并在开头添加相应的变量

private float starX, starY, distanceX, distanceY;public void slideGrids(){layout.setTouchEventListener(new Component.TouchEventListener() {@Overridepublic boolean onTouchEvent(Component component, TouchEvent touchEvent) {MmiPoint point = touchEvent.getPointerScreenPosition(0);switch (touchEvent.getAction()) {case TouchEvent.PRIMARY_POINT_DOWN:starX = point.getX();starY = point.getY();break;case TouchEvent.PRIMARY_POINT_UP:distanceX = point.getX() - starX;distanceY = point.getY() - starY;break;}if (gameover() == false){if (Math.abs(distanceX) > Math.abs(distanceY)) {if (distanceX > 200) {changeGrids(grids,1);} else if (distanceX < -200) {changeGrids(grids,-1);}} else if (Math.abs(distanceX) < Math.abs(distanceY)){if (distanceY > 200) {changeGrids(grids,-2);} else if (distanceY < -200) {changeGrids(grids,2);}}}drawGrids(grids);return false;}});}

最后在initialize()函数中调用slideGrids()函数和drawButton()函数

public void initialize(){layout = new DirectionalLayout(this);grids = new int[][]{{1, 2, 3, 4}, {5, 6, 7, 8,}, {9, 10, 11, 12}, {13, 14, 15, 0}};createGrids(grids);slideGrids();drawButton();drawGrids(grids);
}

至此,这一部分完成了

实现游戏成功界面

点击“重新开始”按钮即会重新生成随意打乱的1至15的数字和一个空白方格的方阵,点击“返回”按钮即会切换到数字华容道的初始界面,经过若干次滑动或点击后,当所有的数字按顺序排列后,则会弹出游戏成功的界面,再滑动或点击也不会有任何变化。
在entry>src>main>java>com.example.myphoneapplication>slice>SecondAbilitySlice编写代码
首先定义一个函数drawText()用于绘制游戏成功字样

 public void drawText(){Text text=new Text(this);text.setText("游戏成功");text.setTextSize(100);text.setTextColor(Color.BLUE);text.setTextAlignment(TextAlignment.CENTER);text.setMarginsTopAndBottom(-2000,0);text.setMarginsLeftAndRight(350,0);layout.addComponent(text);setUIContent(layout);}

然后定义一个函数gameover()用于判断二维数组的数字是否按顺序排列,当二维数组的数字按顺序排列时返回true,否则返回false

public boolean gameover() {int[][] gameoverGrids = {{1, 2, 3, 4}, {5, 6, 7, 8,}, {9, 10, 11, 12}, {13, 14, 15, 0}};for (int row = 0; row < 4; row++) {for (int column = 0; column < 4; column++) {if (grids[row][column] != gameoverGrids[row][column]) {return false;}}}return true;}

再在drawButton()函数中重新开始按钮中添加一个响应点击事件的函数,用于调用函数initialize()实现重新生成随意打乱的1至15的数字和一个空白方格的方阵,返回按钮中添加一个响应点击事件的函数,用parsen函数返回数字华容道的初始界面,四个指示不同方向箭头的按钮的响应点击事件的函数中增加一个判断,当函数gameover()返回为false时才调用各自的changeGrids(grids,direction)函数,最后增加一个判断,当函数gameover()返回为true时调用函数drawText()

public void drawButton(){//部分代码没有贴出,可自行下载源代码查看button.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {initialize();}});button0.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {present(new SecondAbilitySlice(),new Intent());}});button1.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {if (gameover() == false){changeGrids(grids,2);}}});button2.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {if (gameover() == false){changeGrids(grids,-1);}}});button3.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {if (gameover() == false){changeGrids(grids,1);}}});button4.setClickedListener(new Component.ClickedListener() {@Overridepublic void onClick(Component component) {if (gameover() == false){changeGrids(grids,-2);}}});if(gameover()){drawText();}}

在函数slideGrids()函数中增加一个判断,当函数gameover()返回为false时才调用changeGrids(grids,direction)函数,最后增加一个判断,当函数gameover()返回为true时调用函数drawText()

public void slideGrids(){//部分代码没有贴出,可自行下载源代码查看if (gameover() == false){//{...}}if(gameover()){drawText();}}

至此,整个demo全部完成了。

源代码

源代码下载链接:源代码下载。

结语

以上就是数字华容道小游戏在手机的主要编写思路以及代码,源码将放在附件中,欢迎大家下载,感兴趣的读者可以自行跟着编写学习,相信你们也能够完成的。更多深鸿会深大小组学习项目可以查看荔园Harmony,如果有遇到什么问题,或者查找出其中的错误之处,或者能够优化代码和界面,也欢迎各位在评论区留言讨论,让我们一起学习进步!

从零开发HarmonyOS(鸿蒙)手机小游戏——数字华容道相关推荐

  1. 数字华容道java_从零开发HarmonyOS(鸿蒙)手机小游戏——数字华容道

    前言 2月16号HarmonyOS2.0手机开发者Beta版已经发布了,作为"1+8+N"战略的重要入口和生态核心,怎么能少得了手机应用开发呢,今天将由深鸿会深大学习小组(Zzt_ ...

  2. 鸿蒙小游戏-数字华容道 自定义组件的踩坑记录

    前两天看到HarmonyOS开发者官网上发布的一个挑战HarmonyOS分布式趣味应用的帖子,然后有个想法想搞一个小游戏出来,结果三天的时间都卡在了自定义组件上,使用了各种方式方法去实现功能,但是还是 ...

  3. 团队开发--手机小游戏 需求分析

    一.项目名称:手机小游戏 二.设计背景 我们团队认为现在是21世纪,人际关系往往能决定你的人生是一帆风顺还是坎坷不平. 相信大家都有这样的经历,同学或者各种关系聚会的时候,会有一些时间比较尴尬,不知道 ...

  4. 小白零基础搞unity手机跑酷游戏-01-GettingStarted

    小白零基础搞unity2D手机跑酷游戏-01-Getting Started 策划 键位 内容 准备工作 这是我第一次在CSDN上写博客,是想锻炼一下自己,也是对自己的一种激励吧,毕竟立了一个很大的f ...

  5. 手牵手,使用uni-app从零开发一款视频小程序 (系列上 准备工作篇)

    系列文章 手牵手,使用uni-app从零开发一款视频小程序 (系列上 准备工作篇) 手牵手,使用uni-app从零开发一款视频小程序 (系列下 开发实战篇) 前言 好久不见,很久没更新博客了,前段时间 ...

  6. html小游戏代码_研发实践:Mozilla分享如何开发一款WebVR小游戏

    文章相关引用及参考:mozvr 本文来自Mozilla的Josh Marinacci (映维网 2019年02月06日)在倡导新技术时,我总是尝试采用现实世界开发者的方式,而对于WebVR,开发一款游 ...

  7. 云开发谁是卧底线下小游戏发牌助手微信小程序源码-亲测可用

    云开发谁是卧底线下小游戏源码,发牌助手微信小程序源码. "谁是卧底OL"是一个非常有趣,风靡全国的比拼语言表述能力.知识面与想象力的游戏. 谁是卧底OL是一款由开发商北游科技倾力打 ...

  8. 视频教程-Layabox3D游戏开发入门-微信3D小游戏案例 -微信开发

    Layabox3D游戏开发入门-微信3D小游戏案例 有多年Unity程序开发经验,有策划和美术设计的经验.愿意在csdn这个平台和大家一起分享! 金龙 ¥29.00 立即订阅 扫码下载「CSDN程序员 ...

  9. 如何通过 LeanCloud 快速开发实时对战小游戏?

    实时对战是 LeanCloud 专门针对多人在线对战游戏推出的后端服务.开发者不需要自己搭建后端系统,利用云服务就可以轻松实现游戏内玩家匹配.在线对战消息同步等功能.本期直播课程我们将通过此服务来实现 ...

最新文章

  1. Matlab心得及学习方法(不断更新)
  2. spark shuffle内在原理说明
  3. linux下如何修改根口令
  4. BZOJ2738 矩阵乘法 【整体二分 + BIT】
  5. addeventlistener事件第三个参数_简析JavaScript 事件绑定、事件冒泡、事件捕获和事件执行顺序...
  6. linux下磁盘是硬盘吗,肿么确定linux系统上的硬盘哪个是主盘
  7. node项目正常启动后不能访问(防火墙未放行端口)
  8. # 遍历结构体_C#学习笔记05--枚举/结构体
  9. Python Flask实现修改和删除数据
  10. [ML]熵、KL散度、信息增益、互信息-学习笔记
  11. Android Binder通信机制
  12. 奥维地图电脑端手机端不能用了,有没有可替代的地图工具
  13. mysql报错1194_ERROR 1194 (HY000): Table 't1' is marked as crashed and should be repaired
  14. 矩阵分解在推荐系统中的应用及实践
  15. adb inputswipe shell_[Android]通过adb shell input上报命令模拟屏幕点击事件【转】
  16. 地球系统模式(CESM)应用
  17. Java后端面试必问:四十八道面试题及答案最新整理(速看速藏)
  18. 市场分析-全球与中国液态有机氢载体市场现状及未来发展趋势
  19. DB2 TSA资源查看
  20. Android 11 + 使用阿里“金融级实人认证方案”闪退

热门文章

  1. 力扣(LeetCode)怎么刷题,以排序算法为例
  2. win10下VMware安装CentOS7并配置网络
  3. mongodb查询后排序
  4. 数学学习在计算机研究领域的作用和重要性
  5. vue + sentry监控平台
  6. Python笔记相关
  7. 手机照片局部放大镜_如何为不识字的老年人挑选一款合适的智能手机
  8. 居民身份证阅读器产品开发学习心得(再谈标准-软件-协议)
  9. 软件的基本是要处理好”算法“及其基础(一)流-字-字符(包括某个数字、字母、符号和某个汉字等)-字符串-字节动态数组-字节-整数之间的转化关系和算法
  10. request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)