java 向量上的坐标点_反复横跳的瞄准线!从向量计算说起!射线检测!Cocos Creator...

本文介绍了如何使用Cocos Creator的物理系统中的射线检测来实现反复横跳的瞄准线效果。首先,文章简单回顾了向量的加法、点乘等基础知识,然后阐述了反射向量的计算公式。接着,在Cocos Creator中设置静态刚体和碰撞器,并开启物理引擎。通过起始点、入射方向和剩余线段长度进行射线检测,当检测到碰撞体时计算反射方向并继续检测,直至完成瞄准线的绘制。此外,还提供了画瞄准线小圈圈的方法。
摘要由CSDN通过智能技术生成

最近有小伙伴问我瞄准线遇到各种形状该怎么处理?如何实现反复横跳的瞄准线?最近刚好在《Cocos Creator游戏开发实战》中看到物理系统有一个射线检测,于是,基于这个射线检测,写了一个反复横跳的瞄准线效果。一起往下看吧!

国际惯例,先上最终效果!

0a46aa19a95b8614a7fb11768eb58d6a.gif

在讲解之前我们需要一些向量的知识,简单的介绍一些吧!

向量的加法,OA + AB = OB

408f227c24963a36017849c8e00096c1.png

向量的点乘,表示一个向量在另一个向量上的投影,是个标量,有正负之分。向量夹角小于 90度 为正数,等于 90度 为 零,大于 90度 为负数。

fb6b03018cf5bd940677809950baa68f.png

向量的叉乘,结果为向量,正好垂直于两个向量构成的平面(右手系),也称为法向量。这里暂时没用到,顺便提一下。

接下来进入正题,已知入射向量(单位向量),法向量(单位向量),如何得出反射向量?

3f98057eb40d9fe0d65deebfef580570.png

我们将反射向量平移至入射向量起点,延长法向量与其相交,这个延长线的长度,刚好是 入射向量在法向量上的投影的相反数的两倍 。再根据投影和向量加法可以推出反射向量的计算公式。

0844925f0b9916ccf39a3c76360fe2c0.png

清楚了么?不清楚也没关系,记得最后的公式就可以了,接下来进入 cocos creator 操作环节。

既然是物理系统中的碰撞检测,我们在编辑器里添加的是物理系统中的碰撞器,而不是引擎的碰撞器,不要选错了哦。

4122755c1d536fdadfd9e97f4f74a886.png

不动的刚体类型设为 static ,添加完所有的物理碰撞器后如下所示。

96ecc74563c43bacbe85c0a2485e497d.png

用到物理引擎自然要把物理引擎打开。

cc.director.getPhysicsManager().enabled = true;

如何进行射线检测的?通过起始点、入射方向和剩余线段的长度获取射线检测的结果。如果检测到碰撞体,就画入射线段,并计算反射方向,再次进行射线检测;如果未检测到碰撞体,就把剩余线段画完。主要代码如下:

/** * @description 计算射线 * @param startLocation 起始位置 世界坐标系 * @param vector_dir 单位方向向量 */private drawRayCast(startLocation: cc.Vec2, vector_dir: cc.Vec2) {    // 剩余长度    const left_length = AIM_LINE_MAX_LENGTH - this._cur_length;    if (left_length <= 0) return;    // 计算线的终点位置    const endLocation = startLocation.add(vector_dir.mul(left_length));    // 射线测试    const results = cc.director.getPhysicsManager().rayCast(startLocation, endLocation, cc.RayCastType.Closest);    if (results.length > 0) {        const result = results[0];        // 指定射线与穿过的碰撞体在哪一点相交。        const point = result.point;        // 画入射线段        this.drawAimLine(startLocation, point);        // 计算长度        const line_length = point.sub(startLocation).mag();        // 计算已画长度        this._cur_length += line_length;        // 指定碰撞体在相交点的表面的法线单位向量。        const vector_n = result.normal;        // 入射单位向量        const vector_i = vector_dir;        // 反射单位向量        const vector_r = vector_i.sub(vector_n.mul(2 * vector_i.dot(vector_n)));        // 接着计算下一段        this.drawRayCast(point, vector_r);    } else {        // 画剩余线段        this.drawAimLine(startLocation, endLocation);    }}

如何画瞄准线小圈圈?通过结束位置和起始位置计算数量和间隔向量,画出一个个小圆圈。参考代码如下。

/** * @description 画瞄准线 * @param startLocation 起始位置 世界坐标系 * @param endLocation 结束位置 世界坐标系 */private drawAimLine(startLocation: cc.Vec2, endLocation: cc.Vec2) {    // 转换坐标    const graphic_startLocation = this.graphic_line.node.convertToNodeSpaceAR(startLocation);    this.graphic_line.moveTo(graphic_startLocation.x, graphic_startLocation.y);    // 画小圆圆    // 间隔    const delta = 20;    // 方向    const vector_dir = endLocation.sub(startLocation);    // 数量    const total_count = Math.round(vector_dir.mag() / delta);    // 每次间隔向量    vector_dir.normalizeSelf().mulSelf(delta);    for (let index = 0; index < total_count; index++) {        graphic_startLocation.addSelf(vector_dir)        this.graphic_line.circle(graphic_startLocation.x, graphic_startLocation.y, 2);    }}
9b85c215d289fdc5de4ce72f825ffaa1.png

4771c7e984ee0b4b3589d815640c3950.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值