cocos2d-x 3.16实现地图任意缩放

上代码:

1.MapZoom.hpp

#ifndef MapZoom_hpp
#define MapZoom_hpp

#include <stdio.h>
#include <cocos2d.h>

using namespace std;
USING_NS_CC;
class MapZoom : public Layer
{
public:
    enum{
        TAG_MAP,
    };
    MapZoom();
    ~MapZoom();
    static Scene *scene();

    bool init() override;

    virtual void onTouchesBegan(const vector<Touch*> &touches,Event *event) override;
    virtual void onTouchesMoved(const vector<Touch*> &touches,Event *event) override;
    virtual void onTouchesEnded(const vector<Touch*> &touches,Event *event) override;
    virtual void onTouchesCanceled(const vector<Touch*> &touches,Event *event);

    CREATE_FUNC(MapZoom);
private:

    float m_fMinScale =0.1f;//最小缩放值,最好不要设置为0
    float m_fMaxScale =4.0f;//最大缩放值,根据实际情况设定
    float m_fScale =1.0f;//当前缩放值,这里注意,一定不要设置成0,因为cocos2d-x默认的缩放值就是1.0
    float m_fDistance =0.0f;//位移

    cocos2d::Vec2 m_pMiddlePoint;//触摸中点
    //cocos2d::Vec2 m_pBoderOrigin;//左下角的边界点
    //cocos2d::Vec2 m_pBoderMax;//右上角的边界点

    void scaleMap(Point pt1,Point pt2);

    vector<int> m_touchIDVec;//触摸点ID
    map<int,cocos2d::Vec2> m_touchPointMap;//触摸点位置
};
#endif /* MapZoom_hpp */

2.MapZoom.cpp

//
//  MapZoom.cpp
//  Hello-mobile
//
//  Created by LiYong on 2018/2/2.
//

#include "MapZoom.hpp"
MapZoom::MapZoom()
{

}
MapZoom::~MapZoom()
{

}
Scene *MapZoom::scene()
{
    MapZoom *pLayer = MapZoom::create();
    Scene *scene = Scene::create();
    scene->addChild(pLayer);
    return scene;
}
bool MapZoom::init()
{
    if (!Layer::init())
    {
        return false;
    }

    Size winSize = Director::getInstance()->getWinSize();
    Sprite *sprite = Sprite::create("white.jpeg");
    sprite->setPosition(Vec2(winSize.width/2, winSize.height/2));
    sprite->setTag(TAG_MAP);
    addChild(sprite,0);
    EventListenerTouchAllAtOnce *listener = EventListenerTouchAllAtOnce::create();

    listener->onTouchesBegan = CC_CALLBACK_2(MapZoom::onTouchesBegan, this);
    listener->onTouchesMoved = CC_CALLBACK_2(MapZoom::onTouchesMoved, this);
    listener->onTouchesEnded = CC_CALLBACK_2(MapZoom::onTouchesEnded, this);
    listener->onTouchesCancelled = CC_CALLBACK_2(MapZoom::onTouchesCancelled, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, sprite);

    return true;
}
void MapZoom::onTouchesBegan(const vector<Touch*> &touches,Event *event)
{
    Sprite *sprite = dynamic_cast<Sprite*>(getChildByTag(TAG_MAP));
    if (sprite)
    {
        sprite->stopAllActions();
    }
    unsigned long num = touches.size();
    if (num > 1)
    {
        for(Touch *elem:touches)
        {
            m_touchIDVec.push_back(elem->getID());
            m_touchPointMap[elem->getID()] = elem->getLocation();
        }
    }
    if (m_touchIDVec.size()>=2)
    {
        auto touchPoint = m_touchIDVec.begin();
        auto mPoint = m_touchPointMap[(*touchPoint)];
        ++touchPoint;
        auto mPoint2 = m_touchPointMap[(*touchPoint)];

        if (m_fDistance == 0.0)
        {
            m_fDistance = mPoint.distance(mPoint);
            m_pMiddlePoint = mPoint.getMidpoint(mPoint2);
        }

    }
}
void MapZoom::onTouchesMoved(const vector<Touch*> &touches,Event *event)
{
    if (touches.size() >= 2)
    {
        for(Touch *iter : touches)
        {
            if (find(m_touchIDVec.begin(), m_touchIDVec.end(), iter->getID()) == m_touchIDVec.end())
            {
                m_touchIDVec.push_back(iter->getID());
            }

            m_touchPointMap[iter->getID()] = iter->getLocation();
        }
        auto touchPoint = m_touchIDVec.begin();
        auto mPoint = m_touchPointMap[(*touchPoint)];
        ++touchPoint;
        auto mPoint2 = m_touchPointMap[(*touchPoint)];

        if (m_fDistance == 0)
        {
            m_fDistance = mPoint.distance(mPoint2);
            m_pMiddlePoint = mPoint.getMidpoint(mPoint2);
            return;
        }
        scaleMap(mPoint, mPoint2);
    }
    else if (touches.size() == 1)
    {
        auto iter = touches.cbegin();
        Sprite *sprite = dynamic_cast<Sprite *>(this->getChildByTag(TAG_MAP));
        Point endPoint = sprite->getParent()->convertTouchToNodeSpace(*iter);
        if (find(m_touchIDVec.begin(), m_touchIDVec.end(), (*iter)->getID()) == m_touchIDVec.end())
        {
            m_touchIDVec.push_back((*iter)->getID());
            m_touchPointMap[(*iter)->getID()] = (*iter)->getLocation();
            return;
        }
        if (m_touchIDVec.size() == 1)
        {
            Point pos1 = m_touchPointMap[(*iter)->getID()];
            m_touchPointMap[(*iter)->getID()] = (*iter)->getLocation();
            Point pos2 = endPoint - pos1 + sprite->getPosition();
            sprite->setPosition(pos2);
            m_fDistance = 0;
        }
        else if (m_touchIDVec.size() >= 2)
        {
            m_touchPointMap[(*iter)->getID()] = (*iter)->getLocation();
            auto touchPoint = m_touchIDVec.begin();
            auto pt1 = m_touchPointMap[(*touchPoint)];
            ++touchPoint;
            auto pt2 = m_touchPointMap[(*touchPoint)];
            scaleMap(pt1, pt2);
        }
    }

}
void MapZoom::onTouchesEnded(const vector<Touch*> &touches,Event *event)
{
    for (Touch *iter : touches)
    {
        int touchId = iter->getID();
        if (m_touchPointMap.find(touchId) != m_touchPointMap.end())
        {
            m_touchPointMap.erase(touchId);
        }
        auto idter = find(m_touchIDVec.begin(), m_touchIDVec.end(), touchId);
        if (idter != m_touchIDVec.end())
        {
            m_touchIDVec.erase(idter);
        }
    }
    if (m_touchPointMap.empty())
    {
        m_fDistance = 0;

    }
    else if (m_touchPointMap.size() >= 2)
    {
        auto touchPoint = m_touchIDVec.begin();
        auto pt1 = m_touchPointMap[(*touchPoint)];
        ++touchPoint;
        auto pt2 = m_touchPointMap[*touchPoint];
        m_fDistance = pt1.distance(pt2);
    }
}
void MapZoom::onTouchesCanceled(const vector<Touch*> &touches,Event *event)
{
    m_fDistance = 0;
    m_touchPointMap.clear();
    m_touchIDVec.clear();
}
void MapZoom::scaleMap(Point pt1, Point pt2)
{
    Sprite *sprite = dynamic_cast<Sprite *>(this->getChildByTag(TAG_MAP));

    float newdis = pt1.distance(pt2);
    m_fScale = newdis*m_fScale/m_fDistance;

    Point midPt = pt1.getMidpoint(pt2);
    Point curlMidNodePt = sprite->getParent()->convertToNodeSpace(midPt);
    Point oldMidNodePt = sprite->getParent()->convertToNodeSpace(m_pMiddlePoint);
    Point newPos = 2*curlMidNodePt - oldMidNodePt;

    midPt = sprite->convertToNodeSpace(midPt);
    Point newAnchorPoint = Vec2(midPt.x/sprite->getContentSize().width, midPt.y/sprite->getContentSize().height);

    m_fScale = max(m_fScale, m_fMinScale);//缩放比例最小不能小于m_fMinScale
    m_fScale = min(m_fScale, m_fMaxScale);//缩放比例最大不能超过m_fMaxScale
    float spScale = sprite->getScale();
    float newScale = spScale + (m_fScale - spScale)*0.25;
    if (abs(newScale - sprite->getScale()) > 0.01f)
    {
        sprite->setScale(newScale);
    }
    sprite->setPosition(newPos);
    sprite->setAnchorPoint(newAnchorPoint);
    m_pMiddlePoint = pt1.getMidpoint(pt2);
    m_fDistance = newdis;
}
1)注意cocos2d-x默认不开启多点触摸
2)最小缩放最好不要设置为0

参考文章:
cocos2d-x简单实现地图的缩放

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值