当前位置:   article > 正文

【案例分享】重塑经典,如何在 HarmonyOS 手机上还原贪吃蛇游戏

【案例分享】重塑经典,如何在 HarmonyOS 手机上还原贪吃蛇游戏
        通过 JS 模板在 HarmonyOS 手机上一步步开发呈现,简单有趣的小游戏 demo,希望给你的
HarmonyOS 开发之旅多一点启发。
        贪吃蛇,一款经典的小游戏,勾起了多少人的童年回忆。小时候,我们在游戏中快乐玩耍,
现如今,让我们在开发中慢慢回溯吧!
        在游戏中,玩家须通过导航按钮控制蛇的运动,以便吃掉随机出现的食物,来获得相应积分
并增加蛇身长度,当蛇发生碰撞或反向移动时,则游戏结束。首先,让我们一起梳理一下开
发的要点:
  1.  绘制固定组件:包括画布、导航按钮、得分栏等内容的绘制
  2. 设计动态组件:包括蛇体与食物的形状、大小、颜色的设计
  3. 动态规则:设定食物随机出现的位置,蛇的运动方式及形态
  4. 运行机制:当蛇消耗食物后,增加积分和蛇的长度,并绘制新的食物
  5. 违规判定:当蛇碰撞到自身或画布边缘,或者反向移动,则判定违规,提示用户“game
    over”,并自动重新开始游戏
        在正式开始敲代码之前,开发者们需要先下载安装 Huawei DevEco Studio,如果对于这个
流程不甚熟悉,可以参照官网的教程操作。
下面我们就进入项目开发环节,逐一攻破以上要点,一起探寻贪吃蛇之旅:

创建项目

        打开 DevEco Studio,创建新项目(New Project),选择 Phone 设备,点击 Empty Feature
Ability (JS)模板,注意项目命名须不带中文或特殊字符(如此处的 MyPhoneGame),最
后点击 Finish。
项目创建后,我们先了解一下目录结构:
  • index.hml 文件:描述页面布局
  • index.css 文件:描述页面样式
  • index.js 文件:处理页面和用户之间的交互
  • app.js 文件:管理全局 JavaScript 逻辑和应用程序生命周期
  • pages 目录:存储所有组件页面
  • java 目录:存放与项目相关的 java 文件
其中,app.js 文件、pages 目录和 java 目录内容均由 JS 模板自动提供。

1)绘制固定组件

① 绘制画布,在 index.hml 文件中,设定画布的颜色和尺寸;
index.hml:
  1. <div class="container" onswipe="touchMove">
  2. <text class="title">Snake Game</text>
  3. <canvas ref="canvasref" style="width: 600px; height: 600px;
  4. background-color:#000000" >
  5. </canvas>
  6. </div>
在 index.css 文件中,可以描述画布的呈现样式;
  1. .container {
  2. flex-direction: column;
  3. justify-content: center;
  4. align-items: center;
  5. background-color: #d6d8d8;
  6. }
在 index.js 文件中,引用画布$refs.canvasref,保障画布被蛇和食物图像填充。
  1. const canvas = this.$refs.canvasref;
  2. this.ctx = canvas.getContext("2d")
② 绘制导航按钮,我们先在 entry/src/main/js/default/common 目录下,添加 png
格式的导航按钮图片。
然后,在 index.hml 文件中,创建“上下左右”四个导航按钮,并将方向保存在变量
“this.direction”中;
  1. <image src='/common/up.png' class="backBtnup"
  2. onclick="onStartGame(1)"></image>
  3. <div class="directsecond">
  4. <image src='/common/left.png' class="backBtnleft"
  5. onclick="onStartGame(2)"></image>.
  6. <image src='/common/down.png' class="backBtncenter"
  7. onclick="onStartGame(3)"></image>
  8. <image src='/common/right.png' class="backBtnright"
  9. onclick="onStartGame(4)"></image>
  10. </div>
在 index.css 文件中,设置导航按钮大小、位置、边框和颜色等参数;
  1. .backBtnup, .backBtncenter, .backBtnleft, .backBtnright {
  2. width: 100px;
  3. height: 100px;
  4. margin-bottom: 20px;
  5. margin-top: 20px;
  6. border-radius: 10px;
  7. background-color: #000000;
  8. }
  9. .directsecond {
  10. flex-direction: row;
  11. justify-content: center;
  12. align-items: center;
  13. }
  14. .backBtnup {
  15. margin-top: 80px;
  16. }
  17. .backBtncenter {
  18. margin-left: 40px;
  19. margin-right: 40px;
  20. }
在 index.js 文件中,通过 if 判断,调用“this.direction”,实现导航按钮控制蛇的运动方
向。
  1. onStartGame(direct){
  2. if (direct == 1) {
  3. this.direction = 'up'
  4. } else if (direct == 2) {
  5. this.direction = 'left'
  6. } else if (direct == 3) {
  7. this.direction = 'down'
  8. } else if (direct == 4) {
  9. this.direction = 'right'
  10. }
  11. },
③ 在 index.hml 文件中,创建“得分”名称;在 index.css 文件中,设置“得分栏”大小
和顶部边距; 在 index.js 文件中,设定原始得分为“0”
<text if="{{!gameOver}}"class="scoretitle">Score: {{score}}</text>
  1. .scoretitle {
  2. font-size: 50px;
  3. margin-top: 30px;
  4. }
  1. //index.js
  2. data: {
  3. title: "",
  4. snakeSize: 10,
  5. w: 600,
  6. h: 600,
  7. score: 0,
  8. snake : [],
  9. ctx: null,
  10. food: null,
  11. direction: '',
  12. gameOver: false,
  13. tail: {
  14. x: 0,
  15. y: 0
  16. },

2)设计动态组件

接下来,我们在 index.js 文件中创建蛇体,设定蛇的初始位置(0,0),蛇的长度为 10
  1. drawSnake() {
  2. var len = 7;
  3. var snake = [];
  4. for (var i = len - 1; i >= 0; i--) {
  5. snake.push({
  6. x: 0,
  7. y: i
  8. });
  9. }
  10. this.snake = snake;
  11. },
在 index.js 文件中,为蛇绘制食物,设定食物的颜色和风格。
  1. cookie(x, y) {
  2. var ctx= this.ctx;
  3. ctx.fillStyle = '#e28743';
  4. ctx.fillRect(x * this.snakeSize, y * this.snakeSize, this.snakeSize, this.snakeSize);
  5. //border color of the cookie
  6. ctx.fillStyle = '#e28743';
  7. ctx.fillRect(x * this.snakeSize + 1, y * this.snakeSize + 1, this.snakeSize- 2,
  8. this.snakeSize - 2);
  9. this.ctx = ctx;
  10. }

3)动态规则

        在 index.js 文件中,我们通过随机函数 Math.random(),设定食物位置的随机值,同时须
加 if 判断,以确保食物不会出现在蛇的身体上。
  1. createFood() {
  2. this.food = {
  3. x: Math.floor((Math.random() * 30) + 1),
  4. y: Math.floor((Math.random() * 30) + 1)
  5. }
  6. for (var i = 0; i > this.snake.length; i++) {
  7. var snakeX = this.snake[i].x;
  8. var snakeY = this.snake[i].y;
  9. if (this.food.x === snakeX && this.food.y === snakeY || this.food.y ===
  10. snakeY && this.food.x === snakeX) {
  11. this.food.x = Math.floor((Math.random() * 30) + 1);
  12. this.food.y = Math.floor((Math.random() * 30) + 1);
  13. }
  14. }
  15. }
在 index.js 文件中,我们可以设定蛇自动跑,每跑一步的时间间隔为“500”。
 
  1. var ctx = this.ctx;
  2. ctx.fillStyle = '#e28743';
  3. ctx.fillRect(x * this.snakeSize, y * this.snakeSize, this.snakeSize, this.snakeSize);
  4. //border color of snake
  5. ctx.strokeStyle = '#063970';
  6. ctx.strokeRect(x * this.snakeSize, y * this.snakeSize, this.snakeSize, this.snakeSize);
  7. this.ctx = ctx;

 在 index.js 文件中,判断按键导航的方向,并沿此方向增加蛇头,减少蛇尾。

  1. if (this.direction == 'right') {
  2. snakeX++;
  3. }
  4. else if (this.direction == 'left') {
  5. snakeX--;
  6. }
  7. else if (this.direction == 'up') {
  8. snakeY--;
  9. } else if (this.direction == 'down') {
  10. snakeY++;
  11. }

4)运行机制

在 index.js 文件中,我们设定每当蛇消耗食物后,“得分栏”就增加 5 分;
  1. if(snakeX == this.food.x && snakeY== this.food.y) {
  2. this.tail = {x: snakeX, y: snakeY}; //Create a new head instead of moving thetail
  3. this.score = this.score+5;
  4. this.createFood(); //Create new food
  5. } else {
  6. this.tail = this.snake.pop(); //pops out the last cell
  7. this.tail.x = snakeX;
  8. this.tail.y = snakeY;
  9. }

与此同时,增加蛇的长度,并绘制新的食物。

  1. //index.js
  2. this.snake.unshift(this.tail); //putsback the tail as the first cell
  3. for(var i = 0; i < this.snake.length; i++) {
  4. this.bodySnake(this.snake[i].x, this.snake[i].y);
  5. }
  6. this.cookie(this.food.x, this.food.y);

5)违规判定

我们设定假如蛇碰撞自身或画布边缘,或者反向移动,则判定违规,提示用户“game over”,
并自动重新开始游戏。
在 index.js 文件中,检查蛇是否碰撞自身或画布边缘:
  1. checkCollision(x, y, array) {
  2. for(var i = 0; i < array.length; i++) {
  3. if(array[i].x === x && array[i].y === y)
  4. return true;
  5. }
  6. return false;
  7. }
在 index.js 文件中,检查蛇是否反向移动:
  1. if (snakeX == -1 || snakeX == this.w / this.snakeSize ||snakeY == -1 || snakeY
  2. ==this.h / this.snakeSize ||this.checkCollision(snakeX, snakeY, this.snake)) {
  3. ctx.clearRect(0,0,this.w,this.h); //cleanup the canvas
  4. this.restart()
  5. return;
  6. }
在 index.hml 文件中,设定当游戏结束时,得分栏显示“game over”;在 index.js 文件
中,设定重启游戏,重新绘制区域、蛇和食物,得分清零:
<text if="{{gameOver}}" class="scoretitle">Game Over!!</text>
  1. //index.js
  2. restart() {
  3. this.drawArea()
  4. this.drawSnake()
  5. this.createFood()
  6. this.gameOver = true
  7. this.score = 0
  8. },
到此,我们已经完成了贪吃蛇游戏的开发啦!
最终实现的效果,奥利给
回顾整个开发过程,难点在于当蛇消耗食物后,增加得分及蛇的长度,同时随机出现新的食
物,如何判定违规并提示等方面,当我们一步步实操起来,所有难题都会迎刃而解。
代码开发者:Kiruba Pradeep, Tech Lead, currentlybased at L&T Technology Services
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/274658
推荐阅读
相关标签
  

闽ICP备14008679号