鸿蒙开发游戏(三)---大鱼吃小鱼(放置NPC)
效果图
添加了一个NPC(小红鱼),玩家控制小黄鱼

鸿蒙开发游戏(三)---大鱼吃小鱼(放置NPC)
鸿蒙开发游戏(四)---大鱼吃小鱼(互吃升级)
鸿蒙开发游戏(五)---大鱼吃小鱼(添加音效)
鸿蒙开发游戏(六)---大鱼吃小鱼(称霸海洋)
前两篇文章我们做了摇杆控制小鱼移动,这篇将会添加一个NPC,让其自动在海洋里游荡,然后玩家控制吃掉它。在这之前我们想思考一些问题,
NPC如何生成?NPC有哪些属性?NPC是如何控制的?如何做到随机转方向?
这是该篇的难点,这里还用到了一些数学知识,包括sin,cos,弧度与角度的计算等,还是比较麻烦的,但是等你看到代码又会发现代码量很少,又会觉得如此简单,好了,看例子。
1、开始游戏
这里我们需要添加一个开始游戏按钮,因为只有玩家开始了游戏,我们启动一个计时器才会变得顺理成章,不然的话,上来就启动计时器会很好资源的。
export struct FishPage {
@State isBegin: boolean = false
}
这里我们默认是false,未启动状态
build() {
Row() {
Stack() {
// 背景
Image($r("app.media.bg_fish"))
if (this.isBegin == false) {
Button('开始游戏')
.backgroundColor('#36d')
.onClick(() => {
//这里把设置成true
this.isBegin = true
})
} else {
//渲染小鱼
}
}
}

2、添加NPC小鱼
我们在开始之前就已经开始思考了,NPC应该有什么属性,起始位置,方向,速度,等,这里暂时不需要等级,下篇互吃逻辑写。
//NPC
@State npcSpeed: number = 3
@State npcFishX: number = 300
@State npcFishY: number = 200
@State npcAngle: number = 0
@State intervalIdNPC_1: number = 1
@State npcSin: number = 1
@State npcCos: number = 1
npc显示需要写在else里面,也就是点击开始游戏后,isBegin=true时
if (this.isBegin == false) {
Button('开始游戏')
.backgroundColor('#36d')
.onClick(() => {
this.isBegin = true
})
} else {
Image($r("app.media.icon_fish_right"))
.position({ x: this.xFish - this.fishRadius, y: this.yFish - this.fishRadius })
.rotate({ angle: this.angle, centerX: '50%', centerY: '50%' })
.width(40)
.height(40)
Image($r("app.media.icon_npc_2"))
.position({ x: this.npcFishX - this.fishRadius, y: this.npcFishY - this.fishRadius })
.rotate({ angle: this.npcAngle, centerX: '50%', centerY: '50%' })
.objectFit(ImageFit.ScaleDown)
.width(40)
.height(40)
}
ok,第一个image是玩家控制的小鱼,第二个image是NPC。
3、NPC动起来
问题来了,NPC如何自己动起来了,这就又用到了计时器,这里如果有其他好的方法也评论区打出来哈。当玩家点击开始游戏按钮时启动计时器,
if (this.isBegin == false) {
Button('开始游戏')
.backgroundColor('#36d')
.onClick(() => {
this.isBegin = true
clearInterval(this.intervalIdNPC_1)
this.intervalIdNPC_1 = setInterval(() => {
//设置小鱼的移动位置,
this.npcFishX += this.npcSpeed * this.npcCos
this.npcFishY += this.npcSpeed * this.npcSin
this.npcFishX = this.getNPCBorderX(this.npcFishX)
this.npcFishY = this.getNPCBorderY(this.npcFishY)
}, 40)
})
}
这里需要说一下,启动一个计时器,内部是不断地计算npc的位置,getNPCBorderX这个是防止走出屏幕的宽度和高度设置的,当触碰到边框要改变方向。难点也在这
getNPCBorderX(x: number) {
if (x <= this.fishRadius) {
x = this.fishRadius + 10
this.getRandom()
}
if (x > this.screenWidth - this.fishRadius) {
x = this.screenWidth - this.fishRadius - 15
this.getRandom()
}
return x
}
getNPCBorderY(y: number) {
if (y <= this.fishRadius) {
y = this.fishRadius + 10
this.getRandom()
}
if (y > this.screenHeight - this.fishRadius) {
y = this.screenHeight - this.fishRadius - 10
this.getRandom()
}
return y
}
那一个x方向说吧,当x<=小鱼的半径时说明,小鱼已经贴左边了,大于屏幕宽度时贴右边了,这时我们要改变方向,getRandom()就是改变方向用的,至于x=this.fishRadius +10 这个主要是当贴边后,小鱼还在走,就会触发多次if语句,生成多次方向,也就是说会出现抖动现象,感兴趣去掉赋值可以试试。
4、NPC方向生成
这一块是最麻烦的,
弧度 = 角度 * π / 180
角度 = 弧度 * 180 / π
我们认识到的Math.sin,cos,tan等一般都是传入一个弧度,而不是角度(我传入角度老是有问题,这里传入弧度就解决了)
/*随机获取一个角度*/
getRandom() {
this.npcAngle= this.selectFrom(-179,180)
// let angle = Math.random()+Math.random()+Math.random()
// this.npcAngle = angle * 180 / Math.PI
//这是是求弧度,弧度 = 角度 * π / 180
this.npcSin = Math.sin(this.npcAngle * Math.PI /180)
this.npcCos = Math.cos(this.npcAngle * Math.PI /180)
console.log("角度"+this.npcAngle)
}
selectFrom(startNumber, endNumber) {
let choice = endNumber - startNumber + 1;
return Math.floor(Math.random() * choice + startNumber)
}
首先我们需要随机生成一个角度,比如说90度,50度,-120度等

角度是作为鱼头方向用的,我们按照speed速度去计算该方向的值

那么x轴上的值就是x = speed * cos值,如下
this.intervalIdNPC_1 = setInterval(() => {
//设置小鱼的移动位置,
this.npcFishX += this.npcSpeed * this.npcCos
this.npcFishY += this.npcSpeed * this.npcSin
this.npcFishX = this.getNPCBorderX(this.npcFishX)
this.npcFishY = this.getNPCBorderY(this.npcFishY)
}, 40)
5、关闭计时器
onPageHide() {
clearInterval(this.intervalIdNPC_1)
}
记住页面消失时,或者游戏结束时需要关闭计时器
好了,到这NPC防止就完成了。
鸿蒙开发游戏(三)---大鱼吃小鱼(放置NPC)的更多相关文章
- 【C语言探索之旅】 第三部分第二课:SDL开发游戏之创建窗口和画布
内容简介 1.第三部分第二课: SDL开发游戏之创建窗口和画布 2.第三部分第三课预告: SDL开发游戏之显示图像 第三部分第二课:SDL开发游戏之创建窗口和画布 在上一课中,我们对SDL这个开源库做 ...
- 【C语言探索之旅】 第三部分第一课:SDL开发游戏之安装SDL
内容简介 1.课程大纲 2.第三部分第一课: SDL开发游戏之安装SDL 3.第三部分第二课预告: SDL开发游戏之创建窗口和画布 课程大纲 我们的课程分为四大部分,每一个部分结束后都会有练习题,并会 ...
- HTML5 Canvas游戏开发(三)lufylegend开源库件(上)
lufylegend可以解决HTML5开发游戏中会遇到的一些问题: 1.各种浏览器对于JavaScript和HTML的解析是不一致的. 2.手机浏览器和PC浏览器的区别. 3.JavaScript并非 ...
- 使用 Unity 3D 开发游戏的架构设计难点
Unity 3D 引擎对于开发者来说,入手非常快,因为它采用的是 C# 作为开发语言,这也大大降低了开发者的门槛.但凡只要懂一门编程语言的人都能使用 Unity 3D 引擎开发,另外 Unity 3D ...
- GJM : 各大开发游戏引擎
感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...
- MS CRM 2011的自定义和开发(11)——插件(plugin)开发(三)
http://www.cnblogs.com/StoneGarden/archive/2012/02/06/2340661.html MS CRM 2011的自定义和开发(11)——插件(plugin ...
- Qt移动应用开发(三):使用精灵图片实现帧动画
Qt移动应用开发(三):使用精灵图片实现帧动画 上一篇博文讲到了Qt Quick对于动画的一般支持.动画的形式多样,配合不同的插值函数,能够差点儿实现全部想要的动画效果,而对于游戏的一些特殊的效果比方 ...
- 使用Photon引擎进行unity网络游戏开发(三)——网络游戏大厅及房间
使用Photon引擎进行unity网络游戏开发(三)--网络游戏大厅及房间 Photon PUN Unity 网络游戏开发 连接到Photon ConnectUsingSettings 设置你的客户端 ...
- Kinect for Windows SDK开发入门(三):基础知识 下
原文来自:http://www.cnblogs.com/yangecnu/archive/2012/04/02/KinectSDK_Application_Fundamentals_Part2.htm ...
- Java开发学习(三十七)----SpringBoot多环境配置及配置文件分类
一.多环境配置 在工作中,对于开发环境.测试环境.生产环境的配置肯定都不相同,比如我们开发阶段会在自己的电脑上安装 mysql ,连接自己电脑上的 mysql 即可,但是项目开发完毕后要上线就需要该配 ...
随机推荐
- BTC-实现
BTC-实现 Transaction-based ledger(比特币是基于交易的账本模式) Account-based ledger(以太坊是基于账户的账本模式) UTXO Unspent Tran ...
- shell 编程中 awk ,wc ,$0,$1 等 命令的使用总结
本文为博主原创,转载请注明出处: 1. awk 的常用场景总结 2. wc 常用场景总结 3. $0,$1,$# 的使用总结 4. seq 的使用总结 5. 获取用户输入 read 使用 1. awk ...
- SV 自定义数据类型
概述 自定义类型 枚举类型 定义枚举值 自定义枚举类型 枚举类型之间进行赋值是可以的 枚举类型可以赋值给整型,整型不能直接赋值给枚举类型 枚举类型 + 1 ==> 会进行隐式的转换,枚举类型转换 ...
- 【VSCode】秒下vscode
有时从vscode官网下载速度奇慢甚至失败,介绍一种方法可以秒下 进入官网选择要下载的版本 像我的电脑,下载网址根本打不开 修改下载网址,替换下载地址中红框字符串:vscode.cdn.azure.c ...
- linux-介绍
- 【面试题精讲】JVM中有哪些垃圾收集器
有时博客内容会有变动,首发博客是最新的,其他博客地址可能未同步,请认准https://blog.zysicyj.top 首发博客地址 系列文章地址 在Java虚拟机(JVM)中,有以下几种常见的垃圾收 ...
- [转帖]Django10——从db.sqlite3迁移到MySQL
https://blog.csdn.net/weixin_47197906/article/details/124889477 文章目录 1.查看Django支持的数据库 2.修改数据库配置 1.查看 ...
- [转帖]global cache cr request等待事件分析及优化
在RAC环境中,和全局调整缓存相关的最常见的等待事件无非就是:global cache cr request,global cache busy和equeue 在XX电信做了一次数据库巡检中发现,sp ...
- [转帖]dd命令中dsync和fsync区别
在Linux系统中经常会使用dd命令来测试硬盘的写入速度,命令会涉及几个常用参数:sync.dsync.fsync与fdatasync # dd if=/dev/zero of=/tmp/1G bs= ...
- [转帖]07-rsync企业真实项目备份案例实战(需求收集--服务器配置---客户端配置---报警机制---数据校验---邮件告警)
https://developer.aliyun.com/article/885820?spm=a2c6h.24874632.expert-profile.279.7c46cfe9h5DxWK 简介: ...