cocos2d-x学习日志(9) --战争烟雾

转载请标明:转载自【小枫栏目】,博文链接: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

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

热血枫叶

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

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

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

打赏作者

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

抵扣说明:

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

余额充值