【HarmonyOS开发】吃鱼吧——简易版大鱼吃小鱼(二)

摇杆设计和主角鱼的移动

通过触屏操作设计摇杆实现主角鱼的移动

首先定义遥杆,使用两个Circle组件绘制两个半径不同的圆,较小的圆形作为遥杆可以移动,较大的圆形作为较小圆的移动范围,并添加处理用户触屏操作的事件

import router from '@ohos.router'
import curves from '@ohos.curves'
import NpcInfo from '../viewmodel/NpcInfo';
import npcView from '../view/npcView'
 
@Entry
 
@Component
struct AnimationPage {
 
  @State screenHeight:number=1440;
  @State screenWidth:number=2200;
 
 
  @State fishSize:number=200
  // 小鱼坐标
  @State fishX: number = 200
  @State fishY: number = 120
  // 小鱼角度
  @State angle: number = 0
  // 小鱼图片
  @State src: Resource = $r('app.media.fish')
 
  // 是否开始游戏
  @State isBegin: boolean = false

  // 摇杆中心区域坐标
  private centerX: number = 120
  private centerY: number = 120

  // 大、小圆半径
  private maxRadius: number = 200
  private radius: number = 60

  // 摇杆小圆球初始位置
  @State positionX: number = this.centerX;
  @State positionY: number = this.centerY;

  // 角度正弦和余弦
  sin: number = 0
  cos: number = 0

  // 小鱼移动速度
  speed: number = 0
  // 任务id
  taskId: number = -1
 
  build() {
    Row() {
      Stack(){
        // 返回按钮
        Button('BACK')
          .position({x:30, y: 30})
          .backgroundColor('#20101010')
          .onClick(() => {
            // 返回上一页
            router.back()
          })
          .fontSize(50)
          .width(200)
          .height(100)
 
        // 开始按钮和小鱼
        if(!this.isBegin){
          // 开始按钮
          Button('GAME START')
            .onClick(() => {
              animateTo(
                {duration: 1000},
                () => {
                  //点击后显示小鱼
                  this.isBegin = true  
                }
              )
            })
            .fontSize(85)
            .width(600)
            .height(200)
        }else{
          // 小鱼图片
          Image(this.src)
            .position({x: this.fishX, y: this.fishY})
            .rotate({angle:this.angle, centerX: '50%', centerY: '50%'})
            .width(this.fishSize)
            .height(this.fishSize)
            .transition({
              type: TransitionType.Insert,
              opacity: 0,
              translate: {x: -250}
            })
         }

                // 摇杆
        Row(){
          Circle({width: this.maxRadius * 2, height: this.maxRadius * 2})
            .fill('#20101010')
            .position({ x: this.centerX-this.maxRadius, y: this.centerY-this.maxRadius })
          Circle({ width: this.radius * 2, height: this.radius * 2 })
            .fill('#403A3A3A')
            .position({ x: this.positionX - this.radius, y: this.positionY - this.radius})
        }
        .height(440)
        .width(440)
        .justifyContent(FlexAlign.Center)
        .position({x:100,y:1050})
        .onTouch(this.handleTouchEvent.bind(this))
   }

自定义触屏事件

实现了摇杆跟随触屏移动但不会超过外面的大圆范围,在触屏事件停止发生即手指离开时让摇杆回到原来的坐标位置,并且实现小鱼根据摇杆操控移动

首先利用event.touch得到手指的位置,再计算手指与中心点的差值vx,vy,通过差值利用tan函 数计算夹角angle,之后再利用得到的夹角计算出出手指离中心点的距离   

代码如下:

 handleTouchEvent(event: TouchEvent){
    switch (event.type){
      case TouchType.Up:
      // 还原小鱼速度
        this.speed = 0
      // 取消定时任务
        clearInterval(this.taskId)
      // 还原摇杆小球的坐标
        animateTo(
          {curve: curves.springMotion()},
          () => {
            this.positionX = this.centerX
            this.positionY = this.centerY

            this.angle = 0
          }
        )
        break
      case TouchType.Down:
      // 开始定时任务
        this.taskId = setInterval(() => {
          this.fishX += this.speed * this.cos
          this.fishY += this.speed * this.sin
          this.eatFish()

          //console.log("opacity:"+this.opacitycnt.toString())
        }, 40)
        break

      case TouchType.Move:
      // 1.获取手指位置坐标
        let x = event.touches[0].x
        let y = event.touches[0].y
      // 2.计算手指与中心点的坐标差值
        let vx = x - this.centerX
        let vy = y - this.centerY
      // 3.计算手指与中心点连线和x轴正半轴的夹角,单位是弧度
        let angle = Math.atan2(vy, vx)
      // 4.计算手指与中心点的距离
        let distance = this.getDistance(vx, vy)

        this.sin = Math.sin(angle)
        this.cos = Math.cos(angle)
      //加上动画使得摇杆移动更丝滑
        animateTo(
          {curve: curves.responsiveSpringMotion()},//可以提供自然和流畅的动画曲线
          () => {
            // 5.计算摇杆小球的坐标
            this.positionX = this.centerX + distance * this.cos
            this.positionY = this.centerY + distance * this.sin

            // 6.修改小鱼的角度
            if(Math.abs(angle * 2) < Math.PI){
              this.src = $r('app.media.fish')
            }else{
              this.src = $r('app.media.fish_rev')
              angle = angle < 0 ? angle + Math.PI : angle - Math.PI
            }
            this.angle = angle * 180 / Math.PI
            // console.log(this.speed.toString())
            this.speed = 20;//小鱼移动的速度
          }
        )
        break
    }
  }

  getDistance(x: number, y: number){
    let d = Math.sqrt(x * x + y * y)
    return Math.min(d, this.maxRadius)
  }
  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值