专栏首页白玉无冰物理挖洞!涂抹地形! 优化篇!

物理挖洞!涂抹地形! 优化篇!

回顾

物理挖洞!涂抹地形! 小鳄鱼爱洗澡!百战天虫 !Cocos Creator ! 这篇文章介绍了如何实现。

整体思路是先使用 PolyBool 计算多边形,接着使用 cc.PhysicsChainCollider 将多边形围起来,最后使用 cc.Graphics 将整个地形绘制出来。

优化

物理引擎

调低物理引擎的步长和处理的迭代次数。

// onLoad() {// 开启物理步长的设置cc.director.getPhysicsManager().enabledAccumulator = true;// 物理步长,默认 FIXED_TIME_STEP 是 1/60cc.PhysicsManager.FIXED_TIME_STEP = 1 / 30;// 每次更新物理系统处理速度的迭代次数,默认为 10cc.PhysicsManager.VELOCITY_ITERATIONS = 8;// 每次更新物理系统处理位置的迭代次数,默认为 10cc.PhysicsManager.POSITION_ITERATIONS = 8;

多边形的顶点

计算的过程中,可能会带有小数,我们可以把所有的点都优化到整数范围。

//const DIG_OPTIMIZE_SIZE = 1;private _optimizePoint(point) {    return [Math.floor(point[0] * DIG_OPTIMIZE_SIZE) / DIG_OPTIMIZE_SIZE, Math.floor(point[1] * DIG_OPTIMIZE_SIZE) / DIG_OPTIMIZE_SIZE];}

DIG_OPTIMIZE_SIZE也可以改大一点,就是把图中红色的点都算作灰色的点。

多边形的边

需要剔除一些长度为0的边。

去除一些共线的边,这边用到了向量的叉乘,关于向量的点乘和叉乘介绍可以参考之前的这一篇文章

private _optimizeRegions() {    const regions = [];    for (let index = 0; index < this._regions.length; index++) {        const pos = this._regions[index];        const newPos = [];        pos.forEach((p, i) => {            p = this._optimizePoint(p);            const p_pre = this._optimizePoint(pos[(i - 1 + pos.length) % pos.length]);            const p_next = this._optimizePoint(pos[(i + 1) % pos.length]);            const vec1 = cc.v2(p[0] - p_pre[0], p[1] - p_pre[1]);            const vec2 = cc.v2(p_next[0] - p[0], p_next[1] - p[1]);            if (vec1.lengthSqr() != 0 && vec2.lengthSqr() != 0 && vec1.cross(vec2) != 0) {                newPos.push(p);            }        })
        if (newPos.length > 2) {            regions.push(newPos);        }    }    this._regions = regions;}

触摸平滑连续

当手指滑动时,如果 touch_move 的抓取的两个点距离比较大的话,就会出现不平滑的情况。

这里用到向量的点乘帮助我们解决这个问题,不清楚向量计算参考之前的这一篇文章

算出两个触摸点和各自边的向量,与移动的方向向量关系,可以确定整个多边形的点。

当两个偏移点距离太小我们就忽略。

// private _touchMove(touch: cc.Touch) {const regions = [[]];const pos = this.graphics.node.convertToNodeSpaceAR(touch.getLocation());const delta = touch.getDelta();const count = DIG_FRAGMENT;if (delta.lengthSqr() < 5) {    for (let index = 0; index < count; index++) {        const r = 2 * Math.PI * index / count;        const x = pos.x + DIG_RADIUS * Math.cos(r);        const y = pos.y + DIG_RADIUS * Math.sin(r);        regions[0].push(this._optimizePoint([x, y]));    }} else {    const startPos = pos.sub(delta);    for (let index = 0; index < count; index++) {        const r = 2 * Math.PI * index / count;        let vec_x = DIG_RADIUS * Math.cos(r);        let vec_y = DIG_RADIUS * Math.sin(r);        let x, y;        if (delta.dot(cc.v2(vec_x, vec_y)) > 0) {            x = pos.x + vec_x;            y = pos.y + vec_y;        } else {            x = startPos.x + vec_x;            y = startPos.y + vec_y;        }        regions[0].push(this._optimizePoint([x, y]));    }}

调用 PolyBool 的优化

在这个库 https://github.com/voidqk/polybooljs 中提到了更高级的用法。

// private _touchMove(touch: cc.Touch) {const seg1 = PolyBool.segments({    regions: this._regions,    inverted: false});const seg2 = PolyBool.segments({    regions,    inverted: false});const comb = PolyBool.combine(seg1, seg2);const result = PolyBool.polygon(PolyBool.selectDifference(comb));

其他

另一种实现思路

首先创建一堆刚体铺满所有泥土,在监听到触摸事件后,移除对应位置的刚体。

算法参考

多边形算法我没有深究其实现,如果要做到更好的优化,可能需要自己去实现其中的算法,可以把上面的优化点融入到算法中。以下是一些相关算法的参考资料。

•http://www.cs.ucr.edu/~vbz/cs230papers/martinez_boolean.pdf•https://hal.inria.fr/inria-00517670/document•https://www.sciencedirect.com/science/article/abs/pii/S0965997813000379

可能的问题

web端测试感觉比较流畅,未在native端测试,也没有在微信小游戏端做测试。

小结

可能有其他更好的方案去实现这个功能,如果你有更好的方案,欢迎分享!欢迎加入qq交流群(859642112)一起讨论,群里收集了一些我认为还不错的书籍和资料。

以上为白玉无冰使用 Cocos Creator v2.3.3 开发"物理挖洞!涂抹地形! 优化 "的技术分享。如果对你有点帮助,欢迎分享(在看)给身边的朋友。

前文链接:物理挖洞!涂抹地形!

完整代码: https://github.com/baiyuwubing/cocos-creator-examples/tree/master/dig_hole

本文分享自微信公众号 - 白玉无冰(lamyoung-com),作者:lamyoung

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-04-27

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 物理挖洞!涂抹地形! 小鳄鱼爱洗澡!百战天虫 !Cocos Creator !

    整体思路是先使用 PolyBool 计算多边形,接着使用 cc.PhysicsChainCollider 将多边形围起来,最后使用 cc.Graphics 将整...

    白玉无冰
  • 拇指投篮 ! Cocos Creator 3D !

    为了能达到好的投篮效果,在网上找了一个投篮机参数,大致按照实际参数设置篮框大小,球的大小,以及篮框的位置。

    白玉无冰
  • 图片/文字 的渐变色实现!

    在 cc.Spirte 或 cc.Label 添加脚本 ColorAssembler2D 。

    白玉无冰
  • 物理挖洞!涂抹地形! 小鳄鱼爱洗澡!百战天虫 !Cocos Creator !

    整体思路是先使用 PolyBool 计算多边形,接着使用 cc.PhysicsChainCollider 将多边形围起来,最后使用 cc.Graphics 将整...

    白玉无冰
  • spark2 sql读取数据源编程学习样例1

    问题导读 1.dataframe如何保存格式为parquet的文件? 2.在读取csv文件中,如何设置第一行为字段名? 3.dataframe保存为表如何指定b...

    用户1410343
  • 洛谷P3372 【模板】线段树 1(树状数组)

    $= sum_{i = 1}^x (x+1)d_i - \sum_{i = 1}^x id_i$

    attack
  • java_字节流、字符流

    java.io.OutputStream 抽象类是表示字节输出流的所有类的超类,将指定的字节信息写出到目的地。它定义了字节输出流的基本共性功能方法。

    咕咕星
  • Android 蓝牙4.0

    用户1733354
  • 图片/文字 的渐变色实现!

    在 cc.Spirte 或 cc.Label 添加脚本 ColorAssembler2D 。

    白玉无冰
  • H5Canvas入门(上)(下)

    前言 本系列教程是专门给设计师写的快速入门教程,只要一步步跟随本教程,即可轻松进入编程的世界。 学习成果 用canvas制作带有图案的封面。 a、了解HTML、...

    mixlab

扫码关注云+社区

领取腾讯云代金券