lufy 发表于 2017-5-16 12:13:51

关于drawTriangles的优化

有不少人通过各种方式问我关于drawTriangles出现白线的问题,这其实是一个老问题了
用过drawTriangles的朋友,大多都看过我的一篇文章
HTML5高级编程之图形扭曲及其应用
http://lufylegend.com/forum/forum.php?mod=viewthread&tid=94
drawTriangles函数的原理就如下图这样,将两次变形通过clip裁剪一下,然后接在一起
http://lufylegend.com/lufylegend_blog_img/png/12.png
但是,canvas的clip有个不足,就是对接起来并不那么完美,两个clip之间出现了一条缝,所以drawTriangles最终的效果会是这样
http://lufylegend.com/lufylegend_blog_img/png/84.png
这就尴尬了....:dizzy:
而其实这一效果在不同浏览器中也是不一样的,有的浏览器会好一些,我一直在等待浏览器自身的完善,能够解决这个问题
但是很长时间过去了,估计这个问题不一定会被修复了,实际上图片扭曲是咱们自己要这么做的,人家clip的用途也并不是为了实现这个效果,所以,还是自己想想办法如何才能解决吧
要说完美的解决方案,我一时也想不到(也不是一时了,好几年了都...),不过投机取巧的方案倒是有的,比如像下面这样
http://lufylegend.com/lufylegend_blog_img/png/83.png
左边的三角形,如图,把其中三角形的两个点分别移动,将三角形扩大,我们多画一部分,这样和第二个三角形对接的时候,那条缝就会被遮住
而右边的三角形,我们采取同样的方法,把其中一个点移动,也将三角形扩大,实际上右边的三角形比较麻烦,因为和这个三角形对接的是下一组三角形(两个三角形是一组,这个应该不用我多做解释了),而且这个点一旦移动,变形效果就会有偏差
另外,我为了说明效果,移动的距离比较远,实际代码中我们必须只能移动一个单位或者两个单位,否则变形就会出现较大的偏差
好了,原理就是这个原理了,接下来修改drawTriangles的代码部分                LGraphics.prototype.drawTriangles = function (ve, ind, u, tn, lco) {
                        var s = this;
                        var i, j, l = ind.length, c;
                        s.setList.push(function (c) {
                                var v = ve, a, k, sw;
                                for (i = 0, j = 0; i < l; i += 3) {
                                        a = 0;
                                        c.save();
                                        c.beginPath();
                                        c.moveTo(v * 2], v * 2 + 1]);
                                        c.lineTo(v * 2] + (i % 6 == 0 ? 1 : 0), v * 2 + 1]);
                                        c.lineTo(v * 2] + (i % 6 == 0 ? 0 : 2), v * 2 + 1] + 2);
                                        c.lineTo(v * 2], v * 2 + 1]);
                                        c.closePath();
                                        if (tn) {
                                                c.lineWidth = tn;
                                                c.strokeStyle = lco;
                                                c.stroke();
                                        }
                                        c.clip();
                                        if (i % 6 == 0) {
                                                sw = -1;
                                                var w = (u * 2] - u * 2]) * s.bitmap.width;
                                                var h = (u * 2 + 1] - u * 2 + 1]) * s.bitmap.height;
                                                if (j == 0 && w < 0) {
                                                        for (k = i + 9; k < l; k += 3) {
                                                                if (u * 2 + 1] == u * 2 + 1]) {
                                                                        j = k - i;
                                                                        break;
                                                                }
                                                        }
                                                        if (j == 0) {
                                                                j = l - i;
                                                        }
                                                        w = (u * 2] - u * 2]) * s.bitmap.width;
                                                }
                                                if (i + j >= l) {
                                                        w = (u * 2] - u * 2]) * s.bitmap.width;
                                                        sw = u * 2] == 1 ? 0 : s.bitmap.width * u * 2] + w;
                                                        if (sw > s.bitmap.width) {
                                                                sw -= s.bitmap.width;
                                                        }
                                                } else {
                                                        sw = s.bitmap.width * u * 2];
                                                }
                                                sh = s.bitmap.height * u * 2 + 1];
                                                if (h < 0) {
                                                        h = (u * 2 + 1] - u * 2 + 1]) * s.bitmap.height;
                                                        sh = 0;
                                                }
                                                if(sw > 0){
                                                        sw -= 1;
                                                }
                                                if(sh > 0){
                                                        sh -= 1;
                                                }
                                                var t1 = (v * 2] - v * 2]) / w;
                                                var t2 = (v * 2 + 1] - v * 2 + 1]) / w;
                                                var t3 = (v * 2] - v * 2]) / h;
                                                var t4 = (v * 2 + 1] - v * 2 + 1]) / h;
                                                c.transform(t1, t2, t3, t4, v * 2], v * 2 + 1]);
                                                w += 1;
                                                h += 1;
                                                c.drawImage(s.bitmap.image,
                                                                        s.bitmap.x + sw,
                                                                        s.bitmap.y + sh,
                                                                        w, h,
                                                                        0, 0,
                                                                        w, h);
                                        } else {
                                                var w = (u * 2] - u * 2]) * s.bitmap.width;
                                                var h = (u * 2 + 1] - u * 2 + 1]) * s.bitmap.height;
                                                if (j == 0 && w < 0) {
                                                        for (k = i + 9; k < l; k += 3) {
                                                                if (u * 2 + 1] == u * 2 + 1]) {
                                                                        j = k - i;
                                                                        break;
                                                                }
                                                        }
                                                        if (j == 0) {
                                                                j = l - i;
                                                        }
                                                        w = (u * 2] - u * 2]) * s.bitmap.width;
                                                }
                                                if (i + 1 + j >= l) {
                                                        w = (u * 2] - u * 2]) * s.bitmap.width;
                                                        sw = u * 2] == 1 ? 0 : s.bitmap.width * u * 2] + w;
                                                        if (sw > s.bitmap.width) {
                                                                sw -= s.bitmap.width;
                                                        }
                                                } else {
                                                        sw = s.bitmap.width * u * 2];
                                                }
                                                sh = s.bitmap.height * u * 2 + 1];
                                                if (h < 0) {
                                                        h = (u * 2 + 1] - u * 2 + 1]) * s.bitmap.height;
                                                        sh = 0;
                                                }
                                                var t1 = (v * 2] - v * 2]) / w;
                                                var t2 = (v * 2 + 1] - v * 2 + 1]) / w;
                                                var t3 = (v * 2] - v * 2]) / h;
                                                var t4 = (v * 2 + 1] - v * 2 + 1]) / h;
                                                c.transform(t1, t2, t3, t4, v * 2], v * 2 + 1]);
                                                c.drawImage(s.bitmap.image,
                                                                s.bitmap.x + sw,
                                                                s.bitmap.y + sh,
                                                                w+2, h+2,
                                                                0, -h,
                                                                w+2, h+2);
                                        }
                                        c.restore();
                                }
                        });
                };具体改了什么,大家自己对照下引擎源码吧
把这段代码加到你的js里就能覆盖引擎中的处理了,引擎下次更新我会把它加进去(不要问引擎什么时候更新,我保证引擎不会死了...)
说了半天效果如何呢,看下图吧
http://lufylegend.com/lufylegend_blog_img/png/84.png
http://lufylegend.com/lufylegend_blog_img/png/85.png
对照下上面的图,虽然不算完美,是不是效果也好了很多了

smallnews 发表于 2017-5-16 12:24:15

厉害了!!!

zyflzxy 发表于 2017-6-15 09:44:41

修改后是没有线了,但是有截取的图片会错位,没有之前的好。

lufy 发表于 2017-6-15 10:17:26

zyflzxy 发表于 2017-6-15 09:44 static/image/common/back.gif
修改后是没有线了,但是有截取的图片会错位,没有之前的好。
帖子里说了,优化的方法就是错位1px来处理
但是跟其他敌方应该没有影响吧,你指的截取图片是什么?

zyflzxy 发表于 2017-6-15 14:42:00

lufy 发表于 2017-6-15 10:17 static/image/common/back.gif
帖子里说了,优化的方法就是错位1px来处理
但是跟其他敌方应该没有影响吧,你指的截取图片是什么? ...

错位1PX明白了,错位会影响图片的变化效果,感觉没有之前的好。因为在微信端是没有线的。

yorhomwang 发表于 2017-6-15 19:34:37

马上要读大学了,想抽点时间帮lufy前辈做点什么?前辈有什么需求吗?我尽力去做吧。
我对引擎的设想是将来提供一个完善的系统,也就是说有一个很大的社区可以给开发者提供讨论,源码分享,教程,甚至组件(比如手柄,按钮等),还有各式各样的开发工具。

lufy 发表于 2017-6-16 14:21:53

yorhomwang 发表于 2017-6-15 19:34 static/image/common/back.gif
马上要读大学了,想抽点时间帮lufy前辈做点什么?前辈有什么需求吗?我尽力去做吧。
我对引擎的设想是将来 ...

兄弟可以抽时间多写几个游戏分享一下,
一来锻炼自己,二来对引擎的推广也会起到一定作用

zyflzxy 发表于 2018-3-7 12:08:28

LUFY,这个能再优化下吗,感 觉还是有点问题。

Rain_Golden 发表于 2019-3-24 14:25:17

我分析了一下白线的原因,就是因为clip边缘的1px被半透明化。把半透明改为不透明,白线消失,虽然解决了问题。但这样就不支持扭曲半透明图片了

lanny886 发表于 2019-6-19 16:22:05

Rain_Golden 发表于 2019-3-24 14:25 static/image/common/back.gif
我分析了一下白线的原因,就是因为clip边缘的1px被半透明化。把半透明改为不透明,白线消失,虽然解决了问 ...

请问如何设置
页: [1] 2
查看完整版本: 关于drawTriangles的优化