vue 游戏 虚拟摇杆 控制飞机

使用vue  设计了一个虚拟摇杆,可以控制飞机移动

移动使用二维向量,实现任意方向的移动

点击显示,不占用屏幕空间

可以控制移动的速度,与小球与大球的距离成正比

设置需要使用到的属性

包括是否显示摇杆,大小圆到的位置大小,飞机的大小,位置和移动的方向向量

        show: false,
        // 大小圆圈的圆心位置
        outX: 0,
        outY: 0,
        inX: 0,
        inY: 0,
        outR: 50,
        inR: 25,
        planeX: 0,
        planeY: 0,
        // 飞机的宽高和速度
        planeSize: 64,
        speed: 10,

        // 方向向量
        moveX: 0,
        moveY: 0,

首先监听三个事件

@touchmove="touchmove"
@touchstart="touchstart"
@touchend="touchend"

当移动开始时(点击时)触发start事件,显示摇杆面板,设置移动向量为0,记录大小球的圆心位置

开始移动时,获取移动的位置与大球位置的距离和方向向量,调整小球的位置,并且使其不要超出大球范围,设置移动向量

移动结束,设置摇杆不可见,并设置移动向量为0

在挂载时设置一个定时器,根据方向向量计算飞机位置,即向量相加,注意还要考虑速度

      setInterval(
        () => {
          this.planeX += this.moveX * this.speed
          this.planeY += this.moveY * this.speed
          console.log(this.planeX, this.planeY)
        },
        50
      )

全部代码

<template>
  <div class="main"
       @touchmove="touchmove"
       @touchstart="touchstart"
       @touchend="touchend"
  >
    <!--两个div,一个是背景,一个是移动时显示的控制小球。虽然在逻辑上有父子关系,
    但是由于使用绝对定位,并不需要在结构上也遵循这个关系-->
    <div class="out" ref="out" v-show="show" :style="outPos"></div>
    <div class="in" ref="in" :style="inPos" v-show="show"></div>

    <div class="plane" ref="plane" :style="planePos"></div>
  </div>
</template>

<script>

  export default {
    name: "t3",
    data() {
      return {
        show: false,
        // 大小圆圈的圆心位置
        outX: 0,
        outY: 0,
        inX: 0,
        inY: 0,
        outR: 50,
        inR: 25,
        planeX: 0,
        planeY: 0,
        // 飞机的宽高和速度
        planeSize: 64,
        speed: 10,

        // 方向向量
        moveX: 0,
        moveY: 0,
      }
    },
    computed: {
      outPos() {
        return `width:${this.outR * 2}px;height:${this.outR * 2}px;left:${this.outX - this.outR }px;top:${this.outY - this.outR }px`
      },
      inPos() {
        return `width:${this.inR * 2}px;height:${this.inR * 2}px;left:${this.inX - this.inR }px;top:${this.inY - this.inR }px`
      },
      planePos() {
        return `left:${this.planeX - this.planeSize / 2 }px;top:${this.planeY - this.planeSize / 2}px`
      }

    },
    methods: {

      touchstart(e) {
        this.show = true
        let x = e.touches[0].clientX
        let y = e.touches[0].clientY
        this.outX = x
        this.outY = y
        this.inX = x
        this.inY = y
        this.moveX = 0
        this.moveY = 0
      }
      ,
      touchend(e) {
        this.show = false
        this.moveX = 0
        this.moveY = 0
      }
      ,
      touchmove(e) {
        let x = e.touches[0].clientX
        let y = e.touches[0].clientY
        // this.outX = x
        // this.outY = y
        this.inX = x
        this.inY = y

        // len是 外面小球与里面小球的最大距离
        // 如果距离过大,调整为两球的半径之和
        let len1 = this.outR
        let len2 = ((x - this.outX) ** 2 + (y - this.outY) ** 2) ** 0.5


        // 调整小球的位置,使其不超出大球的范围
        console.log(len1, len2)
        if (len1 < len2) {
          console.log('222222222')
          let dx = this.inX - this.outX
          let dy = this.inY - this.outY
          let r = len1 / len2
          let ndx = dx * r
          let ndy = dy * r
          this.inX = this.outX + ndx
          this.inY = this.outY + ndy
        }


        // 设置方向向量,y以下为正,x以右为正
        this.moveX = (this.inX - this.outX) / this.outR
        this.moveY = (this.inY - this.outY) / this.outR

      }
    }
    ,
    mounted() {
      setInterval(
        () => {
          this.planeX += this.moveX * this.speed
          this.planeY += this.moveY * this.speed
          console.log(this.planeX, this.planeY)
        },
        50
      )
      this.HEIGHT = document.body.clientHeight
      this.WIDTH = document.body.clientWidth
      console.log(this.WIDTH, this.HEIGHT)
      this.planeX = this.WIDTH / 2
      this.planeY = this.HEIGHT / 2
    }
  }
</script>

<style scoped>
  .main {
    width: 100vw;
    height: 100vh;
    /*display: flex;*/
    position: relative;

  }

  .out {

    border-radius: 50%;
    background: lightskyblue;
    position: absolute;
  }

  .in {

    border-radius: 50%;
    background: deepskyblue;
    position: absolute;
  }

  .plane {
    background: url("../assets/plane.svg");
    width: 64px;
    height: 64px;
    position: absolute;
    /*left: 50%;*/
    /*top: 50%;*/
  }
</style>

猜你喜欢

转载自my.oschina.net/ahaoboy/blog/1795493