首页 > 其他 > 详细

物理挖洞之分块 !Cocos Creator !

时间:2020-06-17 11:54:54      阅读:72      评论:0      收藏:0      [点我收藏+]

减少多边形计算!画饼分之~

效果预览

技术分享图片

回顾

物理挖洞之链条!实现!(含视频讲解) 中介绍了用 PolyBool 和链条组件(cc.PhysicsChainCollider)实现物理挖洞的方法。

虽说这种方案可能不是最佳方案,但里面有一种 evenodd 的思想,觉得不错的。

技术分享图片

物理挖洞之链条!优化!(含视频讲解) 中介绍了几个优化的地方。

其中,单位化的思想和平滑移动的思想在后续一直被使用。

技术分享图片

不过,多边形链条组件有一个问题,容易穿透。

接着,经过多次查找和分析,在物理挖洞之多边形!实现! 中介绍用多边形碰撞组件(cc.PhysicsPolygonCollider)去实现物理挖洞。

整体思路是,先用 Clipper 去计算多边形 (效率比 PolyBool 高),接着用 poly2tri 将多边形分割成多个三角形,最后用多边形刚体填充。

技术分享图片

但是呢,poly2tri 限制比较多,物理挖洞之多边形!填坑! 中介绍了填坑之路。

并利用 maskgraphics 实现好看的纹理。

技术分享图片

当然,还有群内小伙伴们讨论分享的3D效果,在上面的基础上,修改了一个物理挖洞之3D效果,感谢各位小伙伴的分享!

技术分享图片

强烈建议按顺序阅读上面几篇文章,有助于更好的理解这篇的文章哦!

实现原理

整体思路是对区域进行分块,点击的时候判断是对哪个区域块有操作,再对这些区域块进行多边形计算,最后再绘制所有的多边形。

技术分享图片

这里与物理挖洞之多边形!实现! 中的区别是少了一步 poly2tri,这是怎么做到的?

首先得明白一点,之前使用 poly2tri 是因为会有内多边形出现。

所以,在分块的时候,只要满足分块的尺寸小于挖洞的尺寸,这样就不会出现内多边形了。

技术分享图片

如何判断点击的是哪个区域呢?

在初始化的时候,用一个2D矩形(cc.Rect)数组记录每一个分块的信息。

private _rects: cc.Rect[] = [];

技术分享图片

当点击的时候会生成一个多边形(参考物理挖洞之链条!优化! 中的触摸平滑连续)数据。

对于这个多边形的每个点,计算出坐标 xy 的最大值和最小值。

然后就可以算出这个的多边形的矩形(aabb (Axis-Aligned Bounding Box))。

let xMin = Number.MAX_SAFE_INTEGER, xMax = Number.MIN_SAFE_INTEGER, yMin = Number.MAX_SAFE_INTEGER, yMax = Number.MIN_SAFE_INTEGER;
// 计算最小最大值
xMin = p.x < xMin ? p.x : xMin;
yMin = p.y < yMin ? p.y : yMin;
xMax = p.x > xMax ? p.x : xMax;
yMax = p.y > yMax ? p.y : yMax;
// 得出矩形
const rect_r = cc.Rect.fromMinMax(cc.v2(xMin, yMin), cc.v2(xMax, yMax));

技术分享图片

再用这个矩形和初始化矩形做一次相交判断,这样就可以粗略的确定要计算的块了。

for (let index = 0; index < this._rects.length; index++) {
    const rect = this._rects[index];
    if (rect.intersects(rect_r)) {
        this.polyEx.pushCommand(‘polyDifference‘, [regions, index])
    }
}

技术分享图片

多边形计算用的是 Clipper ,使用接口可以参考官网或者物理挖洞之多边形!

// polyDifference(poly: cc.Vec2[], index: number) {
// 计算新的多边形
// https://sourceforge.net/p/jsclipper/wiki/documentation
const cpr = new ClipperLib.Clipper(ClipperLib.Clipper.ioStrictlySimple);
const subj_paths = this._polys[index];
const clip_paths = [this._convertVecArrayToClipperPath(poly)]
cpr.AddPaths(subj_paths, ClipperLib.PolyType.ptSubject, true);
cpr.AddPaths(clip_paths, ClipperLib.PolyType.ptClip, true);
const subject_fillType = ClipperLib.PolyFillType.pftEvenOdd;
const clip_fillType = ClipperLib.PolyFillType.pftEvenOdd;
const solution = new ClipperLib.Paths();
cpr.Execute(ClipperLib.ClipType.ctDifference, solution, subject_fillType, clip_fillType);
this._polys[index] = solution || [];

在所有分块计算之后,最后整体绘制多边形碰撞体和纹理。

// private draw() {
ctx.clear();
for (let index = 0; index < this._polys.length; index++) {
    const polygons = this._polys[index];
    for (let index2 = 0; index2 < polygons.length; index2++) {
        const polygon = polygons[index2];
        let c = this._physicsPolygonColliders[_physicsPolygonColliders_count];
        c.points = this._convertClipperPathToVecArray(polygon);
        c.apply();

        for (let index3 = 0; index3 < c.points.length; index3++) {
            const p = c.points[index3];
            if (index3 === 0) ctx.moveTo(p.x, p.y);
            else ctx.lineTo(p.x, p.y);
        }
        ctx.close();
    }
}
ctx.fill();

当然,群(859642112)内小伙伴 @吴先生 也实现了这个分块,分块计算多边形同时,也进行分块绘制,欢迎加群一起讨论!

小结

生命不息,挖坑不止!

以上为白玉无冰使用 Cocos Creator v2.3.3 开发"物理挖洞之分块!"的技术分享。如果对你有点帮助,欢迎分享给身边的朋友。

天下事有难易乎?为之,则难者亦易矣;不为,则易者亦难矣。人之为学有难易乎?学之,则难者亦易矣;不学,则易者亦难矣。 --《为学》


原文链接
完整代码(见readme)
原创文章导航

物理挖洞之分块 !Cocos Creator !

原文:https://www.cnblogs.com/lamyoung/p/13151315.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!