#夏日挑战赛# HarmonyOS - 基于ArkUI(JS)实现打地鼠游戏
Posted 开源基础软件社区官方
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了#夏日挑战赛# HarmonyOS - 基于ArkUI(JS)实现打地鼠游戏相关的知识,希望对你有一定的参考价值。
作者 : 尹宝荣
前言
初学 HarmonyOS ArkUI(JS) ,对于FA的开发还是不太熟悉,单纯看文档,不使用起来的话,始终掌握不了,代码还是要多敲多思考才能进步。所以周末突发奇想利用HarmonyOS 写了一个简单的打地鼠游戏。
实现效果
游戏说明
点击开始按钮之后,顶部剩余时间会从60秒开始倒计时,命中数和得分数清0,同时格子中会随机出现地鼠,点击格子出现锤子敲击地鼠,打中地鼠之后命中数+1,分数根据难度相应增加。难度分为四个星级,玩家可以根据自己的手速选择相应难度,难度越高击中得分越高,地鼠消失的间隔时间越短。60秒倒计时结束之后,地鼠不再出现,弹框提示游戏结束,并显示最终得分。
项目说明
主要用到知识:animation,倒计时,HarmonyOS 基础组件
图片来源: iconfont-阿里巴巴矢量图标库
实现步骤
-
绘制4x4的格子,每个格子中有一张地鼠的图片和一张锤子的图片,都默认隐藏。锤子的图片定位在地鼠头上
-
点击开始按钮的时候
-
开始60秒倒计时
- 每隔一段时间随机显示一张地鼠图片,根据难度显示几秒后隐藏
-
-
点击“地鼠”时
-
锤子出现并有一个向下打击的animation动画效果
- 根据当前格子中地鼠的图片和锤子的图片是否显示,判断是否打中地鼠
-
-
如果打中地鼠,命中次数+1,得分相应增加
-
难度切换后,命中单个地鼠的得分改变,地鼠消失的时间间隔改变
- 60秒倒计时结束后,游戏结束,地鼠不再出现,倒计时停止,弹框提示得分
代码实现
1. hml部分
1.1 最上面是一些计数信息数据,用到了 input 组件
<div class="container">
<!-- 头部计数信息模块-->
<div class="game-title">
<text class="title-text">打地鼠游戏</text>
</div>
<div class="header-info">
<!-- 剩余 -->
<div class="input-box">
<text class="input-title">剩余:</text>
<input class="input" type="text" value=" timeInt "></input>
<text class="input-unit">秒</text>
</div>
<!-- 命中 -->
<div class="input-box">
<text class="input-title">命中:</text>
<input class="input" type="text" value=" countInt "></input>
<text class="input-unit">个</text>
</div>
<!-- 共计 -->
<div class="input-box">
<text class="input-title">共计:</text>
<input class="input" type="text" value=" scoreInt "></input>
<text class="input-unit">分</text>
</div>
1.2 难度星级设定,用到了 rating 组件
<!-- 难度选择-->
<div class="hard-container">
<text class="input-title">难度设定:</text>
<rating numstars="4" rating=" hardRating " stepsize="1" @change="changeRating" id="rating">
</rating>
</div>
<!-- 过关分数说明 -->
<div class="pass-score">
<text class="pass-text">当前难度: hardRating 星 命中单个得分: passScore 分</text>
</div>
</div>
附表:rating组件的属性和事件
1.3 打地鼠的格子区域 ,是用数据for循环出来的,写的时候没有考虑周全,代码有一些冗余,感兴趣的伙伴可以把这块代码重构一下,看起来会更简洁
<!-- 打地鼠区域 -->
<div class="game-area">
<!-- 第1行-->
<div class="game-tr1">
<div class="game-td" for="item in trOne[0]" on:click="showHammer( item )">
<image class="hammer-pic cover" id=" item.idValue " src="common/images/hammer.png"
show=" item.showHammer ">
</image>
<image class="game-pic cover" src="common/images/dishu.png" show=" item.showMose ">
</image>
</div>
</div>
<!-- 第2行 -->
<div class="game-tr1">
<div class="game-td" for="item in trOne[1]" on:click="showHammer( item )">
<image class="hammer-pic cover" id=" item.idValue " src="common/images/hammer.png"
show=" item.showHammer ">
</image>
<image class="game-pic cover" src="common/images/dishu.png" show=" item.showMose ">
</image>
</div>
</div>
<!-- 第3行 -->
<div class="game-tr1">
<div class="game-td" for="item in trOne[2]" on:click="showHammer( item )">
<image class="hammer-pic cover" id=" item.idValue " src="common/images/hammer.png"
show=" item.showHammer ">
</image>
<image class="game-pic cover" src="common/images/dishu.png" show=" item.showMose ">
</image>
</div>
</div>
<!-- 第4行 -->
<div class="game-tr1 last-tr">
<div class="game-td" for="item in trOne[3]" on:click="showHammer( item )">
<image class="hammer-pic cover" id=" item.idValue " src="common/images/hammer.png"
show=" item.showHammer ">
</image>
<image class="game-pic cover" src="common/images/dishu.png" show=" item.showMose ">
</image>
</div>
</div>
</div>
1.4 开始按钮和弹框,用到了 button 组件和 dialog 组件
<!-- 开始按钮 -->
<div class="btn-area">
<button class="btn-start" value="开始" on:click="startGame">
</button>
</div>
<!-- 提示框 -->
<dialog id="hintDialog" style="margin-bottom : 50%;">
<div class="dialog-div">
<div class="inner-txt">
<text class="txt">GAME OVER</text>
</div>
<text class="text">游戏得分: scoreInt </text>
<div class="inner-btn">
<button type="text" value="确定" onclick="closeDialog" class="btn-txt"> </button>
</div>
</div>
</dialog>
</div>
2. css部分
.container
padding-top: 20px;
flex-direction: column;
/*头部信息样式*/
.game-title
display: flex;
justify-content: center;
color: chocolate;
margin-bottom: 20px;
.header-info
flex-direction: column;
.input-title
font-size: 18px;
.input
width: 100px;
height: 30px;
.input-unit
font-size: 18px;
margin-left: 8px;
.input-box
margin-bottom: 14px;
margin-left: 20px;
/*难度系数选择样式*/
.hard-container
margin-left: 20px;
margin-bottom: 15px;
rating
width: 160px;
height: 40px;
.pass-score
margin-left: 20px;
.pass-text
font-size: 16px;
color: mediumblue;
/*游戏区域样式*/
.game-area
border: 1px solid black;
flex-direction: column;
margin: 20px;
background-color: lightgreen;
.game-tr1
height: 80px;
border-bottom: 1px solid black;
.last-tr
border-bottom: none;
flex: 1;
.game-td
position: relative;
width: 80px;
height: 80px;
border-right: 1px solid black;
display: flex;
justify-content: center;
align-items: center;
.game-pic
width: 85%;
height: 85%;
.hammer-pic
position: absolute;
top: 0px;
left: 20px;
width: 60px;
height: 60px;
z-index: 99;
/*按钮样式*/
.btn-area
display: flex;
justify-content: center;
margin-top: 10px;
.btn-start
width: 100px;
height: 30px;
/*弹框样式*/
.dialog-div
flex-direction: column;
align-items: center;
.area
width: 88%;
border-radius: 5px;
.inner-txt
width: 80%;
height: 100px;
align-items: center;
flex-direction: column;
justify-content: space-around;
.txt
font-size: 18px;
color: #000000;
font-weight: bold;
.text
font-size: 16px;
.inner-btn
width: 80%;
height: 100px;
align-items: center;
justify-content: space-around;
3. js部分
export default
data:
timeInt: 60, //剩余时间
countInt: 0, //命中个数
scoreInt: 0, //得分
animation: , //敲击动画
//地鼠数据
trOne: [
[
tr: 1,
id: 1,
idValue: A1,
showHammer: false,
showMose: false
,
tr: 1,
id: 2,
idValue: A2,
showHammer: false,
showMose: false
,
tr: 1,
id: 3,
idValue: A3,
showHammer: false,
showMose: false
,
tr: 1,
id: 4,
idValue: A4,
showHammer: false,
showMose: false
,],
[
tr: 2,
id: 1,
idValue: A5,
showHammer: false,
showMose: false
,
tr: 2,
id: 2,
idValue: A6,
showHammer: false,
showMose: false
,
tr: 2,
id: 3,
idValue: A7,
showHammer: false,
showMose: false
,
tr: 2,
id: 4,
idValue: A8,
showHammer: false,
showMose: false
,],
[
tr: 3,
id: 1,
idValue: A9,
showHammer: false,
showMose: false
,
tr: 3,
id: 2,
idValue: A10,
showHammer: false,
showMose: false
,
tr: 3,
id: 3,
idValue: A11,
showHammer: false,
showMose: false
,
tr: 3,
id: 4,
idValue: A12,
showHammer: false,
showMose: false
,],
[
tr: 4,
id: 1,
idValue: A13,
showHammer: false,
showMose: false
,
tr: 4,
id: 2,
idValue: A14,
showHammer: false,
showMose: false
,
tr: 4,
id: 3,
idValue: A15,
showHammer: false,
showMose: false
,
tr: 4,
id: 4,
idValue: A16,
showHammer: false,
showMose: false
,]
],
hardRating: 1, //难度等级(默认为1)
passScore: 1, //命中单个得分
disAppearTime: 2500, //消失时间
hardList: [
hardId: 1,
add: 1,
disappear: 2500,
,
hardId: 2,
add: 2,
disappear: 2000,
,
hardId: 3,
add: 3,
disappear: 1500,
,
hardId: 4,
add: 5,
disappear: 500,
],
,
onInit()
,
onShow()
this.hardRating = 1
,
//打开弹框
showDialog(e)
this.$element(hintDialog).show()
,
//关闭弹框
closeDialog(e)
this.$element(hintDialog).close()
,
//开始按钮 数据清零
startGame()
this.timeInt = 60;
this.countInt = 0;
this.scoreInt = 0;
//生成地鼠
let moseTimer = setInterval(this.showMose, 100)
//游戏时间倒计时
let countDown = setInterval(() =>
this.timeInt--;
//倒计时结束清除定时器
if (this.timeInt === 0)
clearInterval(countDown);
clearInterval(moseTimer);
//弹出游戏结束弹框
this.showDialog();
, 1000)
,
//随机生成地鼠
showMose()
let i = Math.round(Math.random() * 3);
let j = Math.round(Math.random() * 3);
this.trOne[j][i].showMose = true;
//根据难度决定隔多少毫秒地鼠消失
setTimeout(() =>
this.trOne[j][i].showMose = false;
, this.disAppearTime)
,
//敲击地鼠动画效果
showHammer(item)
this.trOne[item.tr-1][item.id-1].showHammer = true;
var options =
duration: 50,
easing: friction,
delay: 0,
fill: forwards,
iterations: 2,
direction: normal,
;
var frames = [
transform:
rotate: 0deg
, opacity: 0.1, offset: 0.0
,
transform:
rotate: -30deg
, opacity: 1.0, offset: 1.0
];
this.animation = this.$element(item.idValue).animate(frames, options);
this.animation.play();
//命中数及分数变化
this.countHander()
//锤子消失
setTimeout(() =>
this.trOne[item.tr-1][item.id-1].showHammer = false;
, 300)
,
//命中数及分数变化
countHander()
this.trOne.forEach((item, index) =>
item.forEach((_item, _i) =>
if (_item.showHammer == true && _item.showMose == true)
this.countInt++;
//根据难度计算得分
this.scoreInt += this.passScore
)
)
,
//难度改变
changeRating(e)
this.hardRating = e.rating;
//命中得分改变
this.passScore = this.hardList[this.hardRating-1].add;
//地鼠消失时间改变
this.disAppearTime = this.hardList[this.hardRating-1].disappear
总结
对于FA目前还在摸索的路上,这个游戏写的比较简单,思考的不够全面,还有很多不足之处。希望大家有什么想法和意见可以提出来,共同进步。
更多原创内容请关注:中软国际 HarmonyOS 技术团队
入门到精通、技巧到案例,系统化分享HarmonyOS开发技术,欢迎投稿和订阅,让我们一起携手前行共建鸿蒙生态。
以上是关于#夏日挑战赛# HarmonyOS - 基于ArkUI(JS)实现打地鼠游戏的主要内容,如果未能解决你的问题,请参考以下文章