Cocos2d-x之瓦片地图 Tiled
Cocos2d-x之瓦片地图 Tiled
首先使用 瓦片地图编辑器(Tiled) 制作一个瓦片地图,并将其放入工程的Resources目录下
功能实现:
将地图显示在窗体中
将精灵添加到地图定义的对象层中的一个对象上
移动精灵,使其可以和碰撞图层上的精灵发生碰撞
碰撞后碰撞图层上的精灵消失,label字体改变
代码部分:
HelloWorldScene.h
1 #ifndef __HELLOWORLD_SCENE_H__ 2 #define __HELLOWORLD_SCENE_H__ 3 4 #include "cocos2d.h" 5 6 class HelloWorld : public cocos2d::Layer 7 { 8 public: 9 // there's no 'id' in cpp, so we recommend returning the class instance pointer 10 static cocos2d::Scene* createScene(); 11 12 // Here's a difference. Method 'init' in cocos2d-x returns bool, instead of returning 'id' in cocos2d-iphone 13 virtual bool init(); 14 15 // a selector callback 16 void menuCloseCallback(cocos2d::Ref* pSender); 17 18 // implement the "static create()" method manually 19 CREATE_FUNC(HelloWorld); 20 21 virtual bool onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *event); 22 23 // 坐标转换,opgl 坐标转换为 Tiled 地图坐标(每块小地图的坐标) 24 cocos2d::Vec2 tileCoordForPosition(cocos2d::Vec2 position); 25 26 void judgeCollide(); // 判断碰撞 27 28 private: 29 cocos2d::Size visibleSize; 30 cocos2d::Sprite *sprite; 31 cocos2d::TMXTiledMap *map; 32 cocos2d::LabelTTF *label; 33 }; 34 35 #endif // __HELLOWORLD_SCENE_H__
HelloWorldScene.cpp
1 #include "HelloWorldScene.h" 2 3 USING_NS_CC; 4 5 Scene* HelloWorld::createScene() 6 { 7 // 'scene' is an autorelease object 8 auto scene = Scene::create(); 9 10 // 'layer' is an autorelease object 11 auto layer = HelloWorld::create(); 12 13 // add layer as a child to scene 14 scene->addChild(layer); 15 16 // return the scene 17 return scene; 18 } 19 20 // on "init" you need to initialize your instance 21 bool HelloWorld::init() 22 { 23 ////////////////////////////// 24 // 1. super init first 25 if ( !Layer::init() ) 26 { 27 return false; 28 } 29 30 visibleSize = Director::getInstance()->getVisibleSize(); 31 Vec2 origin = Director::getInstance()->getVisibleOrigin(); 32 33 34 35 ///////////////////////////// 36 // 2. add a menu item with "X" image, which is clicked to quit the program 37 // you may modify it. 38 39 // add a "close" icon to exit the progress. it's an autorelease object 40 auto closeItem = MenuItemImage::create( 41 "CloseNormal.png", 42 "CloseSelected.png", 43 CC_CALLBACK_1(HelloWorld::menuCloseCallback, this)); 44 45 closeItem->setPosition(Vec2(origin.x + visibleSize.width - closeItem->getContentSize().width/2 , 46 origin.y + closeItem->getContentSize().height/2)); 47 48 // create menu, it's an autorelease object 49 auto menu = Menu::create(closeItem, NULL); 50 menu->setPosition(Vec2::ZERO); 51 this->addChild(menu, 1); 52 53 ///////////////////////////// 54 // 3. add your codes below... 55 56 // add a label shows "Hello World" 57 // create and initialize a label 58 59 label = LabelTTF::create("Hello World", "Arial", 24); 60 61 // position the label on the center of the screen 62 label->setPosition(Vec2(origin.x + visibleSize.width/2, 63 origin.y + visibleSize.height - label->getContentSize().height)); 64 65 // add the label as a child to this layer 66 this->addChild(label, 1); 67 68 69 70 /////////////// 瓦片地图 Tiled /////////////// 71 72 73 map = TMXTiledMap::create("map.tmx"); 74 addChild(map); // 默认添加的位置是左下角 75 76 // 获取 objLayer 对象层 77 TMXObjectGroup *objGroup = map->objectGroupNamed("objLayer"); 78 // 获取 hero 对象 79 auto vm = objGroup->objectNamed("hero"); 80 81 // 获取 hero 对象的 x,y 坐标 82 float x = vm.at("x").asFloat(); 83 float y = vm.at("y").asFloat(); 84 85 //// 获取 hero 的 id 属性值 86 //auto id = vm.at("id").asInt(); 87 //log(" sprite id is %d ", id); 88 89 // 获取 hero 的名字 90 String name = vm.at("name").asString(); 91 log(" name %s ", name); 92 93 // 在 hero 的位置处添加精灵 94 sprite = Sprite::create("button.png"); 95 sprite->setPosition(Vec2(x, y)); 96 // 因为地图的锚点是左下角,所以设置精灵的锚点也为左下角,这样位置才能对应上 97 sprite->setAnchorPoint(Vec2::ZERO); 98 addChild(sprite); 99 100 // 设置可以获取触摸 101 setTouchEnabled(true); 102 setTouchMode(Touch::DispatchMode::ONE_BY_ONE); 103 104 return true; 105 } 106 107 bool HelloWorld::onTouchBegan(Touch *touch, Event *event){ 108 109 Vec2 pos = touch->getLocation(); 110 ActionInstant *func = CallFunc::create(this, callfunc_selector(HelloWorld::judgeCollide)); 111 sprite->runAction(Sequence::create(MoveTo::create(1, pos), func, nullptr)); 112 return true; 113 } 114 115 116 Vec2 HelloWorld::tileCoordForPosition(Vec2 position){ 117 118 // 用 x 坐标(opgl中的)除以 每个小地图的宽度,就可以得出 这个点 的 x 轴坐标(瓦片地图中的) 119 int x = position.x / map->getTileSize().width; 120 // 使用 瓦片地图的高度 * 瓦片地图每个的高度 - 点的 y 坐标) / 每个瓦片地图的高 121 int y = (map->getMapSize().height * map->getTileSize().height - position.y) / map->getTileSize().height; 122 123 return Vec2(x, y); 124 } 125 126 void HelloWorld::judgeCollide(){ 127 128 TMXLayer *collisionLayer = map->layerNamed("collisionLayer"); // 获取瓦片地图的碰撞层 129 Vec2 tiledPos = tileCoordForPosition(sprite->getPosition()); // 将精灵坐标转换为瓦片地图的坐标 130 131 if (collisionLayer->tileGIDAt(tiledPos)){ 132 collisionLayer->removeTileAt(tiledPos); 133 log("collisionLayer->tileGIDAt(tiledPos) = %d ", collisionLayer->tileGIDAt(tiledPos)); 134 label->setString("you eat me"); 135 } 136 else{ 137 label->setString("HelloWorld ~~~ "); 138 } 139 140 } 141 142 143 void HelloWorld::menuCloseCallback(Ref* pSender) 144 { 145 #if (CC_TARGET_PLATFORM == CC_PLATFORM_WP8) || (CC_TARGET_PLATFORM == CC_PLATFORM_WINRT) 146 MessageBox("You pressed the close button. Windows Store Apps do not implement a close button.","Alert"); 147 return; 148 #endif 149 150 Director::getInstance()->end(); 151 152 #if (CC_TARGET_PLATFORM == CC_PLATFORM_IOS) 153 exit(0); 154 #endif 155 }