参考文章地址:
迷雾效果实现原理:http://bbs.9ria.com/thread-157487-1-1.html
C++代码:FogLayer.h
#ifndef _FOG_LAYER_H_
#define _FOG_LAYER_H_
#include "cocos2d.h"
USING_NS_CC;
//迷雾层
class FogLayer :public CCNode{
public:
//迷雾块图素信息封装类
class FogBlock:public CCObject{
CC_SYNTHESIZE(int,leftTop,LeftTop);
CC_SYNTHESIZE(int,rightTop,RightTop);
CC_SYNTHESIZE(int,leftButtom,LeftButtom);
CC_SYNTHESIZE(int,rightButtom,RightButtom);
int getTotal(){
return leftTop + rightTop + leftButtom + rightButtom;
}
};
private:
//TileGID与图素关系数组(total - gid)
CCArray* tileGids;
//瓦片地图
CCTMXTiledMap* fogMap;
//把cocos2d-x坐标转换为地图坐标
CCPoint convertGLToMap(CCPoint point);
//根据地图坐标更新图素
void updateTiles(CCPoint mapPoint);
//瓦片集合的图素信息(瓦片坐标点 - 瓦片图素信息)
CCDictionary* fogBlocks;
//根据地图坐标点获取迷雾块
FogBlock* getFogBlock(CCPoint mapPoint);
//根据图素信息之和获取TileGID
int getTileGID(int total);
public:
//创建一个迷雾层
CREATE_FUNC(FogLayer);
//初始化
virtual bool init();
//触摸迷雾层
bool onTouch(CCPoint point);
//释放资源
virtual void onExit();
};
#endif
C++代码:FogLayer.cpp
#include "FogLayer.h"
bool FogLayer::init(){
do
{
fogBlocks = CCDictionary::create();
fogBlocks->retain();
tileGids = CCArray::createWithCapacity(16);
tileGids->retain();
//建立图素与TileGID之间的关系 (total - gid)
tileGids->addObject(CCInteger::create(1)); //0 -- 1
tileGids->addObject(CCInteger::create(5)); //1 -- 5
tileGids->addObject(CCInteger::create(9)); //2 -- 9
tileGids->addObject(CCInteger::create(13)); //3 -- 13
tileGids->addObject(CCInteger::create(2)); //4 -- 2
tileGids->addObject(CCInteger::create(6)); //5 -- 6
tileGids->addObject(CCInteger::create(10)); //6 -- 10
tileGids->addObject(CCInteger::create(14)); //7 -- 11
tileGids->addObject(CCInteger::create(3)); //8 -- 3
tileGids->addObject(CCInteger::create(7)); //9 -- 7
tileGids->addObject(CCInteger::create(11)); //10 -- 11
tileGids->addObject(CCInteger::create(15)); //11 -- 15
tileGids->addObject(CCInteger::create(4)); //12 -- 4
tileGids->addObject(CCInteger::create(8)); //13 -- 8
tileGids->addObject(CCInteger::create(12)); //14 -- 12
tileGids->addObject(CCInteger::create(16)); //15 -- 16
fogMap = CCTMXTiledMap::create("fog.tmx");
CC_BREAK_IF(!fogMap);
//设置锚点为左上角
fogMap->setAnchorPoint(CCPoint(0,1));
//设置位置为左上角(UI坐标的原点)
fogMap->setPosition(ccp(0,CCDirector::sharedDirector()->getVisibleSize().height));
this->addChild(fogMap);
return true;
} while (0);
return false;
}
//把cocos2d-x坐标转换为地图坐标
CCPoint FogLayer::convertGLToMap(CCPoint point){
point = CCDirector::sharedDirector()->convertToUI(point);
//float mapWidth = fogMap->getMapSize().width * fogMap->getTileSize().width;
//float mapHeight = fogMap->getMapSize().height * fogMap->getTileSize().height;
//CCLOG("mapWidth=%f mapHeight=%f",mapWidth,mapHeight);
//x = 触摸点的宽度/瓦片宽度
int x = point.x/fogMap->getTileSize().width;
//y = 触摸点的高度/瓦片高度
int y = point.y/fogMap->getTileSize().height;
return ccp(x,y);
}
//根据图素信息之和获取TileGID
int FogLayer::getTileGID(int total){
if (total >= 16)
{
return 0;
}
else{
return ((CCInteger*)tileGids->objectAtIndex(total))->getValue();
}
}
//触摸迷雾层
bool FogLayer::onTouch(CCPoint point){
//把cocos2d-x坐标转换为地图坐标
CCPoint mapPoint = convertGLToMap(point);
CCLOG("map x=%f y=%f",mapPoint.x,mapPoint.y);
//根据地图坐标更新图素
updateTiles(mapPoint);
return false;
}
//根据地图坐标更新图素
void FogLayer::updateTiles(CCPoint mapPoint){
CCSize mapSize = fogMap->getMapSize();
CCTMXLayer* fogLayer = fogMap->layerNamed("fogLayer");
//边界判断
if (mapPoint.x > mapSize.width || mapPoint.x < 0 || mapPoint.y > mapSize.height || mapPoint.y <0)
{
CCLOG("mapPoint out of range x=%f y=%f",mapPoint.x,mapPoint.y);
return;
}
//根据坐标点获取对应的迷雾块,并更新图素信息
FogBlock* fogBlock4 = getFogBlock(mapPoint);
FogBlock* fogBlock8 = getFogBlock(ccp(mapPoint.x+1,mapPoint.y));
FogBlock* fogBlock1 = getFogBlock(ccp(mapPoint.x,mapPoint.y+1));
FogBlock* fogBlock2 = getFogBlock(ccp(mapPoint.x+1,mapPoint.y+1));
//旧的total
int total4 = fogBlock4->getTotal();
int total8 = fogBlock8->getTotal();
int total1 = fogBlock1->getTotal();
int total2 = fogBlock2->getTotal();
//CCLOG("old total4=%d total8=%d total1=%d tota2=%d",total4,total8,total1,total2);
fogBlock4->setRightButtom(4);
fogBlock8->setLeftButtom(8);
fogBlock1->setRightTop(1);
fogBlock2->setLeftTop(2);
//CCLOG("new total4=%d total8=%d total1=%d tota2=%d",fogBlock4->getTotal(),fogBlock8->getTotal(),fogBlock1->getTotal(),fogBlock2->getTotal());
//更新图素
if (total4 != fogBlock4->getTotal())
{
fogLayer->setTileGID(getTileGID(fogBlock4->getTotal()),mapPoint);
}
if (total8 != fogBlock8->getTotal())
{
fogLayer->setTileGID(getTileGID(fogBlock8->getTotal()),ccp(mapPoint.x+1,mapPoint.y));
}
if (total1 != fogBlock1->getTotal())
{
fogLayer->setTileGID(getTileGID(fogBlock1->getTotal()),ccp(mapPoint.x,mapPoint.y+1));
}
if (total2 != fogBlock2->getTotal())
{
fogLayer->setTileGID(getTileGID(fogBlock2->getTotal()),ccp(mapPoint.x+1,mapPoint.y+1));
}
}
//根据地图坐标点获取迷雾块
FogLayer::FogBlock* FogLayer::getFogBlock(CCPoint mapPoint){
const char* key = CCString::createWithFormat("%f%f",mapPoint.x,mapPoint.y)->getCString();
CCObject* fogBlock = fogBlocks->objectForKey(key);
//如果没找到图素信息类
if (fogBlock)
{
return (FogBlock*)fogBlock;
}else{
//创建一个新的图素信息类,并放到集合中
FogBlock* fog = new FogBlock;
fog->autorelease();
//初始化
fog->setLeftTop(0);
fog->setLeftButtom(0);
fog->setRightTop(0);
fog->setRightButtom(0);
//添加到集合
fogBlocks->setObject(fog,key);
return fog;
}
}
//释放资源
void FogLayer::onExit(){
if (fogBlocks)
{
fogBlocks->release();
}
if (tileGids && tileGids->count()>0)
{
tileGids->release();
}
}
C++代码:HelloWorldScene.h
#ifndef __HELLOWORLD_SCENE_H__
#define __HELLOWORLD_SCENE_H__
#include "cocos2d.h"
class HelloWorld : public cocos2d::CCLayer
{
public:
// Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone
virtual bool init();
// there's no 'id' in cpp, so we recommend returning the class instance pointer
static cocos2d::CCScene* scene();
// a selector callback
void menuCloseCallback(CCObject* pSender);
// implement the "static node()" method manually
CREATE_FUNC(HelloWorld);
/* 注册触摸监听 */
virtual void onEnter();
/* 注销触摸监听 */
virtual void onExit();
/* 手指按下 */
virtual bool ccTouchBegan(cocos2d::CCTouch *pTouch, cocos2d::CCEvent *pEvent);
};
#endif // __HELLOWORLD_SCENE_H__
C++代码:HelloWorldScene.cpp
#include "HelloWorldScene.h"
#include "FogLayer.h"
USING_NS_CC;
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;
}
CCSize visibleSize = CCDirector::sharedDirector()->getVisibleSize();
CCPoint origin = CCDirector::sharedDirector()->getVisibleOrigin();
/////////////////////////////
// 2. add a menu item with "X" image, which is clicked to quit the program
// you may modify it.
// add a "close" icon to exit the progress. it's an autorelease object
CCMenuItemImage *pCloseItem = CCMenuItemImage::create(
"CloseNormal.png",
"CloseSelected.png",
this,
menu_selector(HelloWorld::menuCloseCallback));
pCloseItem->setPosition(ccp(origin.x + visibleSize.width - pCloseItem->getContentSize().width/2 ,
origin.y + pCloseItem->getContentSize().height/2));
// create menu, it's an autorelease object
CCMenu* pMenu = CCMenu::create(pCloseItem, NULL);
pMenu->setPosition(CCPointZero);
this->addChild(pMenu, 1);
/////////////////////////////
// 3. add your codes below...
// add a label shows "Hello World"
// create and initialize a label
CCLabelTTF* pLabel = CCLabelTTF::create("Hello World", "Arial", 24);
// position the label on the center of the screen
pLabel->setPosition(ccp(origin.x + visibleSize.width/2,
origin.y + visibleSize.height - pLabel->getContentSize().height));
// add the label as a child to this layer
this->addChild(pLabel, 1);
// add "HelloWorld" splash screen"
CCSprite* pSprite = CCSprite::create("map.png");
// position the sprite on the center of the screen
pSprite->setPosition(ccp(visibleSize.width/2 + origin.x, visibleSize.height/2 + origin.y));
// add the sprite as a child to this layer
this->addChild(pSprite, 0);
//添加迷雾层
this->addChild(FogLayer::create(),3,3);
return true;
}
void HelloWorld::menuCloseCallback(CCObject* pSender)
{
#if (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) || (CC_TARGET_PLATFORM == CC_PLATFORM_WP8)
CCMessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert");
#else
CCDirector::sharedDirector()->end();
#if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS)
exit(0);
#endif
#endif
}
/* 注册触摸监听 */
void HelloWorld::onEnter(){
CCDirector::sharedDirector()->getTouchDispatcher()->addTargetedDelegate(this,1,true);
}
/* 注销触摸监听 */
void HelloWorld::onExit(){
CCDirector::sharedDirector()->getTouchDispatcher()->removeDelegate(this);
}
/* 手指按下 */
bool HelloWorld::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent){
CCPoint uiPoint = CCDirector::sharedDirector()->convertToUI(pTouch->getLocation());
//调用迷雾层的的onTouch方法
FogLayer* fogLayer = (FogLayer*)this->getChildByTag(3);
fogLayer->onTouch(pTouch->getLocation());
return true;
}