Cocos2D-x遊戲開發之十九:瓦塊地圖之碰撞檢測
阿新 • • 發佈:2019-01-29
昨天我們有了精靈和背景,並且精靈可以跑動了,但是我們不能讓精靈無窮無盡地跑下去吧,於是今天我們要在地圖上新增一些障礙物了;
首先開啟精靈的TMX地圖,然後我們自定義一個32X32畫素的圖片新增到圖層中,然後設定此圖層的屬性為:“collidable” 值為“true”,下一步在地圖中新建一個圖層起名為“meta”現在發揮你的創造性把這些小東西新增此圖層中儲存即可。
接下來就該在code中做一些操作了,開啟我們的Player類:
class Player : public Entity { public: Player(void); ~Player(void); public: CREATE_FUNC(Player); virtual bool init(); void run(); virtual bool SetPlayerPosition(int x,int y) ; void SetViewPointByPosition(); CCTMXTiledMap *m_map; void SetTMXTileMap(CCTMXTiledMap *map); CCTMXLayer *meta; CCPoint tileCoordForPosition(CCPoint point); };
Player::Player(void) { } Player::~Player(void) { } bool Player::init() { return true; } void Player::run() { CCSpriteFrameCache * freamCache = CCSpriteFrameCache::sharedSpriteFrameCache(); freamCache->addSpriteFramesWithFile("run.plist","run.png"); CCSpriteFrame *frame = NULL; CCArray *freamlist =CCArray::create(); for (int i =1; i <= 15 ; i++) { frame = freamCache->spriteFrameByName(CCString::createWithFormat("run%d.png",i)->getCString()); freamlist->addObject(frame); } CCAnimation *anination = CCAnimation::createWithSpriteFrames(freamlist); anination->setLoops(-1); anination->setDelayPerUnit(0.08f); CCAnimate *animate = CCAnimate::create(anination); m_sprite->runAction(animate); } void Player::SetViewPointByPosition() { if (m_sprite == NULL) { return ; } CCLayer *parent = (CCLayer*)this->getParent(); CCSize mapTiledNum =m_map->getMapSize(); CCSize tiledSize = m_map->getTileSize(); CCSize mapsize = CCSize::CCSize(mapTiledNum.width*tiledSize.width,mapTiledNum.height*tiledSize.height); CCSize visibleSize = CCDirector::sharedDirector()->getWinSize(); CCPoint spritepoint = getPosition(); float x = max(spritepoint.x,visibleSize.width/2); float y = max(spritepoint.y,visibleSize.height/2); x = min(x,mapsize.width-visibleSize.width/2); y = min(y,mapsize.height- visibleSize.height/2); CCPoint destPos = CCPoint::CCPoint(x,y); CCPoint centerpos = CCPoint::CCPoint(visibleSize.width/2,visibleSize.height/2); CCPoint viewpos = ccpSub(centerpos,destPos); parent->setPosition(viewpos); } bool Player::SetPlayerPosition(int x,int y) { CCSize spritesize = m_sprite->getContentSize(); CCPoint dspoint = CCPoint(x+spritesize.width/2,y); CCPoint tiledpos =tileCoordForPosition(ccp(dspoint.x,dspoint.y)); CCLOG("tiled x = %f,y = %f",tiledpos.x,tiledpos.y); int tiledchild = meta->tileGIDAt(tiledpos); if(tiledchild != 0) { CCDictionary * propertydict = m_map->propertiesForGID(tiledchild); const CCString * prop = propertydict->valueForKey("collidable"); if(prop->m_sString.compare("true") == 0) { return false; } } Entity::SetPlayerPosition(x,y); SetViewPointByPosition(); return true; } void Player::SetTMXTileMap(CCTMXTiledMap *map) { //CC_SAFE_RETAIN(map); //CC_SAFE_RELEASE(m_map); this->m_map = map; this->meta = m_map->layerNamed("meta");//設定圖層不可見 this->meta->setVisible(false); this->meta->retain(); }
//因為精靈的座標是從左下角開始計算,而瓦塊的座標是從左上角開始計算的所以我們需要通過這個函式將精靈座標轉化為瓦塊需要的座標。 CCPoint Player::tileCoordForPosition(CCPoint pos) { CCSize mapTiledNum = m_map->getMapSize(); CCSize tiledSize = m_map->getTileSize(); int x = pos.x/tiledSize.width; //轉換為瓦塊的個數橫座標 int y = (640 - pos.y)/tiledSize.height; //轉換為瓦塊的個數縱座標 if(x >0) { x-=1; } if(y >0) { y-=0; } return ccp(x,y); }
這樣我們的精靈在跑動的過程中就會遇到障礙物而跑不過去。