转载请标明:转载自【小枫栏目】,博文链接:http://blog.csdn.net/rexuefengye/article/details/10517641
一、原理
在开发游戏的过程中,特别是地图编辑器中,需要利用最少的资源,实现最丰富的地形地貌。
另外,就是在一些策略类游戏里经常用到的战争迷雾,如图
战争迷雾制作原理参考以下文章: http://bbs.9ria.com/thread-157487-1-1.html
二、准备工作
1)瓦片地图的图素:
2) 创建TXM地图
现在,打开我们的Tiled地图编辑器,新建一个地图:【新建】->【新建文件】,地图宽为10,地图高为10。
然后将瓦片图素拖动到图块区域,添加图块,宽高分别为128像素,边距和间距都为0:
然后,最重要的一步来了!选中第一个图素,涂满地图,效果如下:
三、实现代码
HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
#include "TiledFourCell.h"
using namespace cocos2d;
class HelloWorld : public cocos2d::CCLayerColor
{
public:
// Method 'init' in cocos2d-x returns bool, instead of 'id' in cocos2d-iphone (an object pointer)
virtual bool init();
// there's no 'id' in cpp, so we recommend to return the class instance pointer
static cocos2d::CCScene* scene();
// a selector callback
void menuCloseCallback(CCObject* pSender);
// preprocessor macro for "static create()" constructor ( node() deprecated )
CREATE_FUNC(HelloWorld);
//add code
virtual bool ccTouchBegan( CCTouch *pTouch, CCEvent *pEvent );
virtual void registerWithTouchDispatcher( void );
CCPoint getMapTiledPos( CCTMXTiledMap* map, CCPoint pos);
void changeCloudTiled4( CCTMXLayer* layer, CCPoint pos );
void setGidByTotalNum( CCTMXLayer* layer, CCPoint pos, int iTotalNum );
TiledFourCell* getCellByTiledPos( CCPoint pos );
void changeCloudTiled8( CCTMXLayer* layer, CCPoint pos );
void changeCloudTiled1( CCTMXLayer* layer, CCPoint pos );
void changeCloudTiled2( CCTMXLayer* layer, CCPoint pos );
private:
CCTMXTiledMap* cloudMap;
CCDictionary* tiledCellsDict; // 瓦片坐标和瓦片顶点对象 键值对
CCArray* gidsArray; // 瓦片图片gid与瓦片顶点数值总和对应
};
#endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.cpp
#include "HelloWorldScene.h"
#include "SimpleAudioEngine.h"
using namespace cocos2d;
using namespace CocosDenshion;
CCScene* HelloWorld::scene()
{
// 'scene' is an autorelease object
CCScene *scene = CCScene::create();
// 'layer' is an autorelease object
HelloWorld *layer = HelloWorld::create();
// add layer as a child to scene
scene->addChild(layer);
// return the scene
return scene;
}
// on "init" you need to initialize your instance
bool HelloWorld::init()
{
//
// 1. super init first
if ( !CCLayer::init() )
{
return false;
}
CCLayerColor::initWithColor(ccc4(255, 255, 255, 255));
cloudMap = CCTMXTiledMap::create("blackCloud.tmx");
this->addChild(cloudMap);
this->setTouchEnabled(true);
gidsArray = CCArray::createWithCapacity(16);
tiledCellsDict = CCDictionary::create();
gidsArray->retain();
tiledCellsDict->retain();
/* 瓦片地图使用4X4的图片,每张小图片对应的数值如下:
0 4 8 12
1 5 9 13
2 6 10 14
3 7 11 15
以上数值为瓦片格子的数据值。
瓦片图素从1开始计数,如下:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
比如数据值4,对应的瓦片图素是2;数据值10,对应的瓦片图素是11。
*/
/* 以数据值为索引,可以取得瓦片图素 */
gidsArray->addObject(CCInteger::create(1));//顶点总和0,对应图素ID为1
gidsArray->addObject(CCInteger::create(5));// 顶点总和1,对应图素ID为5
gidsArray->addObject(CCInteger::create(9));// 顶点总和2,对应图素ID为9
gidsArray->addObject(CCInteger::create(13));// 顶点总和3,对应图素ID为13
gidsArray->addObject(CCInteger::create(2));// 顶点总和4,对应图素ID为2
gidsArray->addObject(CCInteger::create(6));// 顶点总和5,对应图素ID为6
gidsArray->addObject(CCInteger::create(10));
gidsArray->addObject(CCInteger::create(14));
gidsArray->addObject(CCInteger::create(3));
gidsArray->addObject(CCInteger::create(7));
gidsArray->addObject(CCInteger::create(11));
gidsArray->addObject(CCInteger::create(15));
gidsArray->addObject(CCInteger::create(4));
gidsArray->addObject(CCInteger::create(8));
gidsArray->addObject(CCInteger::create(12));
gidsArray->addObject(CCInteger::create(16));
return true;
}
//void HelloWorld::menuCloseCallback(CCObject* pSender)
//{
// CCDirector::sharedDirector()->end();
//
//#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
// exit(0);
//#endif
//}
bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent)
{
CCLog("helloworld");
CCPoint tiledMapPos = getMapTiledPos(
cloudMap,
CCDirector::sharedDirector()->convertToGL(pTouch->getLocationInView()));
CCLOG("TiledMapPos x = %f, y = %f", tiledMapPos.x, tiledMapPos.y);
CCTMXLayer* cloudLayer = cloudMap->layerNamed("cloudLayer");
/* 设置当前瓦片的数据值,以及设置旁白瓦片的数据值 */
changeCloudTiled4(cloudLayer, tiledMapPos);
changeCloudTiled8(cloudLayer, ccp(tiledMapPos.x + 1, tiledMapPos.y));
changeCloudTiled1(cloudLayer, ccp(tiledMapPos.x, tiledMapPos.y + 1));
changeCloudTiled2(cloudLayer, ccp(tiledMapPos.x + 1, tiledMapPos.y + 1));
return true;
}
void HelloWorld::registerWithTouchDispatcher()
{
CCDirector* pDirector = CCDirector::sharedDirector();
pDirector->getTouchDispatcher()->addTargetedDelegate(this, 0, true);
}
CCPoint HelloWorld::getMapTiledPos(CCTMXTiledMap *map, CCPoint pos)
{
CCSize mapSize = map->getMapSize();
CCSize tiledSize = map->getTileSize();
int iMapHeight = mapSize.height * tiledSize.height;
/* pos为笛卡尔坐标系的坐标,所以y轴需要修正 */
int x = pos.x / tiledSize.width;
int y = (iMapHeight - pos.y) / tiledSize.height;
return CCPointMake(x, y);
}
void HelloWorld::changeCloudTiled4(CCTMXLayer *layer,CCPoint pos)
{
TiledFourCell* cell = getCellByTiledPos(pos);
/* 数值4,在瓦片右下角 */
cell->setiRightBottom(4);
/* 根据瓦片4个顶点之和设置地图瓦片的图片 */
setGidByTotalNum(layer, pos, cell->getiTotalNum());
}
void HelloWorld::changeCloudTiled8(CCTMXLayer *layer, CCPoint pos)
{
TiledFourCell* cell = getCellByTiledPos(pos);
cell->setiLeftBottom(8);
setGidByTotalNum(layer, pos, cell->getiTotalNum());
}
void HelloWorld::changeCloudTiled1(CCTMXLayer *layer, CCPoint pos)
{
TiledFourCell* cell = getCellByTiledPos(pos);
cell->setiRightTop(1);
setGidByTotalNum(layer, pos, cell->getiTotalNum());
}
void HelloWorld::changeCloudTiled2(CCTMXLayer *layer, CCPoint pos)
{
TiledFourCell* cell = getCellByTiledPos(pos);
cell->setiLeftTop(2);
setGidByTotalNum(layer, pos, cell->getiTotalNum());
}
void HelloWorld::setGidByTotalNum( CCTMXLayer* layer, CCPoint pos, int iTotalNum )
{
CCSize mapSize = cloudMap->getMapSize();
/* 避免超出范围 */
if(pos.x < 0 || pos. y < 0
|| pos.x >= mapSize.width || pos.y >= mapSize.height) {
return;
}
/* iTotalNum是瓦片的4个顶点数据值的总和,通过这个值获得对应的瓦片图素 */
CCInteger* gidInt = (CCInteger*)gidsArray->objectAtIndex(iTotalNum);
/* 用新的瓦片图素替换pos坐标上的瓦片图素 */
layer->setTileGID(gidInt->getValue(), pos);
}
TiledFourCell* HelloWorld::getCellByTiledPos( CCPoint pos )
{
CCSize mapSize = cloudMap->getMapSize();
/* 瓦片坐标原本是二维坐标,转换为一维数值 */
int index = mapSize.width * pos.x + pos.y;
/* 取得瓦片的顶点数据对象 */
const char* keyCh = CCString::createWithFormat("%d", index)->getCString();
CCObject* obj = tiledCellsDict->objectForKey(keyCh);
TiledFourCell* cell = NULL;
if(obj == NULL) {
/* 如果该瓦片没有顶点数据对象,则创建一个,顶点数据值默认都为0 */
cell = TiledFourCell::create();
tiledCellsDict->setObject(cell, keyCh);
}
else {
cell = (TiledFourCell*)obj;
}
return cell;
}
创建瓦片类TiledFourCell
TiledFourCell.h
//
// TiledFourCell.h
// Fog
//
// Created by IDEA-MAC03 on 13-8-29.
//
//
#ifndef __Fog__TiledFourCell__
#define __Fog__TiledFourCell__
#include "cocos2d.h"
using namespace cocos2d;
class TiledFourCell : public CCNode
{
public:
CREATE_FUNC(TiledFourCell);
virtual bool init();
void setiLeftTop(int _iLeftTop);
int getiLeftTop();
void setiLeftBottom(int _iLeftBottom);
int getiLeftBottom();
void setiRightTop(int _iRightTop);
int getiRightTop();
void setiRightBottom(int _iRightBottom);
int getiRightBottom();
/* 获取顶点值的总和 */
int getiTotalNum();
private:
int iLeftTop; // 左上角
int iLeftBottom;// 左下角
int iRightTop; // 右上角
int iRightBottom; // 右下角
};
#endif /* defined(__Fog__TiledFourCell__) */
TiledFourCell.cpp
//
// Created by IDEA-MAC03 on 13-8-29.
//
//
#include "TiledFourCell.h"
bool TiledFourCell::init()
{
iLeftTop = 0;
iLeftBottom = 0;
iRightTop = 0;
iRightBottom = 0;
return true;
}
void TiledFourCell::setiLeftTop(int _iLeftTop)
{
iLeftTop = _iLeftTop;
}
int TiledFourCell::getiLeftTop()
{
return iLeftTop;
}
void TiledFourCell::setiLeftBottom(int _iLeftBottom)
{
iLeftBottom = _iLeftBottom;
}
int TiledFourCell::getiLeftBottom()
{
return iLeftBottom;
}
void TiledFourCell::setiRightTop(int _iRightTop)
{
iRightTop = _iRightTop;
}
int TiledFourCell::getiRightTop()
{
return iRightTop;
}
void TiledFourCell::setiRightBottom(int _iRightBottom)
{
iRightBottom = _iRightBottom;
}
int TiledFourCell::getiRightBottom()
{
return iRightBottom;
}
int TiledFourCell::getiTotalNum()
{
return (iLeftTop + iLeftBottom + iRightTop + iRightBottom);
}
四、运行效果图
详细教程可参考:http://www.benmutou.com/blog/archives/485
代码下载:http://download.csdn.net/detail/my183100521/6032981