更新于 

向量 Vector

计算公式

向量

向量指具有大小和方向的量

在笛卡尔坐标系中,向量可以分散为沿x轴和y轴的两个分量,

假设向量V方向和x轴正方向之间的夹角角度 = a
则V沿x轴和y轴的分量分别是:

1
2
x = |V|cos(a)
y = |V|sin(a)

在js中提供了一些三角函数的方法,使用的基本都是弧度制,
弧度制和角度制的公式关系如下:

1
1° = Pi/180
1
const radian = this.node.angle * Math.PI / 180

实现

这里要实现的功能是:

  • 俯视角角色跟随鼠标位置旋转
  • 鼠标右键控制子弹沿角色正前方发射出去

每一帧的更新都要涉及到2个计算

  • 子弹Node的旋转角度转弧度
  • 计算子弹移动分量
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    export default class NewClass extends cc.Component {
    @property
    speed:number = 100
    update (dt) {
    // 角度制转弧度制
    const radian = (this.node.angle + 90) * Math.PI / 180
    // 计算分量
    this.node.x += this.speed * dt * Math.cos(radian)
    this.node.y += this.speed * dt * Math.sin(radian)
    }
    }

首先实现玩家跟随鼠标旋转:

  • 监听鼠标移动事件,记录鼠标点位
  • 每帧对玩家Node的angle进行更新
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
export default class Player extends cc.Component{
mousePosition = []
start(){
cc.find('scene').on(cc.Node.EventType.MOUSE_MOVE, (event:cc.Event.EventMouse)=>{
// 记录当前鼠标点位
this.mousePosition = [event.getLocationX(),event.getLocationY()]
})
}
update (dt) {
let dx = this.mousePosition[0] - this.node.x
let dy = this.mousePosition[1] - this.node.y

// 计算旋转角度
let radian = - Math.atan(dx/dy)
let angle = radian * 180 / Math.PI
if((dx < 0 && dy<0) || (dx>0 && dy <0)) angle += 180
this.node.angle = angle

}
}

实现子弹超前发射:

  • 监听鼠标点击事件
  • 创建子弹节点
  • 初始化子弹角度
  • 界面加入子弹
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
 cc.find('scene').on(cc.Node.EventType.MOUSE_UP, (event:cc.Event.EventMouse)=>{
// console.log(event)
let type = event.getButton()
switch(type){
case 0:
// 移动
this.targetPosition = [event.getLocationX(),event.getLocationY()]
break;
case 2:
// 发射子弹
// load用于控制子弹间隔时间
if(this.load) return
// 散弹:一发3枚子弹
for(let i = 0;i<3;i++){
let bullet = cc.instantiate(this.bulletPre)
// 计算子弹角度
bullet.angle = this.node.angle + (1 - i) * 10
// 注意:这里的BulletPosition是Player下的一个子空节点
// 表示子弹发出的位置
// 将子弹坐标系放置在全局坐标系下
bullet.setPosition(this.node.getChildByName("BulletPosition").convertToWorldSpaceAR(cc.Vec2.ZERO))
//根组件加入子弹
bullet.setParent(cc.director.getScene())
}

// 添加音效
cc.find('Canvas/Sound').getComponent(cc.AudioSource).play()
// 间隔控制
this.load = true
setTimeout(()=>{
this.load = false
},this.loadTime * 1000)
break;
}
})