目录:
前言
概述
项目的创建
完成基本布局
把蛇、食物、地面绘制出来
让蛇动起来
吃到食物的判定
游戏的重新开始与计分
结语
源码包
前言
随着学习的深入,我们决定把经典游戏贪吃蛇移植到鸿蒙上,这篇文章用于记录学习中的感悟,也为了分享给对鸿蒙有兴趣的初学者们,希望在这个过程中能够相互交流、共同进步。
一同参与编写的还有:
mb5fa4e07864f6f
Linzijiandevx
Zy82243480
WeChat15820482064
概述
使用工具:DevEco Studio 下载地址:[https://developer.harmonyos.com/cn/develop/deveco-studio]
要完成贪吃蛇游戏,我们需要完成的工作有:
- 项目的创建
- 完成基本布局
- 把蛇、食物、地面绘制出来
- 让蛇动起来
- 吃到食物的判定
- 游戏的重新开始与计分
项目的创建
打开DevEco Studio,然后在左上角的file上选择new->new project创建新项目,为项目命名(不能有中文)。
我们要做的工作主要是修改下图的.hml,.js,.css文件:
完成基本布局
下面是我们这步要实现的效果图
首先我们在hml文件中把组件组织起来:
把原有div组件中的text组件的文字改为当前分数,把该text的class值设为score类,并动态绑定一个变量score,接着设立一个新的组件stack,class类值设为stack,在这个stack组件中放置一个canvas组件,class值设为canvas,ref值设为canvas。
在stack组件后面再添加一个input组件,type值为button,class值设为bit,value设为“重新开始”。
<div class="container">
<text class="score">
当前分数: {{score}}
</text>
<stack class="stack">
<canvas class="canvas" ref="canvas" ></canvas>
</stack>
<input type="button" value="重新开始" class="bit" onclick="reStart" />
</div>
然后我们在css文件中把hml中的要应用的class值设定好。
.container {
flex-direction: column;
justify-content: center;
align-items: center;
454px;
height: 454px;
}
.score {
font-size: 18px;
text-align:center;
300px;
height:20px;
letter-spacing:0px;
margin-button:5px;
}
.canvas{
align-items: center;
flex-direction: column;
320px;
height:320px;
background-color: #BBADA0;
}
.bit{
150px;
height:30px;
background-color:#AD9D8F;
font-size:24px;
margin-top:10px;
}
.stack{
305px;
height: 305px;
margin-top: 10px;
}
在js文件中,先设定score的值为0:
export default {
data: {
score:0
}
}
然后点击previewer可以看到我们要的预览效果。
把蛇、食物、地面绘制出来
在这一步中我们主要是对js文件进行修改:
首先我们初始化一下我们的矩阵,并定义蛇的初始位置(此处也可以让蛇随机生成,方法不唯一),初始化SX,SY数组与矩阵对应,建立与数字对应的颜色字典。
我们利用getContext函数用以得到绘图组件。
首先给边长和边距赋值,其次定义函数draw()用于绘制所有格子,编译行、列索引,并将行列索引获得的数字转换为字符串,然后赋值给变量gridStr。最后通过字典获得对应格子的颜色并赋值给context.fillStyle,并调用context.fillRect来绘制矩形(左上角X,左上角Y,长,宽)
const SIDELEN = 25; //总体布局大小(边长)
const MARGIN = 5; //总体布局大小(边距)
draw() {
for (let i = 0;i < 10; i++) {
for (let j = 0;j < 10; j++) {
let gridStr = map[i][j].toString();
let leftTopX = j * (MARGIN + SIDELEN) + MARGIN;
let leftTopY = i * (MARGIN + SIDELEN) + MARGIN;
context.fillStyle = CORLOR[gridStr];
context.fillRect(leftTopX,leftTopY,SIDELEN,SIDELEN);
}
}
},
绘制蛇和食物
首先定义各类常数和颜色
var SX;//蛇
var SY;//蛇
var GX = 2; //苹果的位置
var GY = 2; //苹果的位置
const CORLOR = {
"0": "#AD9D8F", //地面
"1": "#EEE4DA", //蛇头
"2": "#EEE32A", //蛇身
"3": "#F67C5F" //食物
}
然后用二维数组设置蛇和食物的初始位置,其中SX和SY的第一个元素,即0和1,代表蛇头的位置;第二个元素,即0和0,代表蛇身的位置。
initMap() {
map = [[2, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 3, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
SX = [0, 0];
SY = [1, 0];
},
设置用于初始化的函数。
onInit()分别初始化分数、蛇和十五的位置、蛇行走的方向,并隐藏“游戏结束”的字样。
onReady()为生命周期事件,通过this.$refs.canvas来获得组件canvas的对象实例,然后调用getContext()函数传入实参2d来获得2d绘制引擎,然后赋值给变量context。由于context可能会在其他地方用到,故声明其为全局变量。
onShow()设置蛇前进的速度以及调用绘制蛇、食物、地面的函数。
总的代码如下:
var map //地图
var SX;//蛇
var SY;//蛇
var GX = 2; //苹果的位
var GY = 2; //苹果的位置
var context;
const SIDELEN = 25; //总体布局大小
const MARGIN = 5; //总体布局大小
const CORLOR = {
"0": "#AD9D8F", //地面
"1": "#EEE4DA", //蛇头
"2": "#EEE32A", //蛇身
"3": "#F67C5F" //食物
}
export default {
data: {
score: 0,
isshow: false
},
onInit() {//代表初始化
this.score=0;
this.initMap();
Xstep = 0;
Ystep = 1;
GX = 2;
GY = 2;
clearInterval(timer);
this.isshow=false;
},
onReady() {//程序的准备
context = this.$refs.canvas.getContext('2d');
},
onShow() {//游戏界面的展示
timer = setInterval(this.run,500);
this.draw();
},
initMap() {
map = [[2, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 3, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
SX = [0, 0];
SY = [1, 0];
},
draw() {
for (let i = 0;i < 10; i++) {
for (let j = 0;j < 10; j++) {
let gridStr = map[i][j].toString();
let leftTopX = j * (MARGIN + SIDELEN) + MARGIN;
let leftTopY = i * (MARGIN + SIDELEN) + MARGIN;
context.fillStyle = CORLOR[gridStr];
context.fillRect(leftTopX,leftTopY,SIDELEN,SIDELEN);
}
}
},
效果图如下:
作者:Linzijiandevx
想了解更多内容,请访问: 51CTO和华为官方战略合作共建的鸿蒙技术社区https://harmonyos.51cto.com