上一篇是:尝试搭建webgl游戏引擎-渲染管线
本篇记录一下简单的点击事件
要做游戏,交互肯定是必不可少的。
最简单的交互就是点击物体,然后做出相应的反馈。
本篇简单实现了一下球形碰撞盒的射线检测。
场景点击
因为webgl是基于canvas的。
canvas又是htmlElement。
htmlElement就支持addEventListener添加相关交互事件。
这里注册的是mousedown,mouseup,mousemove相关的鼠标事件。
添加一个input的类,用来管理鼠标事件。
实现了一个eventmanager的事件管理类。
然后其它节点可以通过eventmanager来注册事件。
input里注册了装饰了鼠标事件为touch事件,然后向外发送事件。
要实现场景的点击就非常简单了,只需要向input类注册touch事件即可。
产生射线
射线是一个有起点和终点的线段。(当然也可以没有终点)
在屏幕任何位置点击后,就会创建一个从以摄像机位置为起点,经过屏幕位置到世界坐标的折算位置,然后向屏幕内射去。
运算代码是:
if (startPoint instanceof Vec2) {
const camera = Director.instance.curCamera!;
const r = 2 * camera.near * Math.tan(Math.PI * (camera as any).fovY / 360) / Director.instance.size.h;
const y = startPoint.y * r;
const x = startPoint.x * r;
this.startPoint.set(x, y, camera.container!.worldPosition.z - camera.near);
Vec3.sub(this.direction, this.startPoint, camera.container!.worldPosition);
this.startPoint.set(camera.container!.worldPosition);
}
射线和球的碰撞
要判断一条线是否和球相交非常简单。
只需要判断球心到线的距离是否小于等于自己的半径即可。
如果小于或者等于,则相交。则产生碰撞。
但是实现起来还是要费点工夫
首先需要获得摄像机指向球心的向量A。
然后和射线点乘,获得在射线上的投影距离。
然后投影距离乘以归一化的射线向量,得到投影到射线上的向量B。
然后A减去B就得到了垂直矢量,求其模就行了。
总结
球形射线检测还是比较简单,但是如果有很多个物体,还是需要考虑到性能的。
那是之后需要研究的内容了,比如4叉树。
下一篇研究一下正方体碰撞。