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

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

终于来挖坑了!老规矩!图文+视频讲解!

效果预览

实现步骤

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

引入 PolyBool

PolyBool是什么?对多边形(并集,交集,差,异或)进行运算。(Boolean operations on polygons (union, intersection, difference, xor).)

前往 https://github.com/voidqk/polybooljs 下载。并作为插件脚本。

这个仓库有个 PR 提供了一个声明文件,因为我用的是 TypeScript ,我就把它拿来改改用了。

参考这个库的示例,里面有一个 regions 三维数组记录多边形的信息。

我们也用个三维数组记录当前多边形的形状的数据,并初始化为一个长方形吧!

private _regions: number[][][] = [];
reset() {
    this._regions = [
        [[-480, -320], [-480, 250], [480, 250], [480, -320]]
    ];
}

添加物理链条

先在场景中添加物理节点。

为这个节点初始化一些 cc.PhysicsChainCollider ,并开启物理引擎,顺便开启物理调试模式,方便看效果。

//onLoad() {
cc.director.getPhysicsManager().enabled = true;
cc.director.getPhysicsManager().debugDrawFlags = 1;
for (let index = 0; index < 100; index++) {
    const c = this.node_dirty.addComponent(cc.PhysicsChainCollider);
    c.loop = true;
    c.enabled = false;
}

接着根据_regions的数值,把points传给物理链条。

// draw() {
const chains = this.node_dirty.getComponents(cc.PhysicsChainCollider);
chains.forEach((c) => {
    c.enabled = false;
})
for (let index = 0; index < this._regions.length; index++) {
    const pos = this._regions[index];
    let poly = chains[index];
    if (!poly) {
        poly = this.node_dirty.addComponent(cc.PhysicsChainCollider);
        poly.loop = true;
    }
    poly.points.length = 0;
    poly.points = pos.map((v, i) => {
        const v2 = cc.v2(v[0], v[1])
        return v2;
    });
    poly.enabled = true;
}

看看效果。

开始挖洞!

监听一个节点的触摸事件。

// onLoad() {
this.node_dirty.on(cc.Node.EventType.TOUCH_START, this._touchMove, this);
this.node_dirty.on(cc.Node.EventType.TOUCH_MOVE, this._touchMove, this);

在触摸点周围圈一个多边形(类似画一个圈,不清楚的话可以参考上一篇中的把圆围成一个圈),并使用差集的方法计算新的多边形,计算后再重新画物理链条。

// const DIG_RADIUS = 50;
// const DIG_FRAGMENT = 12;
// _touchMove(touch: cc.Touch) {
const regions = [[]];
const pos = this.node_dirty.convertToNodeSpaceAR(touch.getLocation());

const count = DIG_FRAGMENT;
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([x, y]);
}

const result = PolyBool.difference({
    regions: this._regions,
    inverted: false
}, {
    regions,
    inverted: false
});
this._regions = result.regions;
this.draw();

看看效果。

填充颜色

先画一个多边形,只需先移动到起点,然后逐一划线,就可以了。

// private _drawPoly(ctx, poly) {
poly.forEach((pos, i) => {
    if (i === 0)
        ctx.moveTo(pos.x, pos.y);
    else
        ctx.lineTo(pos.x, pos.y);
    ctx.close();
});

填充思路是基于 canvas 中的 evenodd 规则。

与上面不一样的地方是,我是计算这个多边形被几个大的多边形包围,当是偶数的时候填充泥土的颜色,当是奇数时,填充背景的颜色。

当然,需要注意的是,计数越大的要越后画,这样才能达到最终效果。

// draw() {
const enabled_chains_points=[]
for (let index = 0; index < this._regions.length; index++) {
    // 省略与上面相同 draw
    enabled_chains_points[index] = poly.points;
}
this.graphics.clear(true);
const enabled_chains_points_sort = enabled_chains_points.map((curPoly, curPoly_i) => {
    const count = enabled_chains_points.reduce((pre, nextPoly, nextPoly_i) => {
        if ((curPoly_i != nextPoly_i)) {
            const length = curPoly.length;
            for (let i = 0; i < length; ++i) {
                const p0 = curPoly[i];
                if (!cc.Intersection.pointInPolygon(p0, nextPoly))
                    return pre;
            }
            return pre + 1;
        }
        return pre;
    }, 0);

    return { curPoly, count };
}).sort((a, b) => {
    return a.count - b.count;
})
enabled_chains_points_sort.forEach(({ curPoly, count }) => {
    this.graphics.fillColor = count % 2 === 0 ? cc.Color.ORANGE : cc.Color.BLACK;
    this._drawPoly(this.graphics, curPoly);
    this.graphics.fill();
})

看看效果如何!

优化

< 未完待续 > 可关注【白玉无冰】获取最新进展!

写一篇图文加录一篇视频还是很花时间的,如果有帮助,多多分享(在看)给周边的朋友,帮我涨点粉丝。或者加个鸡腿催更

小结

动手实践!在实践中成长!在模仿中学习!

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

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

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

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

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

我来说两句

0 条评论
登录 后参与评论

相关文章

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

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

    白玉无冰
  • 物理刚体挖洞!另一种实现!

    在 物理挖洞-优化篇 和 物理挖洞-实现篇 中介绍了一种用多边形链条组件(cc.PhysicsChainCollider)实现物理挖洞的方法。这次打算用多边形碰...

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

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

    白玉无冰
  • 物理挖洞!涂抹地形! 优化篇!

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

    白玉无冰
  • Java的强引用,软引用,弱引用,虚引用及其使用场景

    从 JDK1.2 版本开始,Java 把对象的引用分为四种级别,从而使程序能更加灵活的控制对象的生命周期。这四种级别由高到低依次为:强引用、软引用、弱引用和虚引...

    用户3596197
  • IO(上)

    输入流,数据从源数据源流入程序的过程称为输入流。可以理解为从源数据源读取数据到程序的过程。

    Carlos Ouyang
  • 你知道Java的四种引用类型吗?

    在Java中提供了四个级别的引用:强引用,软引用,弱引用和虚引用。在这四个引用类型中,只有强引用FinalReference类是包内可见,其他三种引用类型均为p...

    Java技术江湖
  • 干货 | ES6 系列之我们来聊聊装饰器

           点击上方“腾讯NEXT学院”关注我们 Decorator 装饰器主要用于: 1. 装饰类 2. 装饰方法或属性 1 .装饰类 ...

    腾讯NEXT学位
  • 开发中我们需要遵循的几个设计原则!(转)

    在软件开发中,前人对软件系统的设计和开发总结了一些原则和模式, 不管用什么语言做开发,都将对我们系统设计和开发提供指导意义。本文主要将总结这些常见的原则和具体阐...

    Dawnzhang
  • 开发中我们需要遵循的几个设计原则!

    在软件开发中,前人对软件系统的设计和开发总结了一些原则和模式, 不管用什么语言做开发,都将对我们系统设计和开发提供指导意义。本文主要将总结这些常见的原则和具体阐...

    Java后端技术

扫码关注云+社区

领取腾讯云代金券