地图迷雾效果的实现(源码)

参考文章地址:

迷雾效果实现原理:http://bbs.9ria.com/thread-157487-1-1.html

地图编辑:http://www.benmutou.com/archives/482


源码


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;
}



运行效果:




posted on 2014-07-18 15:09  linchaolong  阅读(1124)  评论(0编辑  收藏  举报

导航