当前位置: 首页 > Web前端 > HTML5

反复跳跃的视线!让我们从向量计算开始吧!基于射线检测的实现!科科斯创造者!

时间:2023-04-05 23:06:07 HTML5

最近有朋友问我如何处理瞄准线上的各种形状?如何实现反复跳跃的视线?最近刚好看到物理系统在《Cocos Creator游戏开发实战》有一个射线检测,于是,基于这个射线检测,写了一个瞄准线效果,重复水平跳跃。一起往下看吧!在文章底部获取完整项目!国际惯例,最终效果第一!在讲解之前,我们需要一些矢量知识,简单介绍一下吧!向量相加,OA+AB=OB向量的点积表示一个向量在另一个向量上的投影。它是一个标量,可以是正数或负数。矢量角度小于90度为正数,等于90度为零,大于90度为负数。向量的叉积,结果是一个向量,它正好垂直于两个向量所形成的平面(右手系),也称为法向量。顺便说一句,这里暂时不使用。接下来进入正题,知道了入射向量(unitvector)和法线向量(unitvector),如何得到反射向量呢?我们将反射向量平移到入射向量的起点,并延伸法向量使其相交。这条延长线的长度恰好是入射向量在法向量上投影的倒数的两倍。然后根据投影和矢量相加,可以推导出反射矢量的计算公式。你清楚吗?不知道也没关系,记住最后一个公式即可,然后进入cocoscreator操作链接。既然是物理系统中的碰撞检测,那么我们在编辑器中添加的是物理系统中的碰撞器,而不是引擎的碰撞器,所以不要搞错了。不动的刚体类型设置为static,添加所有物理碰撞器后如下图所示。要使用物理引擎,自然要开启物理引擎。cc.director.getPhysicsManager().enabled=true;如何进行射线检测?通过起点、入射方向和剩余线段的长度得到射线检测的结果。如果检测到碰撞体,绘制射线段,计算反射方向,重新进行射线检测;如果没有检测到碰撞体,绘制剩余的线段。主要代码如下:/***@descriptioncalculateray*@paramstartLocation起始位置世界坐标系*@paramvector_dir单位方向向量*/privatedrawRayCast(startLocation:cc.Vec2,vector_dir:cc.Vec2){//剩余长度constleft_length=AIM_LINE_MAX_LENGTH-this._cur_length;如果(左长度<=0)返回;//计算直线的结束位置constendLocation=startLocation.add(vector_dir.mul(left_length));//光线测试constresults=cc.director.getPhysicsManager().rayCast(startLocation,endLocation,cc.RayCastType.Closest);if(results.length>0){constresult=results[0];//指定射线与经过的碰撞体相交的点。constpoint=result.point;//绘制入射光线段this.drawAimLine(startLocation,point);//计算长度constline_length=point.sub(startLocation).mag();//计算绘制长度this._cur_length+=line_length;//指定交点处碰撞体表面的单位法线向量。constvector_n=result.normal;//事件单位向量constvector_i=vector_dir;//反射单元向量constvector_r=vector_i.sub(vector_n.mul(2*vector_i.dot(vector_n)));//然后计算下一段this.drawRayCast(point,vector_r);}else{//绘制剩余的线段this.drawAimLine(startLocation,endLocation);}}如何绘制瞄准线的小圆圈?通过结束位置和开始位置计算数量和区间向量,一个一个画小圆圈。参考代码如下。/***@description绘制瞄准线*@paramstartLocation起始位置世界坐标系*@paramendLocation结束位置世界坐标系*/privatedrawAimLine(startLocation:cc.Vec2,endLocation:cc.Vec2){//转换坐标constgraphic_startLocation=this.graphic_line.node.convertToNodeSpaceAR(startLocation);this.graphic_line.moveTo(graphic_startLocation.x,graphic_startLocation.y);//画小圆圈//Intervalconstdelta=20;//方向constvector_dir=endLocation.sub(startLocation);//数量consttotal_count=Math.round(vector_dir.mag()/delta);//每个区间向量vector_dir.normalizeSelf().mulSelf(delta);for(letindex=0;index