【Cocos Creator 实战】04 - 如何给拼图加上吸附效果

继续继续。

上一篇地址:【Cocos Creator 实战】03 - 如何「拿起」拼图游戏的每块图片

概览

主要内容

来看看今天要做的内容:

  • Cocos Creator 中坐标系的基本知识
  • 如何给拼图游戏加上吸附效果

你问我什么是吸附?我咋解释,直接看看效果吧:

在这里插入图片描述

项目资源

推荐大家先把项目 clone 到本地,然后参考着代码来看本篇文章。
我的每篇文章会对应一个分支,大家直接看对应的分支就可以,master 对应的是最新的内容,会整合各个分支。
演示地址也是对应每篇文章独立部署的。

开搞

Cocos Creator 中的坐标系

Creator 中的坐标系原则与笛卡尔坐标系相同,原理如下图:

在这里插入图片描述
即,如果面向屏幕的话,向右是 x 轴 正方向,向上是 y 轴 正方向,垂直于屏幕的是 z 轴 正方向。

结合我们上一篇文章说的 zIndex,这回是不是理解的更好了。

那对于 Creator 中来讲,我们的坐标系可以按照下图来画:
在这里插入图片描述
注意几点哈:

1、z轴 是垂直于屏幕的,有点立体空间的思维,不是斜着的
2、我图上每个轴的剪头的粗细没有关系,那是我使用工具的问题,主要看方向
3、我把三个轴的交叉点放在了正中间,那他们交叉点的位置坐标就是 (0,0,0)

我们先不考虑 z 轴,为什么 xy 轴(0,0) 坐标在中间呢?

这就涉及到下一个知识点:锚点(Anchor)

锚点(Anchor)

锚点其实主要有两个作用:

1、表示用自身节点的哪个位置作为在父节点中设置位置的点
2、表示自身节点本地坐标系的初始原点位置,即子节点使用的坐标系的原点位置

是不是有点蒙圈,我们看看例子(请忽略我粗糙的绘画技巧,对灯发誓,我尽力了):

在这里插入图片描述
假设在一个坐标系里面,有三个节点分别是红黄蓝,他们的锚点分别如上图标注,那么他们在坐标系中的位置将会如图中所示:

  • 锚点(0,0) 的会把自己左下角的位置作为在父节点中设置位置的点
  • 锚点(0.5,0.5) 的会把自己中心位置作为在父节点中设置位置的点
  • 锚点(1,1) 的会把自己右上角的位置作为在父节点中设置位置的点

同样的,该位置(左下、中心、右上)也是作为其子节点所使用坐标系的原点,如图上所画。

明白了么,刚开始没懂没事,其实锚点不只是从0到1,任何数值都可以。

目前我们需要的比较简单,如果大家理解起来实在困难的话,就先理解一下 (0.5,0.5),记住所有节点默认的位置都是指其中心点的位置就可以了。

我们的项目也都是使用的默认的 (0.5,0.5)

我的建议也是,除非你真的明白了这个东西是干什么的,不然就用默认的就好了,一般也没必要设置。

吸附规则

上面说了那么多,都是为了解释下面的吸附规则。

其实设计吸附的规则有很多,你也可以根据自己的理解写一套自己的算法出来,但无论哪种算法,都离不开节点位置的计算,而节点位置的的计算又肯定离不开上面的两个知识点:坐标系、锚点。

下来来说说我设计的吸附规则:

1、首先我们能得到每张拼图的位置(Position),即每张图的正中间
在这里插入图片描述
2、我们把这些点扩充一下,把每张图片相邻一个图片位置的点也标注出来:

在这里插入图片描述
这些点目前已经显示在屏幕之外了,不用管,位置肯定在那,只是屏幕没显示下而已。

3、我们以这些点为中心,各自画一个半径为 100 的圆(图中黄色部分)

在这里插入图片描述
大家不要看画功啊,领会精神。

4、然后我们就可以设计,当一块拼图被拿起又放下的时候,如果他的位置(Position)落在了我们这里某一个黄色圆圈内,那我们就把他的位置自动移动到该黄色圆圈对应的红色中心点上,即吸附过去。

在这里插入图片描述
比如上图中右下角绿色的点表示右下角拼图的位置,他落在了其中一个黄色圈内,那他就要自动移动到黄圈中的红点位置,完成吸附。

当然,这个位置可以是写死的,就是每个图片会被吸附的位置在程序初始化的时候就指定,我们也可以做成灵活的,在放下拼图的时候动态计算所有节点的周围的位置,这样能做到拼图的位置可以随意变换,效果好一点。

毕竟我们是要打造全世界最好的拼图游戏的,体验要好。

核心代码

首先,修改 item.js 文件,在拖拽完成的回调中,把当前拖拽的节点作为参数返回去:

        this.node.on(cc.Node.EventType.TOUCH_END, function () {
            this.opacity = 255;

            self.moveEndCb = self.moveEndCb || function () {
            };
            self.moveEndCb(self.node); // 把当前节点作为参数返回去
        }, this.node);

然后,修改 item-manager.js 文件中拖放结束的回调方法:

    __moveEnd(node) {
        console.info('end');

        let picHeight = node.height;
        let picWidth = node.width;
        let nodeVec = cc.v2({x: node.position.x, y: node.position.y});
        let itemManager = node.parent.getComponent('item-manager');
        let conditions = [
            {x: picWidth, y: 0},
            {x: (-1) * picWidth, y: 0},
            {x: 0, y: picHeight},
            {x: 0, y: (-1) * picHeight},
        ];

        for (let i = 0; i < itemManager.items.length; i++) {
            let itemNode = itemManager.items[i].node;
            let itemPos = itemNode.position;
            let isMoved = false;

            for (let j = 0; j < conditions.length; j++) {
                let con = conditions[j];
                let targetVec = cc.v2({
                    x: itemPos.x + con.x,
                    y: itemPos.y + con.y
                });
                let distance = targetVec.sub(nodeVec).mag();
                if (distance > 100) continue; // 100即为上面图中黄色圆圈的半径

                isMoved = true;

                let action = cc.moveTo(0.1, targetVec);
                node.runAction(action);
            }

            if (!isMoved) continue;
            break;
        }

        cc.loader.loadRes('sound/drop', cc.AudioClip, function (err, clip) {
            cc.audioEngine.playEffect(clip, false);
        });
    },

我们的吸附位置,即上面图中红点的位置是实时计算的,获取各个节点位置要先获取到 item-manager

let itemManager = node.parent.getComponent('item-manager');

那对应的各个节点就可以直接拿出来了:

let itemNode = itemManager.items[i].node;

conditions 表示每个拼图对应的四个点的相对位置,分别是上下左右各距离一个图片的位置。

这里我们是用过 Vec2 也就是 cc.v2 的方式来表示节点的位置的,因为这样能比较方便的计算两个节点间的距离。

let distance = targetVec.sub(nodeVec).mag();
if (distance > 100) continue;

上面的 100 就是我们黄色圆的半径,大家可以根据需要灵活改变,但是要合理哈,太小了起不到吸附效果,太大的话,嘿嘿,你可以设置成 10000 看看效果。

还有最后一个,移动节点的动画,我们通过 动作(action) 来实现:

let action = cc.moveTo(0.1, targetVec);
node.runAction(action);

这里就是表示该节点会用 0.1s 移动到(moveTo) targetVec 位置,好理解吧。

关于动作,要讲的话会有很多,这里大家先简单了解一下就好。

总结

知识点

1、Cocos Creator 中的坐标系
2、锚点的概念
3、设计了一套吸附规则
4、简单接触了 Vec2
5、简单接触了 动作(Action)

下一步

这篇文章花了我将近3天时间,其实代码很好写,但是想把其中的原理讲清楚,还真是麻烦。

可能理解能力比较好的朋友会觉得我写的啰嗦,那没办法,照顾一下牛顿同学吧。

想想下一步,我们是不是也该设计一下胜利规则了,不然玩了半天,也都是自嗨,都不知道拼的对不对。

那么,如何判断拼图游戏已经结束(胜利)呢?

请听下回分解吧。

下一篇地址:【Cocos Creator 实战】05 - 如何判断拼图完成(胜利)

Cocos Creator是一款面向游戏开发者的跨平台游戏开发工具,它集成了Cocos2d-x游戏引擎和Cocos Studio编辑器,支持多种平台上的游戏开发,如iOS、Android、Windows等。 消灭星星是一款基于Cocos Creator开发的游戏。在游戏中,玩家需要消除屏幕上的星星,以获得分数。游戏开始时,屏幕上会随机生成一些星星,玩家可以通过点击相连的星星来消除它们。消除的星星越多,得到的分数就越高。玩家可以通过不断消除星星来刷新高分记录,挑战自己的极限。 在消灭星星游戏中,Cocos Creator提供了丰富的功能和工具,为游戏开发者提供了便利。开发者可以使用Cocos Creator的图形界面编辑器来创建游戏场景、导入资源和设置游戏规则等。同时,Cocos Creator还提供了强大的脚本编写功能,开发者可以使用JavaScript或TypeScript编写游戏逻辑,实现游戏中的各种功能。 除了基本的消除星星玩法,Cocos Creator还支持添加特殊道具、关卡设计、人物角色等功能。开发者可以根据自己的需求,自定义游戏的玩法和功能,使游戏更加有趣和有挑战性。 总而言之,Cocos Creator游戏开发工具提供了强大的功能和便捷的开发环境,使开发者可以轻松地开发出各种各样的游戏,包括消灭星星这样的小而精致的休闲游戏。无论是想要学习游戏开发还是实现自己的游戏创意,Cocos Creator都是一个不错的选择。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值