繼自定義動畫系統後,本篇實現《保衛蘿卜》風格的關卡選擇場景:背景+開始按鈕+中間可水平拖動的關卡預覽列表(預覽圖+可用塔圖標),鬆手自動對齊當前關卡至屏幕中央。
...
每關僅需兩張圖:預覽背景圖與塔圖標合集圖。避免硬編碼,便於策劃維護。
// 單關摘要
class LevelSummary : public CCObject {
CC_SYNTHESIZE_READONLY(string, bgName, BgName);
CC_SYNTHESIZE_READONLY(string, towerIconName, TowerIconName);
static LevelSummary* create(string bg, string icon);
};
// 關卡集合單例
class LevelsSummary : public CCObject {
CC_SYNTHESIZE_READONLY(int, levelCount, LevelCount);
CCArray* levelsArray; // LevelSummary*
static LevelsSummary* SharedLevelsSummary();
LevelSummary* GetLevel(int index);
bool init(); // 解析 levels_summary.xml
};
levelsNode,掛載所有關卡預覽精靈。(winW/2, winH/2),後續每關向右偏移 winW。startBtnY 供開始按鈕定位。for (int i=0; iGetLevel(i); auto map = CCSprite::createWithSpriteFrameName(summary->getBgName().c_str()); map->setPosition(ccp(winW/2 + i*winW, winH/2)); levelsNode->addChild(map); auto icon = CCSprite::createWithSpriteFrameName(summary->getTowerIconName().c_str()); icon->setPosition(ccp(winW/2 + i*winW, winH/2 - map->getContentSize().height/2 - icon->getContentSize().height/2)); levelsNode->addChild(icon); }
// 觸摸開始
void ccTouchesBegan(CCSet* touches, CCEvent* event) {
startDragPoint = touch->getLocation();
startDragNodePoint = levelsNode->getPosition();
}
// 觸摸移動:節點跟隨手指水平位移
void ccTouchesMoved(CCSet* touches, CCEvent* event) {
float dx = touch->getLocation().x - startDragPoint.x;
levelsNode->setPosition(ccp(startDragNodePoint.x + dx, startDragNodePoint.y));
}
// 觸摸結束:判斷方向,切換關卡索引,動畫對齊
void ccTouchesEnded(CCSet* touches, CCEvent* event) {
float dx = touch->getLocation().x - startDragPoint.x;
int newIdx = selectLevelIndex;
if (dx > 200) newIdx = max(0, selectLevelIndex - 1); // 右滑 → 上一關
else if (dx < -200) newIdx = min(levelCount-1, selectLevelIndex + 1); // 左滑 → 下一關
ChangeSelectLevel(newIdx);
}
void ChangeSelectLevel(int idx) {
selectLevelIndex = idx;
levelsNode->setPositionX(-idx * winSize.width); // 瞬間對齊,可改用 CCMoveTo 動畫
}
