今天来实现触摸控制搓牌,先来点熟悉的JS代码。
触摸事件
我们在HelloWorld.js
中添加触摸事件,onLoad中添加以下代码。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17this.node.on(cc.Node.EventType.TOUCH_MOVE, (touch) => {
var location = touch.getLocation();
//计算触摸点与原点(0,0)连线,过其连线中点,并与连线垂直的直线
//注:以扑克牌左下角为原点,需平移(-180,-70)
location.x += -180;
location.y += -70;
//触摸点与原点连线为y=location.y/location.x * x;
//斜率
var k = location.y / location.x;
//连线中点
var mid = cc.v2(location.x / 2, location.y / 2);
//已知斜率+过一点,y-mid.y=-1/k(x - mid.x)
//1/k*x+y-mid.y-mid.x/k=0 由此可知
this.UNI_A = 1 / k;
this.UNI_B = 1;
this.UNI_C = -mid.y - mid.x / k;
}, this);
这里出现的三个变量UNI_A,UNI_B,UNI_C就是我们要传递给shader的。这三个变量是与 触摸点到原点连线L垂直,并且过L中点的直线的三个值,即:
UNI_Ax + UNI_By + UNI_C = 0;
大家根据上图公式推导即可。
传递变量
外部代码给Shader传递变量,分两步即可:
- 获取变量地址
- 为变量赋值
使用代码如下:
1 | this.glProgram.UNI_A = gl.getUniformLocation(this.glProgram.getProgram(), "UNI_A"); |
我们先准备好变量,并且在TOUCH_MOVE
中实时计算变量值,glNode draw方法中使用前刷新变量值。
除此之外Shader中也需要一些小调整,只需要给传递的变量改成uniform
修饰即可。
const float UNI_D = 10;
这个圆弧区域距离的值,50的话,有些边界效果不是很好,我这里改成了10.
差点忘了,释放资源1
2
3
4
5
6
7
8
9
10
11//结束需要移除
onDestroy: function () {
console.log("onDestroy");
gl._deleteBuffer(this._backVertsBuffer)
gl._deleteBuffer(this._backTexsBuffer)
gl._deleteBuffer(this._faceVertsBuffer)
gl._deleteBuffer(this._faceTexsBuffer)
this.glProgram.release();
this._spCardFace.release();
this._spCardBack.release();
},
大功告成!!
上一段视频效果:
总结
关键还是解决问题的思路,以及对顶点Shader和片元Shader的理解。这不是唯一的解决方式,很多小细节可以调整。这里只做了左下角,但是另外的三个角与复杂的触摸控制也都可以借此实现。
是不是突然感觉代数、几何没白学~~~
完整代码下载:
点击下载
为方便新手,我把完整项目放到GitHub了: