2013-03-11 28 views
0

我是小白到的Cocos2D-X,但我一直在編程很長一段時間......我想知道這是什麼代碼的一點是:boc bRet在cocos2d-X循環中做什麼?

我的困惑主要是與這一部分:

bool bRet = false; 做 {}而(0)

這裏是整個方法給一些背景:

bool GameScene::init() 
    { 
     CCLog("GameScene::init"); 
    bool bRet = false; 
    do 
    { 
     ////////////////////////////////////////////////////////////////////////// 
     // super init first 
     ////////////////////////////////////////////////////////////////////////// 
     CC_BREAK_IF(! CCLayer::init()); 

      // Initialize the parent - gets the sprite sheet loaded, sets the background and inits the clouds 
      MainScene::init(); 

      // Start off as game suspended 
      gameSuspended = true; 

      // Get the bird sprite 
      CCSprite *bird = CCSprite::createWithSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName("bird.png")); 
      this->addChild(bird, 4, kBird); 

      // Initialize the platforms 
      initPlatforms(); 

      // Create the bonus sprite 
      CCSprite *bonus; 

      // Load in the bonus images, 5, 10, 50, 100 
      for(int i=0; i<kNumBonuses; i++) 
      { 
        bonus = CCSprite::createWithSpriteFrame(CCSpriteFrameCache::sharedSpriteFrameCache()->spriteFrameByName(bonus_image[i])); 
        this->addChild(bonus,4, kBonusStartTag+i); 
        bonus->setVisible(false); 
      } 

      // Create the Score Label 
      CCLabelBMFont* scoreLabel = CCLabelBMFont::labelWithString("0", "Images/bitmapFont.fnt"); 
      this->addChild(scoreLabel, 5, kScoreLabel); 

      // Center the label 
      scoreLabel->setPosition(ccp(CCDirector::sharedDirector()->getWinSize().width/2,CCDirector::sharedDirector()->getWinSize().height - 50)); 

      // Start the GameScene stepping 
      schedule(schedule_selector(GameScene::step)); 

      // Enable the touch events 
      setTouchEnabled(true); 
      // Enable accelerometer events 
      setAccelerometerEnabled(true); 

      // Start the game 
      startGame(); 

    bRet = true; 
} while (0); 

return bRet; 
} 

這個代碼來自:https://code.google.com/p/tweejump-cocos2dx/source/browse/trunk/Classes/GameScene.cpp

它是一個開源遊戲。

我明白bRet代表bool返回值,但我對一些事情感到困惑......我被這個困惑的一個原因就是爲什麼即使這樣的程序?其次,while循環如何知道bRet == false如果它只等於0 ...我錯過了什麼?

我的另一個問題是你怎麼知道什麼時候使用語法CCdataType * varName = ...,與CCdataType * pVarName = ...我知道第二個是一個指針,但也許我失蹤了一些東西......我不明白其中的差別。是第一個尊重聲明?

+0

這就是整個代碼? 'do {} while(0)'是一個nop - 似乎缺少某些東西。 – Voo 2013-03-11 23:48:55

+0

不,我使用它作爲一個例子,通常有很多...通常來自場景:: init()方法...我只是把它拋出去了,因爲它可能是模棱兩可的...我是cocos2d-X通過查看那裏的開源遊戲,我在其中許多人都看到過。 – 2013-03-11 23:52:05

回答

3

您的示例錯過了解釋所有內容的基本部分 - 代碼中的真實邏輯。我不是在科科斯羣島的專家,但是從我所看到的,它通常用於這樣的:

bool bRet = false; 
do 
{ 
    CC_BREAK_IF(!conditionA); // same as if (!conditionA) break; 
    ... some code which possibly sets bRet 
    CC_BREAK_IF(!conditionB);   
    ... some other code which possibly sets bRet 
    CC_BREAK_IF(!conditionC);   
    ... some other code which possibly sets bRet 
    bRet = true; 
} while (0); 
return bRet; 
在這種情況下

,它允許代碼跳轉到,而無需訴諸goto,或嵌套return語句一堆if陳述。對比一下:

bool bRet = false; 
if (conditionA); 
{ 
    ... some code which possibly sets bRet 
    if (conditionB) 
    { 
     ... some other code which possibly sets bRet 
     if (conditionC);   
     { 
      ... some other code which possibly sets bRet 
     } 
    } 
} 
bRet = true; 

return bRet; 
+0

哦,這使得方式更有意義...如果CC_Break_If返回0,wile語句會中斷嗎? – 2013-03-11 23:57:16

+1

是的。 'break'打破C/C++中的任何循環結構 – 2013-03-11 23:58:15

2

我發現the rationale on the Cocos2d-x forum

此前的Cocos2D-X的開發者寫道,管理它的清理與goto S碼:

#define check(ret) if(!ret) goto cleanup; 

void func() 
{ 
    bool bRet = false; 

    bRet = doSomething(); 
    check(bRet); 
    bRet = doSomethingElse(); 
    check(bRet); 

    bRet = true; 

cleanup: 
    // Do clean up here 

    return bRet; 
} 

正如你所看到的,這是跳轉到清理在最後的一個真正噁心的方式如果沿途出現任何問題,可以使用該功能。每次調用函數都會返回它是否成功。然後使用check宏查看bRet是否爲真,如果不是,則直接跳轉到cleanup標籤。

然後,他決定擺脫goto S和它從一個do while循環改爲break

#define CC_BREAK_IF(cond) if(!cond) break; 

void func() 
{ 
    bool bRet = false; 

    do { 
    bRet = doSomething(); 
    CC_BREAK_IF(bRet); 
    bRet = doSomethingElse(); 
    CC_BREAK_IF(bRet); 

    bRet = true; 
    } while (0); 

    // Do clean up here 

    return bRet; 
} 

這恰好具有同樣的效果。它僅使用break作爲goto機制跳轉到do while循環後的代碼。

+0

將此與我重寫的所謂有問題的代碼進行比較:https://gist.github.com/LearnCocos2D/5139277不需要像do/while(0)那樣的奇怪語言結構 – LearnCocos2D 2013-03-12 00:38:02

1

沒有意義,它只是不好的風格。整個方法可以(也應該)被改寫爲:

bool GameScene::init() 
{ 
    CCLog("GameScene::init"); 

    if (!CCLayer::init()) 
     return false; 

    // Initialize the parent - gets the sprite sheet loaded, sets the background and inits the clouds 
    MainScene::init(); 

    // … lots of scene setup code here ... 

    return true; 
} 

我見過在發動機運行的主循環類似的代碼,但在這種情況下,這將是一個死循環:

do 
{ 
    // run game loop as fast as it can 

    // end the game 
    if (userQuits) 
     break; 
} while(true); 

即使你需要額外的範圍,例如爲了避免名稱衝突的局部變量,一對額外的大括號就足夠了。像這樣:

{ 
    int x = 10; 
    // do stuff 
} 
{ 
    int x = 234; // this x is in its own scope 
    // do other stuff 
} 
+0

如果你必須有很多清理代碼,那麼按照你的方式來做就意味着很多重複。也就是說c中的gotos是處理清理的明智方式,在C++中有RAII。 – Voo 2013-03-12 00:09:47

+0

什麼需要重複? init可能失敗並且必須返回false的多個情況?在這種情況下,由於已經有CC_BREAK_IF宏,因此還可能存在CC_RETURN_FALSE_IF宏。 ;) – LearnCocos2D 2013-03-12 00:12:03

+0

如果它不僅僅是'return false;'而是'doStuff1(); doStuff2();返回false;' - 那麼你必須一直重複調用doStuffX。在C++中,可以使用RAII來一起避免所有的問題,在C中可以有很多嵌套的ifs,但goto/break解決方案是衆所周知的解決此問題的解決方案,也在linux內核中。 – Voo 2013-03-12 00:15:38