跳轉到

第 1 步:節奏大師

先來測測你的節奏感!每按一次空白鍵,小精靈就轉一下,畫面也會告訴你這次和上次按鍵隔了幾毫秒(1000 毫秒 = 1 秒)。目標是剛好隔 1 秒,誤差在 50 毫秒內,就會出現綠色的 PERFECT!

第 1 步的畫面:小精靈在畫面中央,左上角顯示 1151 ms

完整程式

main.cpp
// 第 1 步:節奏大師——按空白鍵,看看兩次之間隔了多久。
#include <string>

#include "GridPlusPlus.h"

using gridpp::GameEngine;
using gridpp::GridObject;
using gridpp::Overlay;

Overlay message;
double last_press = -1;  // 上一次按空白鍵的時間(秒);-1 代表還沒按過

void Dance(GameEngine game, GridObject self) {
    if (!game.keyPressed(KEY_SPACE)) return;  // 這一幀沒按空白鍵,就什麼都不做

    self.setDirection(self.direction() + 1);  // 小精靈轉 90 度

    double now = game.time();
    if (last_press >= 0) {
        int gap = (now - last_press) * 1000;  // 換算成毫秒
        if (gap >= 950 && gap <= 1050) {
            message.setText(std::to_string(gap) + " ms  PERFECT!");
            message.setColor(GREEN);
        } else {
            message.setText(std::to_string(gap) + " ms");
            message.setColor(YELLOW);
        }
    }
    last_press = now;
}

int main() {
    GameEngine game(15, 11, 48);
    game.loadAssets("pacman.db");
    game.setBackgroundColor(BLACK);

    GridObject pacman = game.addObject("pacman", nullptr, Dance);
    pacman.setPosition(7, 5);

    message = game.addTextOverlay("Press SPACE!", 20, 20, 40, YELLOW);
    game.addTextOverlay("Goal: press exactly 1 second apart", 20, 480, 24, GRAY);

    game.run();
    return 0;
}

在專案資料夾的終端機編譯並執行(按 Up 鍵可以叫出上次的指令):

g++ -std=c++17 main.cpp -o game -lraylib -lGL -lm -lpthread -ldl -lrt -lX11 && ./game
g++ -std=c++17 main.cpp -o game $(pkg-config --cflags --libs raylib) && ./game

你能連續拿到幾次 PERFECT?

程式怎麼運作

每一幀都會執行的函式

遊戲畫面其實是一張張圖片快速播放出來的,每一張叫做一幀,Grid++ 每秒大約畫 60 幀。

GridObject pacman = game.addObject("pacman", nullptr, Dance);

這行建立了小精靈,並且告訴 Grid++:「每一幀都幫我執行一次 Dance 函式」。所以 Dance 一秒會被執行 60 次,我們只要在裡面檢查「這一幀有沒有按空白鍵」就好。

讀取鍵盤

if (!game.keyPressed(KEY_SPACE)) return;

game.keyPressed(KEY_SPACE) 只有在空白鍵剛被按下的那一幀是 true。這一幀沒按的話,return 直接結束函式,什麼都不做。

計算時間差

game.time() 會告訴你遊戲開始到現在過了幾秒。把「這次按下的時間」減掉「上次按下的時間」,就是兩次之間隔了多久:

int gap = (now - last_press) * 1000;  // 換算成毫秒

last_press 寫在所有函式外面(全域變數),所以 Dance 結束後它的值還會留著,下一次按鍵時才找得到「上次」的時間。

改變畫面上的字

message 是畫在畫面最上層的文字,setText 換掉它的內容,setColor 換顏色。小精靈轉向用的是 setDirection,0、1、2、3 分別代表朝右、上、左、下。

試試看

  • 把目標改成 0.5 秒(500 毫秒)。
  • 把 KEY_SPACE 換成 KEY_ENTER,改用 Enter 鍵來玩。
  • 挑戰:多一個 perfect_count 變數,記錄總共拿到幾次 PERFECT,顯示在畫面上。(提示:數字要變成文字,可以用 std::to_string(perfect_count)。)
跑不起來,或結果和圖片不一樣?

先確認整份程式都有貼上、而且有存檔。還是不行的話,可以直接執行這一步的參考答案,看看哪裡不同:專案的 steps/ 資料夾裡有每一步的完整程式。

想知道更多?

第 2 步:小精靈出發