经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » 鸿蒙 » 查看文章
鸿蒙开发游戏(三)---大鱼吃小鱼(放置NPC)
来源:cnblogs  作者:TMusketeer  时间:2024/2/18 9:06:22  对本文有异议

效果图

添加了一个NPC(小红鱼),玩家控制小黄鱼

鸿蒙开发游戏(一)---大鱼吃小鱼(界面部署

鸿蒙开发游戏(二)---大鱼吃小鱼(摇杆控制)

鸿蒙开发游戏(三)---大鱼吃小鱼(放置NPC)

鸿蒙开发游戏(四)---大鱼吃小鱼(互吃升级)

鸿蒙开发游戏(五)---大鱼吃小鱼(添加音效)

鸿蒙开发游戏(六)---大鱼吃小鱼(称霸海洋)

 

前两篇文章我们做了摇杆控制小鱼移动,这篇将会添加一个NPC,让其自动在海洋里游荡,然后玩家控制吃掉它。在这之前我们想思考一些问题,

NPC如何生成?NPC有哪些属性?NPC是如何控制的?如何做到随机转方向?

这是该篇的难点,这里还用到了一些数学知识,包括sin,cos,弧度与角度的计算等,还是比较麻烦的,但是等你看到代码又会发现代码量很少,又会觉得如此简单,好了,看例子。

1、开始游戏

这里我们需要添加一个开始游戏按钮,因为只有玩家开始了游戏,我们启动一个计时器才会变得顺理成章,不然的话,上来就启动计时器会很好资源的。

  1. export struct FishPage {
  2. @State isBegin: boolean = false
  3. }

这里我们默认是false,未启动状态

  1. build() {
  2. Row() {
  3. Stack() {
  4. // 背景
  5. Image($r("app.media.bg_fish"))
  6. if (this.isBegin == false) {
  7. Button('开始游戏')
  8. .backgroundColor('#36d')
  9. .onClick(() => {
  10. //这里把设置成true
  11. this.isBegin = true
  12. })
  13. } else {
  14. //渲染小鱼
  15. }
  16. }
  17. }

 

2、添加NPC小鱼

我们在开始之前就已经开始思考了,NPC应该有什么属性,起始位置,方向,速度,等,这里暂时不需要等级,下篇互吃逻辑写。

  1. //NPC
  2. @State npcSpeed: number = 3
  3. @State npcFishX: number = 300
  4. @State npcFishY: number = 200
  5. @State npcAngle: number = 0
  6. @State intervalIdNPC_1: number = 1
  7. @State npcSin: number = 1
  8. @State npcCos: number = 1

npc显示需要写在else里面,也就是点击开始游戏后,isBegin=true时

  1. if (this.isBegin == false) {
  2. Button('开始游戏')
  3. .backgroundColor('#36d')
  4. .onClick(() => {
  5. this.isBegin = true
  6. })
  7. } else {
  8. Image($r("app.media.icon_fish_right"))
  9. .position({ x: this.xFish - this.fishRadius, y: this.yFish - this.fishRadius })
  10. .rotate({ angle: this.angle, centerX: '50%', centerY: '50%' })
  11. .width(40)
  12. .height(40)
  13. Image($r("app.media.icon_npc_2"))
  14. .position({ x: this.npcFishX - this.fishRadius, y: this.npcFishY - this.fishRadius })
  15. .rotate({ angle: this.npcAngle, centerX: '50%', centerY: '50%' })
  16. .objectFit(ImageFit.ScaleDown)
  17. .width(40)
  18. .height(40)
  19. }

ok,第一个image是玩家控制的小鱼,第二个image是NPC。

 

3、NPC动起来

问题来了,NPC如何自己动起来了,这就又用到了计时器,这里如果有其他好的方法也评论区打出来哈。当玩家点击开始游戏按钮时启动计时器,

  1. if (this.isBegin == false) {
  2. Button('开始游戏')
  3. .backgroundColor('#36d')
  4. .onClick(() => {
  5. this.isBegin = true
  6. clearInterval(this.intervalIdNPC_1)
  7. this.intervalIdNPC_1 = setInterval(() => {
  8. //设置小鱼的移动位置,
  9. this.npcFishX += this.npcSpeed * this.npcCos
  10. this.npcFishY += this.npcSpeed * this.npcSin
  11. this.npcFishX = this.getNPCBorderX(this.npcFishX)
  12. this.npcFishY = this.getNPCBorderY(this.npcFishY)
  13. }, 40)
  14. })
  15. }

这里需要说一下,启动一个计时器,内部是不断地计算npc的位置,getNPCBorderX这个是防止走出屏幕的宽度和高度设置的,当触碰到边框要改变方向。难点也在这

  1. getNPCBorderX(x: number) {
  2. if (x <= this.fishRadius) {
  3. x = this.fishRadius + 10
  4. this.getRandom()
  5. }
  6. if (x > this.screenWidth - this.fishRadius) {
  7. x = this.screenWidth - this.fishRadius - 15
  8. this.getRandom()
  9. }
  10. return x
  11. }
  12. getNPCBorderY(y: number) {
  13. if (y <= this.fishRadius) {
  14. y = this.fishRadius + 10
  15. this.getRandom()
  16. }
  17. if (y > this.screenHeight - this.fishRadius) {
  18. y = this.screenHeight - this.fishRadius - 10
  19. this.getRandom()
  20. }
  21. return y
  22. }

那一个x方向说吧,当x<=小鱼的半径时说明,小鱼已经贴左边了,大于屏幕宽度时贴右边了,这时我们要改变方向,getRandom()就是改变方向用的,至于x=this.fishRadius +10 这个主要是当贴边后,小鱼还在走,就会触发多次if语句,生成多次方向,也就是说会出现抖动现象,感兴趣去掉赋值可以试试。

4、NPC方向生成

这一块是最麻烦的,

  1. 弧度 = 角度 * π / 180
  2. 角度 = 弧度 * 180 / π

我们认识到的Math.sin,cos,tan等一般都是传入一个弧度,而不是角度(我传入角度老是有问题,这里传入弧度就解决了)

  1. /*随机获取一个角度*/
  2. getRandom() {
  3. this.npcAngle= this.selectFrom(-179,180)
  4. // let angle = Math.random()+Math.random()+Math.random()
  5. // this.npcAngle = angle * 180 / Math.PI
  6. //这是是求弧度,弧度 = 角度 * π / 180
  7. this.npcSin = Math.sin(this.npcAngle * Math.PI /180)
  8. this.npcCos = Math.cos(this.npcAngle * Math.PI /180)
  9. console.log("角度"+this.npcAngle)
  10. }
  11. selectFrom(startNumber, endNumber) {
  12. let choice = endNumber - startNumber + 1;
  13. return Math.floor(Math.random() * choice + startNumber)
  14. }

首先我们需要随机生成一个角度,比如说90度,50度,-120度等

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

那么x轴上的值就是x = speed * cos值,如下

  1. this.intervalIdNPC_1 = setInterval(() => {
  2. //设置小鱼的移动位置,
  3. this.npcFishX += this.npcSpeed * this.npcCos
  4. this.npcFishY += this.npcSpeed * this.npcSin
  5. this.npcFishX = this.getNPCBorderX(this.npcFishX)
  6. this.npcFishY = this.getNPCBorderY(this.npcFishY)
  7. }, 40)

 

5、关闭计时器

  1. onPageHide() {
  2. clearInterval(this.intervalIdNPC_1)
  3. }

记住页面消失时,或者游戏结束时需要关闭计时器

好了,到这NPC防止就完成了。

 

原文链接:https://www.cnblogs.com/cmusketeer/p/18016841

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号