近期写了一款基于射线测试的小游戏,本篇会介绍射线测试知识和一些坑,保证大家会用并且避免引擎bug。
国际惯例先上效果
先看一遍官网,在页面的最下面部分。射线测试需要用到物理引擎,接下来开始教学。
物理系统默认是关闭的,如果需要使用物理系统,那么首先需要做的事情就是开启物理系统,否则你在编辑器里做的所有物理编辑都不会产生任何效果。
onLoad () {
cc.director.getPhysicsManager().enabled = true;
},
代码挂载在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
检测射线路径上所有碰撞体,但是会对返回值进行删选,只返回每一个碰撞体距离射线起始点最近的那个点的相关信息,最慢
cc.director.getPhysicsManager().rayCast(p1, p2, cc.RayCastType.Closest);
这句话会出现bug,原因是因为运行加载的时候物理引擎这部分没有加载完成,所以底层封装的变量没有new出来。
解决方法: 加一个计时器。
this.schedule(function() {
this.rayTest()
}, 0.01);
创建一个星星 检测到射线测试的点 自动移动到检测点的位置
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))
}
},
基础教程到这结束了,可以在这基础上增加很多效果,比如用一根光线表示出虚拟的射线做一些动作等。
小编用射线检测做了一款小游戏,还在申请软著中,上线后会出教程并公布源码,感兴趣可以关注微信公众号。
需要本篇的资源请回复关键字:射线测试。