三消類遊戲《萬聖大作戰》04:添加時間與分數

1. 添加時間

一般消除類遊戲,要麼關卡,要麼限制時間,但是關卡的設計很麻煩,個體創作,沒有那麼多精力,

所以只能通過限制時間來使遊戲有些可玩性,但這種可玩性極低啊,反覆挑戰同樣的東西,很容易疲勞的。

在程序中加時間,如何操作呢?

當然,先要有個時間的全局變量,在初始化遊戲界面的時候,顯示在屏幕上:

1
2
3
4
5
6
7
// 加載ttf字體  
    TTFConfig config("fonts/haibaoti.ttf",30);  
    // 遊戲時間的顯示  
    auto labelTime = Label::createWithTTF(config,StringUtils::format("Time: %d ",m_time));  
    labelTime -> setPosition(Vec2( labelTime->getContentSize().width , GAME_SCREEN_HEIGHT - labelTime->getContentSize().height ));  
    labelTime -> setTag(11);  
    this ->addChild(labelTime);

然後還要有個函數,讓它每秒都會減少

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void GameScene::myClock( float dt )  
{  
    // 時間變化  
    --m_time;  
    // 如果時間歸0,那麼執行遊戲結束動畫,並跳到遊戲結束界面  
    if( m_time == 0 )  
    {  
        Label *labelTime = (Label *)this -> getChildByTag(11);  
        labelTime->setScale(0);  
   
        // 遊戲結束 動畫  
        auto gmov = Sprite::create("pic_gameover.png");  
        gmov->setPosition(Point(GAME_SCREEN_WIDTH/2,GAME_SCREEN_HEIGHT*1.5));  
        this->addChild(gmov);  
   
        auto action = MoveTo::create(3.0f, Point(GAME_SCREEN_WIDTH/2, GAME_SCREEN_HEIGHT/2));    
   
        gmov -> runAction( action );  
   
        // 跳轉到遊戲結束界面  
        return;  
    }  
    // 如果還有時間,那麼時間減少  
    if( m_time > 0 ) {  
        Label *labelTime = (Label *)this -> getChildByTag(11);  
        labelTime -> setString( StringUtils::format("Time: %d ",m_time));  
    }  
}

但是,別忘了最重要的一步,要將這個倒計時函數加入到計劃任務中,就像之前我們用的檢查精靈。

之前檢查精靈用的是 scheduleUpdate,每一幀都要執行,

而這次,我們用 schedule 就可以,自己指定函數,並且設定間隔時間。

就放在 scheduleUpdate 下面就可以啦。

1
schedule(schedule_selector(GameScene::myClock),1.0f );

然後運行一下,就可以看到倒計時的實現啦。

然後,我們再建立 遊戲結束界面,界面裏放返回遊戲,返回主界面和退出三個按鈕,就可以啦。

代碼就不貼出,具體的可以看文章末尾給出的源碼。


2. 添加分數

光有時間倒計時可不行,要有分數纔有意思!

和時間一樣,也要初始化界面中將分數在遊戲界面顯示出來

1
2
3
4
5
// 分數顯示  
    auto labelScore = Label::createWithTTF(config,StringUtils::format("Score: %d ",m_score) );  
    labelScore -> setPosition(Vec2( GAME_SCREEN_WIDTH/2 , GAME_SCREEN_HEIGHT - labelScore->getContentSize().height*2.6 ));  
    labelScore -> setTag(10);  
    this->addChild(labelScore);

但是 分數 就不需要像時間那樣,單獨弄一個函數,分數是時時刷新的,所以跟隨每幀刷新即可,就是在update函數內加上分數的顯示

1
2
3
4
5
// GameScene.cpp  update()函數  
   
// 分數變化  
    Label *labelScore = (Label *)this -> getChildByTag(10);  
    labelScore -> setString( StringUtils::format("Score: %d ",m_score));

然後在相應位置,進行分數的加,

我是在 精靈下落處,每消除一個精靈加30分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// GameScene.cpp  修改後的 fillSprite  
   
// 填補空缺位置  
void GameScene::fillSprite()    {  
   
    // 下落精靈總個數(方便後面分數的計算)  
    int sum = 0;  
     // 重置移動方向標誌  
    isAction = true;  
   
    int *colEmptyInfo = (int *)malloc(sizeof(int) * COLS);  
    memset((void *)colEmptyInfo, 0, sizeof(int) * COLS);  
       
    // 將存在的精靈降落下來  
    SpriteShape *spr = NULL;  
    for (int c = 0; c < COLS; c++) {  
        int removedSpriteOfCol = 0;  
        // 自底向上  
        for (int r = 0; r < ROWS; r++ ) {  
            spr = map[r][c];  
            if ( spr == NULL ) {  
                ++removedSpriteOfCol;  
            else {  
                if ( removedSpriteOfCol > 0) {  
                    int newRow = r - removedSpriteOfCol;  
                    map[newRow][c] = spr;  
                    map[r][c] = NULL;  
                     
                    Point startPosition = spr->getPosition();  
                    Point endPosition = positionOfItem(newRow, c);  
                    float speed = (startPosition.y - endPosition.y) / GAME_SCREEN_HEIGHT*3;  
                    spr->stopAllActions();  
                    spr->runAction(CCMoveTo::create(speed, endPosition));  
                       
                    spr->setRow(newRow);  
                }  
            }  
        }  
           
        // 記錄相應列數移除的數量  
        colEmptyInfo[c] = removedSpriteOfCol;  
        sum+=removedSpriteOfCol;  
    }  
       
    // 新建新的精靈,並降落  
    for (int c = 0; c < COLS; ++c ) {  
        for (int r = ROWS - colEmptyInfo[c]; r < ROWS ; ++r ) {  
            createSprite(r,c);  
        }  
    }  
       
    m_score += sum*30;  
    free(colEmptyInfo);  
}

接下里,就是在遊戲結束界面,將自己的分數傳遞過去。

如果看源碼,會發現, 在時間到0時,我用的 scheduleOnce ( 有個動畫,要delay一下)

然後跳轉到一個遊戲結束函數,就是在這個函數,進行了分數的傳遞。

當然,相應的 GameOverScene中,也要設置相應的函數來接受分數。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// GameScene.cpp  
   
// 遊戲結束函數  
void GameScene::gameOver(float dt)  
{  
    auto scene = Scene::create();  
    auto layer = GameOver::create();  
    // 傳遞當前遊戲獲得的分數  
    layer -> setScore( m_score );  
    scene -> addChild( layer );  
   
    CCTransitionScene* reScene= CCTransitionFadeUp::create(1.0f, scene);  
    CCDirector::sharedDirector()->replaceScene(reScene);  
}
1
2
3
4
5
6
7
// GameOverScene.cpp   
   
void GameOver::setScore( int sc )  
{  
    auto labelScore = (Label *)this -> getChildByTag(13);  
    labelScore -> setString( StringUtils::format(" %d ",sc));  
}

Ok啦,現在可以運行爽爽啦

現在做的東東已經有基本雛形了,

剩下的就屬於額外的東西,往上添加就行了。

後面的文章將會對本遊戲進行修飾,比如:

—— 消除的特效

—— 消除4個,產生消除一列 或者 一行的東東

—— 音樂、音效的添加

—— 最高分的記錄

等等~


本章資源和代碼:點擊下載


感謝本文筆者LT大樹_的分享,
Cocos引擎中文官網歡迎更多的開發者分享開發經驗,來稿請發送至[email protected]

來源網址:http://blog.csdn.net/lttree/article/details/43196817

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章