cocos2d-x 单指拖放,双指缩放

这篇博客介绍了如何在cocos2d-x游戏中实现单指拖放功能和双指缩放功能。在双指缩放的过程中,重点强调了必须使用缩放后的尺寸来计算节点的锚点和边界处理,以确保正确的行为。

1 单点拖放
这里写图片描述

2.双指缩放
这里写图片描述

代码如下

void GameScene::onTouchesMoved(const std::vector<Touch*>& touches, Event  *event)
{
    auto winSize = Director::getInstance()->getWinSize();
    if(touches.size() > 1)        // 多点进行缩放
    {
        // 得到当前两触摸点
        auto point1 = touches[0]->getLocation();
        auto point2 = touches[1]->getLocation();
        // 计算两点之间得距离
        auto currDistance = point1.distance(point2);
        // 计算两触摸点上一时刻之间得距离
        auto prevDistance = touches[0]->getPreviousLocation().distance(touches[1]->getPreviousLocation());
        // 两触摸点与原点的差向量,pointVec1和pointVec2是相对于bgSprite的位置
        auto pointVec1 = point1  - bgOrigin;
        auto pointVec2 = point2  - bgOrigin;
        // 两触摸点的相对中点
        auto relMidx = (pointVec1.x + pointVec2.x) / 2 ;
        auto relMidy = (pointVec1.y + pointVec2.y) / 2 ;
        // 计算bgSprite的锚点
        auto anchorX = relMidx / bgSprite->getBoundingBox().size.width;
        auto anchorY = relMidy / bgSprite->getBoundingBox().size.height;
        // 相对屏幕的中点
        auto absMidx = (point2.x + point1.x) / 2 ;
        auto absMidy = (point2.y + point1.y) / 2 ;

        // 缩放时,为了避免出现空白的区域,需要做以下的边界处理。        
        // 当bgSprite快要进入到屏幕时,修改bgSprite的位置(既absMidx和absMidy)。
        if(  bgOrigin.x > 0)
        {
            absMidx -= bgOrigin.x;
        }
        if( bgOrigin.x < -bgSprite->getBoundingBox().size.width + winSize.width )
        {
            absMidx +=  -bgSprite->getBoundingBox().size.width + winSize.width - bgOrigin.x;
        }
        if( bgOrigin.y > 0 )
        {
            absMidy -= bgOrigin.y;
        }
        if( bgOrigin.y < -bgSprite->getBoundingBox().size.height + winSize.height )
        {
            absMidy +=  -bgSprite->getBoundingBox().size.height + winSize.height - bgOrigin.y;
        }
        // 重设bgSprite锚点和位置
        bgSprite->setAnchorPoint(Vec2(anchorX, anchorY));
        bgSprite->setPosition(Vec2(absMidx, absMidy));
        // 根据两触摸点前后的距离计算缩放倍率
        auto scale = bgSprite->getScale() * ( currDistance / prevDistance);
        // 控制缩放倍率在14倍之间,最小倍率不能太小,不让背景将不能填充满整个屏幕。
        scale = MIN(4,MAX(1, scale));
        bgSprite->setScale(scale);
        // 更新原点位置
        bgOrigin = Vec2(absMidx, absMidy) - Vec2(bgSprite->getBoundingBox().size.width * anchorX, bgSprite->getBoundingBox().size.height * anchorY) ;
    }
    else if(touches.size() == 1)        // 单点进行移动
    {
        // 单点时,touches中只有一个Touch对象,所以通过touches[0]就可以得到触摸对象
        auto touch = touches[0];
        // 计算滑动过程中的滑动增量
        auto diff = touch->getDelta();       
        // 得到当前bgSprite的位置
        auto currentPos = bgSprite->getPosition();
        // 得到滑动后bgSprite应该所在的位置
        auto pos = currentPos + diff;
        // 得到此刻bgSprite的尺寸
        auto bgSpriteCurrSize = bgSprite->getBoundingBox().size;

        //边界控制,约束pos的位置
        pos.x = MIN(pos.x, bgSpriteCurrSize.width * bgSprite->getAnchorPoint().x);
        pos.x = MAX(pos.x, -bgSpriteCurrSize.width + winSize.width + bgSpriteCurrSize.width * bgSprite->getAnchorPoint().x);
        pos.y = MIN(pos.y, bgSpriteCurrSize.height * bgSprite->getAnchorPoint().y);
        pos.y = MAX(pos.y, -bgSpriteCurrSize.height + winSize.height + bgSpriteCurrSize.height * bgSprite->getAnchorPoint().y);
        // 重设bgSprite位置
        bgSprite->setPosition(pos);

        // 更新原点位置
        if( pos.x >= bgSpriteCurrSize.width * bgSprite->getAnchorPoint().x
           || pos.x <= -bgSpriteCurrSize.width + winSize.width + bgSpriteCurrSize.width * bgSprite->getAnchorPoint().x)
        {
            diff.x = 0;
        }
        if( pos.y >= bgSpriteCurrSize.height * bgSprite->getAnchorPoint().y
           || pos.y <= -bgSpriteCurrSize.height + winSize.height + bgSpriteCurrSize.height * bgSprite->getAnchorPoint().y)
        {
            diff.y = 0;
        }
        bgOrigin += diff;
    }
}

这里写图片描述

这里写图片描述

代码中有一点需要注意的是,在缩放过程中,bgSprite的尺寸不断变化的,所以计算起锚点或进行边界处理时,一定要用它缩放后的尺寸宽高来计算,而不能是它本身的宽高。 所以代码中计算bgSprite的尺寸我们用getBoundingBox函数来获得经过缩放和旋转之后的外框盒大小,而不用getContentSize函数来获得节点原始的大小。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值