前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >鸿蒙开发游戏(二)---大鱼吃小鱼(摇杆控制)

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

作者头像
cMusketeer
发布2024-02-11 08:39:33
1840
发布2024-02-11 08:39:33
举报
文章被收录于专栏:Android机器圈

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

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

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

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

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

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

前言:上一篇介绍了鸿蒙新建项目以及界面部署,并未实现方向逻辑,上下左右控制,这篇来搞一下。首先如果我们用上下左右来控制很显然是不行的,因为我们还希望斜着也能游动,所以只能使用摇杆来试下,大家都肯定玩过王者荣耀,左下角的摇杆控制英雄走动,而且滑动的时候手指不自觉就滑出摇杆圈了,但是任务已经在动,这就物理摇杆和虚拟摇杆的区别,小时候玩过手柄吧,你手柄就不会出现摇出界的情况,因为是实体的,一旦出界你是有感触的,下意识就会修正,但虚拟的摇杆就很容易出界,所以我们要保证就算出界了只要手指没有抬起依旧可以触发事件。

1、摇杆布局

我们需要把←↑↓→替换成圆圈,方式有多种,看你喜欢。

  • 我们可以通过设置组件的弧度让其成圆形
  • Circle:系统给我们提供的圆形

开干

首先我们先看一下需要哪些变量,一定要提前定义好,统一操作一个变量。

  • 大圆有半径,有中心点(可以理解为初始点)
  • 小圆(做摇杆用)有半径,有拖动位置
代码语言:javascript
复制
// 摇杆的中心位置
@State centerX: number = 120
@State centerY: number = 120

//摇杆的初始位置
@State positionX: number = this.centerX
@State positionY: number = this.centerY

//半径
@State radiusMax: number = 100
// 小圆半径
@State radiusMin: number = 20

定义好之后就可以初始化位置了

代码语言:javascript
复制
Row() {
  Circle({ width: this.radiusMax * 2, height: this.radiusMax * 2 })
    .fill('#50f1eded')
    .position({ x: this.centerX - this.radiusMax, y: this.centerY - this.radiusMax })


  Circle({ width: this.radiusMin * 2, height: this.radiusMin * 2 })
    .fill('#50f1eded')
    .position({ x: this.positionX - this.radiusMin, y: this.positionY - this.radiusMin })
}
.width(240)
.height(240)
.position({ x: 0, y: 120 })
.justifyContent(FlexAlign.Center)

上面需要注意的是x: this.centerX - this.radiusMax,我们知道屏幕的起始点是从左上角开始延伸的,组件的起始位置也是从左上角开始的,我们定义的是中心点,所以要减去圆半径,不然的话就偏移了

代码语言:javascript
复制
.justifyContent(FlexAlign.Center)

你看到了Row,这是左右布局,加上这句话可以让内容居中。

效果如下

添加点击事件(Row布局)

代码语言:javascript
复制
.onTouch(this.handleTouchEvent.bind(this))

handleTouchEvent是我们自定义的方法,传入一个 TouchEvent。

  • TouchEvent.Down:按下事件(1次)
  • TouchEvent.Move:移动事件(0-无数次)
  • TouchEvent.Up(1次)

当我们一个事件产生后,就会触发一次down事件,0次移动事件(用户手指不移动)和无数次移动事件(用户疯狂移动手指),之后抬起手指触发一次up事件。

代码语言:javascript
复制
handleTouchEvent(event: TouchEvent) {
  switch (event.type) {
    case TouchType.Down:

      break
    case TouchType.Move:
      this.setMovePosition(event)
      break
    case TouchType.Up:

      break
  }

OK,那就开始吧,由于Move代码有点多,这里抽取一个方法叫做

代码语言:javascript
复制
setMovePosition(event: TouchEvent) {
 

  }

在这我们要开始思考了,竟然是通过摇杆去控制鱼,那我们得知道摇杆滑动的方向

当你的手机从红圆点滑动到指定位置时,他的坐标我们可以得到,从而获取手指与圆点的距离,vy,vx,通过tan可以获取到夹角。通过夹角计算出手指离中心点的距离从而设置摇杆的位置。

1、计算手指的位置

代码语言:javascript
复制
let x = event.touches[0].x;
let y = event.touches[0].y;

2、计算手指与中心点的差值

代码语言:javascript
复制
let vx = x - this.centerX;
let vy = y - this.centerY;

3、计算夹角

代码语言:javascript
复制
let angle = Math.atan2(vy, vx)

4、利用夹角计算出手指离中心点的距离

代码语言:javascript
复制
let distance = this.getDistance(vx, vy)
    
单独写个方法
  getDistance(x: number, y: number) {
    let distance = Math.sqrt(x * x + y * y)
    return Math.min(distance, this.radiusMax)
  }

这里需要注意一下,计算的距离不能超过大圆,我们要始终保持摇杆(小圆)在大圆区域内

5、计算小圆的坐标

代码语言:javascript
复制
this.sin = Math.sin(angle)
this.cos = Math.cos(angle)
this.positionX = distance * this.cos + this.centerX
this.positionY = distance * this.sin + this.centerY

OK,到这就摇杆就完成了,你快去试试效果吧。

调试中。。。。。。。。。。

问题1

你会发现这小鱼没有动只是摇杆动了,我们还需要设置小鱼的位置xfish,yfish

代码语言:javascript
复制
//6、设置小鱼的移动位置,
this.xFish += this.speed * this.cos
this.yFish += this.speed * this.sin

记得给他一个速度speed。

试试效果吧...................

问题2

是不是还有问题,就是我们滑动摇杆时小鱼动了,一旦我们停止滑动摇杆时小鱼就停止了,那这是为什么呢,安卓开发应该都会自定义view,当我们需要对view进行重绘时,会用到invalidate,对,这就是通知系统要刷新view了,在这的问题就是这,所以我们需要通知系统也对view进行刷新。

这里我们开启一个定时器

代码语言:javascript
复制
this.intervalId = setInterval(() => {
          //6、设置小鱼的移动位置,
          this.xFish += this.speed * this.cos
          this.yFish += this.speed * this.sin

          //目的是触碰到边缘时不溢出
          this.xFish = this.getBorderX(this.xFish)
          //还原角度
          // this.angle = 0

        }, 40)

这里我们传入40毫秒,肉眼一秒26帧左右会很顺滑,1000/26 约等于38,我们直接写40。

那么这个定时器我们不能一直开着,主要是没必要,当我们在按压down时设置,抬起时释放掉

代码语言:javascript
复制
clearInterval(this.intervalId)

完整代码是

代码语言:javascript
复制
handleTouchEvent(event: TouchEvent) {
  switch (event.type) {
    case TouchType.Down:
      this.intervalId = setInterval(() => {
        //6、设置小鱼的移动位置,
        this.xFish += this.speed * this.cos
        this.yFish += this.speed * this.sin

        //目的是触碰到边缘时不溢出
        this.xFish = this.getBorderX(this.xFish)
        //还原角度
        // this.angle = 0

      }, 40)
      break
    case TouchType.Move:
      this.setMovePosition(event)
      break
    case TouchType.Up:
      clearInterval(this.intervalId)
    //恢复摇杆位置
      animateTo({
        curve: curves.springMotion()
      }, () => {
        this.positionX = this.centerX
        this.positionY = this.centerY
      })

      this.speed = 0
      break
  }


}

完.....

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-02-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1、摇杆布局
    • 添加点击事件(Row布局)
      • 1、计算手指的位置
        • 2、计算手指与中心点的差值
          • 3、计算夹角
            • 4、利用夹角计算出手指离中心点的距离
              • 5、计算小圆的坐标
                • 问题1
                • 问题2
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档