1

Ncurses ライブラリを使用して C++ で Pacman を作成しています。私のコードでパックマンを動かすことはできますが、キーを押していなくてもパックマンが動き続け、別の方向キーを押すと方向が変わるように動かしたいと思います。現在、キーを押しても pacman は 1 ステップしか進みません。また、パックマンがその方向に移動する前に、キーを 2 ~ 3 回押す必要があります。

if (ch==KEY_LEFT)
{
    int b,row,column;
    getyx(stdscr,row,column);
    int h; 
    do    // do-whileloop to move the pacman left until it hits the wall
    {
        column-=1;
        mvprintw(row,column,">");  //print the ">" symbol
        refresh();
        waitf(0.1);      //this pauses the game for 0.1sec
        attron(COLOR_PAIR(1));      
        mvprintw(row,column,">");
        attroff(COLOR_PAIR(1));
        refresh();
        waitf(0.1);
        mvprintw(row,(b),"O");  //showing the open mouth of pacman
        refresh();
        waitf(0.1);
        attron(COLOR_PAIR(1));a
        mvprintw(row,column,"O");
        attroff(COLOR_PAIR(1));
        h = getch();
    }
    while(h == KEY_LEFT);
}

right = getch();

if条件で右に移動するループ

up = getch();

if条件で上に移動するループ

down = getch();

if条件で下に移動するためのおっと。

4

5 に答える 5

5

これに対する標準的な解決策は、有限状態マシンです。キャラクターには、立っている、上に移動している、右に移動している、下に移動している、左に移動している、死んでいるなど、6 つほどの可能な状態があります。キーを押してキャラクターを直接動かすのではなく、キーを押してキャラクターの状態を変更する必要があります。

このような小さなアプリケーションでは、信じられないほど柔軟な有限状態マシンを実装するのではなく、非常に単純な実装をそのまま使用できます。

enum PlayerState {
    Standing,
    MovingUp,
    MovingRight,
    MovingDown,
    MovingLeft,
    Dead
};

次に、ゲーム ループ内で、フレームに対して適切なアクションを実行する非常に単純な状態チェックを追加できます。

switch(state) {
case Standing:
    break;
case MovingUp:
    player.PositionY += 1;
    break;
// ...
}

最後のステップは、入力をフックすることです。これは、入力を取得する方法によって異なります。コールバックの使用例は次のとおりです。

void KeyDown(Key k) {
    switch(k) {
    case UpArrow:
        if(state != Dead)
            state = MovingUp;
        break;
    case RightArrow:
        if(state != Dead)
            state = MovingRight;
    // ...
    }
}

大規模なプロジェクトでは、より柔軟な有限状態マシンを実装することが重要である理由がわかりますが、この例から理解できるアイデアが得られたことを願っています。

于 2012-09-24T15:54:25.573 に答える
3

kbhitに相当するもの、つまりが必要です。ノンブロッキングgetch. これは実際に解決策を提供O_NONBLOCKし、入力に設定されます。ここで例を参照してください。これを取得したら、連続してループし、実際のキーの押下を待つことなく、キーのヒットを確認するだけです。

于 2012-09-24T15:59:09.797 に答える
1

getch何らかのキーが押されるまで、機能はブロックされます。ブロックされたくない場合は、_kbhit前に呼び出しgetchて、入力バッファーに何かがあることを確認してください。

編集: ncurses 関数nodelayと を見てくださいcbreak。それらは非同期入力を有効にします。

于 2012-09-24T15:56:14.010 に答える
0

model-view-controllerモデルを確認することをお勧めします。これは、この問題や、このようにプログラムを続行した場合に発生する他のすべての問題に役立ちます。

編集:ショートカット

pacmanを継続的に移動するには、pacmanを制御して移動させるための別のスレッドが必要になります。そのためのpthreadを見てください。

プログラムのメイン実行ループでユーザー入力のみを保持する場合、キーを数回押さなければならないという問題も解消されます(ここでの問題は、プロセッサがgetch()行にある必要がある場合です。キーを押すと、検出されません。

于 2012-09-24T15:44:32.513 に答える
0


各方向が 4 つの関数を作成し、その関数内に kbhit によってアクティブになる他の 3 つの方向関数を配置するのは非常に簡単です。

そして、ボタンを押さないと前進し続けるelseステートメントを入れます。つまり、 (!kbhit()); そして、これらすべてをループに入れます。


すべての方向関数に対してこれを行うと、望ましい結果が得られるはずです。

于 2013-01-23T15:00:06.347 に答える