cocos2d-x鼠标拖动地图

1.我们先在一个layer里addChild一个CCTMXTiledMap, 头文件如下:

#include "cocos2d.h"

class GameLayer : public cocos2d::CCLayer
{
public:
    GameLayer(void);
    ~GameLayer(void);
    
    CREATE_FUNC(GameLayer);
    bool init();
    
    static GameLayer* inst(void); //单例
    
    void initTileMap(); //初始化地图
    //void initAttackHero(); //初始化攻方英雄
    //void initDefendHero(); //初始化守方英雄
    
    void update(float dt);
    
    void setViewpointCenter(cocos2d::CCPoint position); //设置视点随玩家移动,这个方法要在GameLayer的update方法里调用
    
    CC_SYNTHESIZE_READONLY(cocos2d::CCTMXTiledMap*, m_tileMap, TileMap); //地图
    
    virtual bool ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
    virtual void ccTouchMoved(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
    virtual void ccTouchEnded(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
    
    virtual void registerWithTouchDispatcher(void);
    
private:
    bool m_bDrag; //鼠标是否开始搬动
    cocos2d::CCPoint m_posBeginDrag;
};

2.在initTileMap里addChild,如下:

void GameLayer::initTileMap()
{
    m_tileMap = CCTMXTiledMap::create("map/level.tmx");
    CCObject *pObject = NULL;
    CCARRAY_FOREACH(m_tileMap->getChildren(), pObject) //为地图每个元素去剧齿
    {
        CCTMXLayer *child = (CCTMXLayer*)pObject;
        child->getTexture()->setAliasTexParameters();
    }
    this->addChild(m_tileMap, -6);
}
地图被addChild里,默认的坐标是(0,0),也就是和GameLayer的坐标一样都是左下角
3.在layer的init方法里设置屏幕可点击

bool GameLayer::init()
{
    bool bRet = false;
    
    do {
        CC_BREAK_IF(!CCLayer::init());
        this->initTileMap();
        
        this->scheduleUpdate();
        
        this->setTouchEnabled(true);
      
        bRet = true;
    } while (0);
    return bRet;
}

4.重载registerWithTouchDispatcher方法

void GameLayer::registerWithTouchDispatcher(void)
{
    CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
}

5.重载CCMoveBegan方法

bool GameLayer::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
    m_bDrag = true; //标记现在在拖动状态
    m_posBeginDrag = this->convertTouchToNodeSpace(pTouch); //记下开始点击位置
    return true;
}

6. 重要的ccTouchMove方法

void GameLayer::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
{
    float mapWidth = m_tileMap->getMapSize().width * m_tileMap->getTileSize().width; //地图宽度
    float mapHeight = m_tileMap->getMapSize().height * m_tileMap->getTileSize().height; //地图高度
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();//屏幕大小
    
    CCPoint pos = this->convertTouchToNodeSpace(pTouch); //当前点位置
    float xOffset = pos.x - m_posBeginDrag.x; //比较鼠标移了多少偏移
    float yOffset = pos.y - m_posBeginDrag.y;
    
    CCPoint layPos = this->getPosition();
    layPos.x += xOffset;
    layPos.y += yOffset;
    
    //判断是否拖出地图边界
    if(layPos.x < -(mapWidth - winSize.width)) //向右拖出屏幕了 你可以把layer的pos当成地图的pos,向右拖地图坐标向左移,就是变小,最小不能小于负的地图宽-屏幕宽
        layPos.x -= xOffset;
    if(layPos.x > 0) //左拖地图起点不能大于0,0,为什么可以自己画张草图
        layPos.x -= xOffset;;
    if(layPos.y < -(mapHeight - winSize.height)) //y方向处理和x一样
        layPos.y -= yOffset;
    if(layPos.y > 0)
       layPos.y -= yOffset;
    
    this->setPosition(layPos); //设置layer坐标,同时也就是设置了地图坐标
}

7.ccTouchEnded方法

void GameLayer::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
    m_bDrag = false;
}


8.附送地图随主角滚动的方法,可上下左右滚动,参数是主角的位置

void GameLayer::setViewpointCenter(CCPoint position)
{
    if(m_bDrag)
        return;
    
    if(!m_tileMap)
    {
        CCLog("error can't find tileMap");
        return;
    }
    CCSize winSize = CCDirector::sharedDirector()->getWinSize();
    
    int x = MAX(position.x, winSize.width / 2);
    int y = MAX(position.y, winSize.height / 2);
    x = MIN(x, (m_tileMap->getMapSize().width * m_tileMap->getTileSize().width) - winSize.width / 2);
    y = MIN(y, (m_tileMap->getMapSize().height * m_tileMap->getTileSize().height) - winSize.height / 2);
    CCPoint actualPosition = ccp(x, y);
    
    CCPoint centerOfView = ccp(winSize.width / 2, winSize.height / 2);
    CCPoint viewPoint = ccpSub(centerOfView, actualPosition);
    this->setPosition(viewPoint);
}

这个方法需要在gamelayer的update里调用,如下:

void GameLayer::update(float dt)
{
    Hero* hero = ArmyController::inst()->getAtkHero();
    if(hero->getArmature())
     this->setViewpointCenter(hero->getArmature()->getPosition());
}

9.最后再送单例的标准实现方法:

在layer.cpp开头处定义静态全局变量: 

static GameLayer *s_GameLayer = NULL;

然后就是实现:

GameLayer* GameLayer::inst()
{
    if (!s_GameLayer)
    {
         s_GameLayer = new GameLayer();
         s_GameLayer->init();
    }
    return s_GameLayer;
}
单例的注意事项就是任何时候想调用GameLayer的方法千万不可new 它,只要GameLayer::inst()->XX方法名即可





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天马流星2719

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值