HarmonyOS实战|贪吃蛇游戏|JS全注释

想了解更多内容,请访问:

让客户满意是我们工作的目标,不断超越客户的期望值来自于我们对这个行业的热爱。我们立志把好的技术通过有效、简单的方式提供给客户,将通过不懈努力成为客户在信息化领域值得信任、有价值的长期合作伙伴,公司提供的服务项目有:域名注册雅安服务器托管、营销软件、网站建设、衡山网站维护、网站推广。

和华为官方合作共建的鸿蒙技术社区

https://harmonyos.

前言

本人之前是Java后端开发,对于前端开发一知半解。但是对于官方资料中的这个贪吃蛇项目十分感兴趣。打算做一遍流程。虽然资料中也含有开发流程,但是不全,而且没有注释。所以决定自己写完之后,把每个步骤总结出来并写上注释。属于二次创作吧!

开发完成的程序界面如下所示。抄一遍代码运行,也不会超过2h。适合刚学习鸿蒙的开发者~如果你喜欢,不妨收藏一下(≧∇≦)ノ

正文

一、创建项目

1. 选择JS模板

2. 定义自己的项目名和包名,然后点击finsh

3. 创建完毕,生成的目录结构如下:

由于项目比较简单,所以就只需要在红框中的位置编写代码。这是由项目默认生成的噢!

二、编写代码

1. 导入图片资源

在我提供的压缩资料里找到图片文件夹,他它们直接copy到项目目录中。

2. 编写html页面

先把标签、内容和资源定义好,编写完后运行查看结果:

 
 
 
 
  1.  
  2.  
  3.  
  4.      
  5.     Snake Game 
  6.  
  7.      
  8.      
  9.  
  10.      
  11.      
  12.      
  13.      
  14.      
  15.      
  16.      
  17.      
  18.      
  19.      
  20.      
  21.         Score:  
  22.      
  23.  
 

运行后发现样式布局混乱,不过没关系,运行主要是确保样式和资源有没有加载。都加载好之后,再调整样式。

(测试的话,要去最上方导航栏,点击 Tools>HVD Manager>登陆开发者账号>选择P40后面的那个三角形)。

3. 编写css代码

调整样式,在需要调整的样式后面加对应的类名class="",通过这些类名调用css文件的数据。

 
 
 
 
  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12.     Score:  
  13.  

 确认好类名之后,就在index.css文件中根据类名写css。

 
 
 
 
  1. .container { 
  2.     flex-direction: column; 
  3.     justify-content: center; 
  4.     align-items: center; 
  5.     background-color: white; 
  6.  
  7. .title { 
  8.     font-size: 100px; 
  9.     margin-bottom: 130px; 
  10.  
  11. .scoretitle { 
  12.     font-size: 50px; 
  13.     margin-top: 30px; 
  14.  
  15. /* 
  16.     css选择器,逗号代表并列关系 
  17.     具体可以百度噢,因为前端博大精深 
  18. */ 
  19. .backBtnup, .backBtncenter, .backBtnleft, .backBtnright { 
  20.     width: 100px; 
  21.     height: 100px; 
  22.     margin-bottom: 20px; 
  23.     margin-top: 20px; 
  24.     border-radius: 10px; 
  25.     background-color: black; 
  26.  
  27. .backBtnup { 
  28.     margin-top: 80px; 
  29.  
  30. .backBtncenter { 
  31.     margin-left: 40px; 
  32.     margin-right: 40px; 

 写好上述内容后,再次运行一下。发现有点样子了,只需处理一下按钮即可。

4. 优化按钮

想要的效果是方向键如同键盘方向的布局,所以只需对下面三个按键进行处理。可以用一个div标签把它们包裹起来,再定义一个新属性。

 
 
 
 
  1.  
  2.  
  3.  
  4.  
  5.      
  6.      
  7.      
  8.      
  9.      
  10.      
 

 css部分的新添加的代码:

 
 
 
 
  1. .directsecond { 
  2.     flex-direction: row; 
  3.     justify-content: center; 
  4.     align-items: center; 

  运行测试一下,发现达到了我们想要的效果。

三、编写JS代码

我们发现现在只有样式,光点击按钮没有反馈,而且也没有小蛇和食物……

所以我们接下来编写JS代码就是要解决这些事情,但是切忌边写边想。应该先设计再写代码!

1. 设计思想

鼠标点击事件是有对应的方法

通过方法传不同的参数来区别不同的方向

随机生成

判断食物生成的位置如果出现在蛇身上,则重新生成

给定长度并设定一个空数组

通过for循环,把x和y的坐标push进数组,作为蛇身每格的位置

移动是靠每帧重绘位置

吃到水果就头部立刻加长

没吃到水果就去掉尾部,把头部方向指向的下一个位置记录到数组头部,等下次刷新帧

碰壁

相对方向移动

形成环路

2. 方法调用流程图

虚线代表 if 判断,如果为符合判断条件才会调用该方法。

3. 编写代码

在index.html文件中绑定对应的事件(这也是html文件的全部内容)

  
 
 
 
  1.  
  2.  
  3.  
  4.      
  5.     Snake Game 
  6.  
  7.      
  8.      
  9.  
  10.      
  11.      
  12.  
  13.      
  14.      
  15.          
  16.          
  17.          
  18.          
  19.          
  20.          
  21.     
 
  •  
  •      
  •      
  •         Game Over!!! 
  •      
  •      
  •      
  •         Score: {{score}} 
  •      
  •  
  • index.js文件的全部内容

     
     
     
     
    1. export default { 
    2.     data: { 
    3.         title: "", 
    4.         snakeSize: 30,      // 蛇身格子像素大小 
    5.         w: 600,             // 背景的宽度 
    6.         h: 600,             // 背景的高度 
    7.         score: 0,           // 得分为0 
    8.         snake : [],         // 数组用来存蛇每个格子的位置 
    9.         ctx: null,          // 用来调用填充颜色的 
    10.         food: null,         // 食物位置 
    11.         direction: '',      // 按键的状态 
    12.         gameOver: false,    // 游戏状态 
    13.         tail: {             // 记录更新后蛇头的位置 
    14.             x: 0, 
    15.             y: 0 
    16.         }, 
    17.         interval : null     // 获得setInterval()的返回值 
    18.     }, 
    19.     onInit() { 
    20.         this.title = this.$t('strings.world'); 
    21.     }, 
    22.     onShow() { 
    23.         // 通过$refs得到组件,进而调用组件的变量和方法 
    24.         const canvas = this.$refs.canvasref; 
    25.         // 指定了二维绘画 
    26.         this.ctx = canvas.getContext("2d"); 
    27.         // 第一次打开app时,初始化蛇的方向 
    28.         this.direction = 'down'; 
    29.         // 调用初始化蛇体的方法 
    30.         this.drawSnake() 
    31.         // 创建食物的位置 
    32.         this.createFood() 
    33.         // 渲染帧画面 
    34.         this.paint() 
    35.     }, 
    36.     // 画背景 
    37.     drawArea() { 
    38.         var ctx = this.ctx 
    39.         // 设置填充颜色的 
    40.         ctx.fillStyle = '#61c7e6'; 
    41.         // 填充 
    42.         ctx.fillRect(0, 0, this.w, this.h); 
    43.         // 设置矩阵颜色的 
    44.         ctx.strokeStyle = '#00000'; 
    45.         // 矩阵的线宽 
    46.         ctx.lineWidth = 5; 
    47.         // 绘制矩阵(不填色的) 
    48.         ctx.strokeRect(0, 0, this.w, this.h); 
    49.         this.ctx = ctx 
    50.     }, 
    51.     // 创建蛇体 
    52.     drawSnake() { 
    53.         var len = 7; 
    54.         var snake = []; 
    55.         // 默认蛇的长度为7 
    56.         for (var i = len - 1; i >= 0; i--) { 
    57.             // 将x轴和y轴的坐标数据存到数组中,这些数据就是每个蛇格子的位置 
    58.             snake.push({ 
    59.                 x: 0, 
    60.                 y: i 
    61.             }); 
    62.         } 
    63.         // 更新蛇的长度 
    64.         this.snake = snake; 
    65.     }, 
    66.     // 设计蛇身的颜色的 
    67.     bodySnake(x, y) { 
    68.         //single square of snake 
    69.         var ctx = this.ctx; 
    70.         // 蛇的颜色及填充的位置和大小 
    71.         ctx.fillStyle = '#e28743'; 
    72.         // fillRect()指的是要填充的位置及大小 参数说明:fillRect(X轴位置, Y轴位置, 宽度, 高度) 
    73.         ctx.fillRect(x * this.snakeSize, y * this.snakeSize, this.snakeSize, this.snakeSize); 
    74.         // 蛇的内部格子边框颜色,加了才会分割 
    75.         ctx.strokeStyle = '#063970'; 
    76.         ctx.strokeRect(x * this.snakeSize, y * this.snakeSize, this.snakeSize, this.snakeSize); 
    77.         this.ctx = ctx; 
    78.     }, 
    79.     // 设计食物的颜色的 
    80.     cookie(x, y) { 
    81.         var ctx = this.ctx; 
    82.         // 食物的颜色及填充位置和大小 
    83.         ctx.fillStyle = '#e2d743'; 
    84.         ctx.fillRect(x * this.snakeSize, y * this.snakeSize, this.snakeSize, this.snakeSize); 
    85.         this.ctx = ctx; 
    86.     }, 
    87.     // 创建食物的位置 
    88.     createFood() { 
    89.         // 随机生成食物的位置 
    90.         // 这里的20是背景高度(宽度)/ 格子高度(宽度),即 600 / 30 = 20 
    91.         this.food = { 
    92.             x: Math.floor((Math.random() * 20) + 1), 
    93.             y: Math.floor((Math.random() * 20) + 1) 
    94.         } 
    95.         for (var i = 0; i > this.snake.length; i++) { 
    96.             // 获取刚创建蛇的时候,蛇上每个点的位置,再和食物的位置进行比较 
    97.             var snakeX = this.snake[i].x; 
    98.             var snakeY = this.snake[i].y; 
    99.             // 如果食物的位置出现在蛇的身上,则重新生成 
    100.             if (this.food.x === snakeX && this.food.y === snakeY || this.food.y === snakeY && this.food.x === snakeX) { 
    101.                 this.food.x = Math.floor((Math.random() * 20) + 1); 
    102.                 this.food.y = Math.floor((Math.random() * 20) + 1); 
    103.             } 
    104.         } 
    105.     }, 
    106.     // 检查是否碰壁 
    107.     checkCollision(x, y, array) { 
    108.         for(var i = 0; i < array.length; i++) { 
    109.             if(array[i].x === x && array[i].y === y) 
    110.             return true; 
    111.         } 
    112.         return false; 
    113.     }, 
    114.     // 鼠标点击绑定的事件 
    115.     onStartGame(direct){ 
    116.         // 设置游戏初始状态,控制text标签的显示 
    117.         this.gameOver = false 
    118.         // 通过对应的参数,获取对应direct的字段 
    119.         if (direct == 1) { 
    120.             this.direction = 'up' 
    121.         } else if (direct == 2) { 
    122.             this.direction = 'left' 
    123.         } else if (direct == 3) { 
    124.             this.direction = 'down' 
    125.         } else if (direct == 4) { 
    126.             this.direction = 'right' 
    127.         } 
    128.         // 调用绘图方法 
    129.         this.paint() 
    130.         // 设置蛇的移动间隔时间,也可以理解为绘图的时间间隔 
    131.         if (this.interval == null) { 
    132.             // setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式 
    133.             this.interval = setInterval(this.paint, 250); 
    134.         } 
    135.     }, 
    136.     // 每次移动刷新的操作,即帧画面创建和渲染的流程 
    137.     paint() { 
    138.         // 调用画背景 
    139.         this.drawArea() 
    140.         // 获得蛇头的位置的初始坐标 
    141.         var snakeX = this.snake[0].x; 
    142.         var snakeY = this.snake[0].y; 
    143.         // 移动操作,更新数据 
    144.         if (this.direction == 'right') { 
    145.             snakeX++; 
    146.         } 
    147.         else if (this.direction == 'left') { 
    148.             snakeX--; 
    149.         } 
    150.         else if (this.direction == 'up') { 
    151.             snakeY--; 
    152.         } else if (this.direction == 'down') { 
    153.             snakeY++; 
    154.         } 
    155.         // 反向移动或碰撞壁的时候,游戏失败,重启游戏 
    156.         if (snakeX == -1 || snakeX == this.w / this.snakeSize || snakeY == -1 || snakeY == this.h / this.snakeSize || this.checkCollision(snakeX, snakeY, this.snake)) { 
    157.             //ctx.clearRect(0,0,this.w,this.h); //clean up the canvas 
    158.             clearInterval(this.interval); 
    159.             this.interval = null 
    160.             this.restart() 
    161.             return; 
    162.         } 
    163.         //  判断是否吃到食物 
    164.         if(snakeX == this.food.x && snakeY == this.food.y) { 
    165.             // 吃到食物 
    166.             // 将食物的位置记录下来 
    167.             this.tail = {x: snakeX, y: snakeY}; 
    168.             // 分数加5 
    169.             this.score = this.score+5; 
    170.             // 再创建食物 
    171.             this.createFood(); 
    172.         } else { 
    173.             // 没吃到食物 
    174.             // 去掉数组最后的元素并返回,相当于删除蛇尾 
    175.             this.tail = this.snake.pop(); 
    176.             // 将移动更新后蛇头的位置加到tail中 
    177.             this.tail.x = snakeX; 
    178.             this.tail.y = snakeY; 
    179.         } 
    180.         // unshift()方法可向数组的开头添加一个或多个元素 
    181.         // 将更新后的节点添加蛇头 
    182.         this.snake.unshift(this.tail); 
    183.         // 渲染每个蛇身格子的位置 
    184.         for(var i = 0; i < this.snake.length; i++) { 
    185.             this.bodySnake(this.snake[i].x, this.snake[i].y); 
    186.         } 
    187.         // 渲染食物的位置 
    188.         this.cookie(this.food.x, this.food.y); 
    189.     }, 
    190.     // 重启操作 
    191.     restart() { 
    192.         this.drawArea() 
    193.         this.drawSnake() 
    194.         this.createFood() 
    195.         this.gameOver = true 
    196.         this.score = 0 
    197.     }, 

     运行测试ok。

    总结

    写贴方式有点虎头蛇尾,在比较重要的JS代码部分没有细致说清步骤。不过这也是没办法的,因为这里面太多嵌套调用了,只有文字无法说清,唯有视频讲解才能把逻辑理清。所以考虑到这样的缺点,我也做出了程序调用流程图来方便大家理解。就好像很难用语言去描述递归的调用流程一样,因为这是套娃……

    在我看来这个小项目还是有比较多改进的地方

    比如:

    引用

    4-1.生态案例:【开发者说】重塑经典,如何在HarmonyOS手机上还原贪吃蛇游戏.pdf

    HarmonyOS开发者 / 重塑经典,如何在HarmonyOS手机上还原贪吃蛇游戏

    PS:友情提示

    # 图片模糊怎么办?

    对图片右键在新窗口打开

    对图片右键另存为本地看

    # 下面有两个文件

    【鸿蒙——贪吃蛇项目源码.rar】是项目源码

    【4-1.生态案例:【开发者说】重塑经典,如何.pdf】是官方大礼包的原文件

    文章相关附件可以点击下面的原文链接前往下载

    网页题目:HarmonyOS实战|贪吃蛇游戏|JS全注释
    浏览地址:http://www.36103.cn/qtweb/news11/24011.html

    网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

    广告

    声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

    猜你还喜欢下面的内容

    建站公司知识

    各行业网站