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方法名即可