近期写了一款基于射线测试的小游戏,本篇会介绍射线测试知识和一些坑,保证大家会用并且避免引擎bug。
国际惯例先上效果
射线测试基础知识
先看一遍官网,在页面的最下面部分。射线测试需要用到物理引擎,接下来开始教学。
开启物理引擎
物理系统默认是关闭的,如果需要使用物理系统,那么首先需要做的事情就是开启物理系统,否则你在编辑器里做的所有物理编辑都不会产生任何效果。
onLoad () {
cc.director.getPhysicsManager().enabled = true;
},
添加物理碰撞物体
添加组件
用到的是物理引擎 添加的碰撞体必须是物理组件里的碰撞体
添加组件-》物理组件-》Collider组件-》Box
type设置撑Static
否则会有重力自己下落
通过触摸点触发射线测试
代码挂载在Canvas节点下
onLoad () {
cc.director.getPhysicsManager().enabled = true;
//添加触摸监听 通过触摸点讲解射线测试
this.node.on(‘touchstart’, this.TouchStart, this)
},
TouchStart (event) {
//获得触摸点本地坐标位置
let p1 = event.getLocation()
//射线测试结束点位置 从开始点向右发射:x坐标增加1000 射线测试
let p2 = cc.v2(p1.x+1000, p1.y)
this.rayTest(p1, p2)
},
rayTest (p1, p2) {
var results = cc.director.getPhysicsManager().rayCast(p1, p2, cc.RayCastType.Closest);
for (var i = 0; i < results.length; i++) {
//两点之间检测出来的点的数组
var result = results[i];
//射线穿过的是哪一个碰撞体。
var collider = result.collider;
//射线穿过的碰撞体的世界坐标
var point = result.point;
//碰撞体在相交点的表面的法线向量。
var normal = result.normal;
//相交点在射线上的分数。
var fraction = result.fraction;
//打印出碰撞点的坐标
cc.log('point:', point)
}
},
检测类型介绍
cc.RayCastType.Any
检测射线路径上任意的碰撞体,一旦检测到任何碰撞体,将立刻结束检测其他的碰撞体,最快。
cc.RayCastType.Closest
检测射线路径上最近的碰撞体,这是射线检测的默认值,稍慢。
cc.RayCastType.All
检测射线路径上的所有碰撞体,检测到的结果顺序不是固定的。在这种检测类型下一个碰撞体可能会返回多个结果,这是因为 box2d 是通过检测夹具(fixture)来进行物体检测的,而一个碰撞体中可能由多个夹具(fixture)组成的,慢。更多细节可到 物理碰撞组件 查看。
cc.RayCastType.AllClosest
检测射线路径上所有碰撞体,但是会对返回值进行删选,只返回每一个碰撞体距离射线起始点最近的那个点的相关信息,最慢
result返回值介绍
实际开发过程中的坑
cc.director.getPhysicsManager().rayCast(p1, p2, cc.RayCastType.Closest);
1
这句话会出现bug,原因是因为运行加载的时候物理引擎这部分没有加载完成,所以底层封装的变量没有new出来。
解决方法: 加一个计时器。
this.schedule(function() {
this.rayTest()
}, 0.01);
1
2
3
结果
在这基础上增加表现形式
创建一个星星 检测到射线测试的点 自动移动到检测点的位置
拖拽进入场景
移动
properties: {
m_star: cc.Node,
},
拖入星星
rayTest (p1, p2) {
var results = cc.director.getPhysicsManager().rayCast(p1, p2, cc.RayCastType.Closest);
for (var i = 0; i < results.length; i++) {
//两点之间检测出来的点的数组
var result = results[i];
//射线穿过的是哪一个碰撞体。
var collider = result.collider;
//射线穿过的碰撞体的世界坐标
var point = result.point;
//碰撞体在相交点的表面的法线向量。
var normal = result.normal;
//相交点在射线上的分数。
var fraction = result.fraction;
// cc.log('point:', point)
//世界坐标转成当前节点坐标
let localPos = this.node.convertToNodeSpaceAR(point)
//移动
this.m_star.runAction(cc.moveTo(1,localPos))
}
},
结果
————————————————
版权声明:本文为CSDN博主「游戏创造者黄昱」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/creator_HY/article/details/104074282