簡體   English   中英

如何使用 C 在 Ncurses 中實現獨立於用戶輸入的獨立移動?

[英]How to implement independent movement apart from user input in Ncurses with C?

我試圖讓“o”獨立於用戶輸入而向下移動。 我計划對另一個對象使用用戶輸入。 如果沒有 if 語句,“o”將增加並減少。 使用 getch,“o”僅在有輸入時移動。

 while(1) {
 clear(); // Clear the screen of all
 // previously-printed characters
 mvprintw(y, x, "o"); // Print our "ball" at the current xy position
        int ch = getch();     //THE PROBLEM
        // Move the player's ship left or right based on user input, currently controls the "o" IKNOW. IT's JUST TESTING. THAT"S BESIDES THE PROBLEM
        if (ch == 'a') x--;
        else if(ch == 'd') x++;
        else if(ch == 'q') break;// quit option  i
 refresh();

 usleep(DELAY);
 // Shorter delay between movements
 y++; // Advance the ball down
 }

我嘗試了不同的循環,將運動部分放入不同的函數中,但我仍然要求運動在 while 循環中。 有人告訴我 while(1) 是每 1 幀,但輸出似乎停留在需要輸入才能進入下一幀。 我怎么能獨立移動“o”?

閱讀編輯

我保留原始答案,因為它可能對有類似問題但不需要多線程的人有用。

我不知道你到底想達到什么目的,但希望這能讓你更接近你的目標。 實際上,您需要做的就是在 main 函數的頂部添加DELAY毫秒的timeout

這行得通,但可能並不理想——每次按下 a/d 鍵時,飛船都會下降 1 行。 您可以通過在if (ch == 'a'/'d') x--/++; // continue;之后添加 'continue' 來扭轉這種局面。 if (ch == 'a'/'d') x--/++; // continue; (相反,我的意思是“按下 a+d 鍵時根本不向下移動”)

這可能是您想要的行為,但可能更好? 解決方案可能是使用多線程(*nix 系統上的 pthreads,我想 Win32 API 可以在 Windows 上做同樣的事情)。 我試過了,但是你可能需要做更多的研究,因為在嘗試了幾分鍾后我無法讓它工作(ncurses 庫可能不喜歡多線程或者我做錯了什么 [可能是后者]) (再次,見編輯)。

#include <ncurses.h>

const int DELAY = 1000;

int x = 0;
int y = 0;

int main() {
    initscr();
    timeout(DELAY);
    for (;;) {
        clear();
        mvprintw(y, x, "o");

        int ch = getch();
        if (ch == 'a') x--;
        else if (ch == 'd') x++;
        else if (ch == 'q') return 0;

        y++;
    }

    return 0;
}

希望這可以幫助!

編輯/更新:我得到了線程版本工作

所以,我不知道為什么線程以前不工作,但現在我有一個工作程序,沒有以前版本的問題:

#include <ncurses.h>
#include <pthread.h>
#include <unistd.h>

const int DELAY = 1000000;

int x = 0;
int y = 0;
pthread_mutex_t y_mutex;

void *inc_y(void* ptr) {
    for (;;) {
        pthread_mutex_lock(&y_mutex);
        y++;
        pthread_mutex_unlock(&y_mutex);
        usleep(DELAY);
    }
}

void *draw(void* ptr) {
    initscr();
    timeout(1);
    for (;;) {
        int ch = getch();
        if (ch == 'a') x--;
        else if (ch == 'd') x++;
        else if (ch == 'q') return 0;

        clear();
        mvprintw(y, x, "o");
    }
}

int main() {
    pthread_mutex_init(&y_mutex, NULL);

    pthread_t inc_y_thread, draw_thread;
    pthread_create(&inc_y_thread, NULL, inc_y, NULL);
    pthread_create(&draw_thread, NULL, draw, NULL);
    pthread_join(inc_y_thread, NULL);
    pthread_join(draw_thread, NULL);

    pthread_mutex_destroy(&y_mutex);

    return 0;
}

請注意,雖然我沒有使用 C 多線程的經驗,並且y的互斥鎖可能不是絕對必要的,但我認為這將確保在draw讀取y變量時,它不會也被寫入。

delaymove將在延遲一秒后增加行。
manualmove將根據用戶輸入修改行和列。 可以使用箭頭鍵以及adwx
這些函數在循環中調用。
timeout設置getch在返回ERR之前等待輸入的毫秒數。

#include <stdio.h>
#include <ncurses.h>
#include <time.h>

#define DELAY  1.0
#define BILLION  1E9

void delaymove ( int *x, int *y) {
    static struct timespec start;
    static double delay = 0.0;
    struct timespec stop;
    double elapsed;

    if ( delay < .0001) {
        clock_gettime ( CLOCK_REALTIME, &start);
        delay = DELAY;
    }
    clock_gettime ( CLOCK_REALTIME, &stop);
    elapsed = stop.tv_sec - start.tv_sec;
    elapsed += ( stop.tv_nsec - start.tv_nsec) / BILLION;
    if ( elapsed < delay) {
        return;//if delay is still in effect
    }
    clock_gettime ( CLOCK_REALTIME, &start);
    ++(*x);
}

int manualmove ( int *x, int *y) {
    int ch = 0;

    ch = getch(); // if no input before timeout, ch will be ERR
    switch ( ch) {
        case ERR:
            break;
        case 1:
            while ( getch() != 1) {} //resume with another ctrl+a
            break;
        case 'q':
            return 1;
        case KEY_LEFT:
        case 'a':
            if ( *y > 0) {
                --(*y);
            }
            break;
        case KEY_RIGHT:
        case 'd':
            ++(*y);
            break;
        case KEY_UP:
        case 'w':
            if ( *x > 0) {
                --(*x);
            }
            break;
        case KEY_DOWN:
        case 'x':
            ++(*x);
            break;
    }
    return 0;
}

int main ( void) {
    int row = 0;
    int col = 0;
    int rw = 0;
    int cl = 0;
    int r = 0;
    int c = 0;

    initscr ( );
    noecho ( );
    timeout ( 20); // milliseconds getch waits for a character
    keypad ( stdscr, TRUE);
    curs_set ( 0); // hide cursor
    getmaxyx ( stdscr, row, col);
    rw = 0;
    cl = col / 2;
    while(1)
    {
        r = rw;
        c = cl;
        delaymove ( &rw, &cl);
        if ( manualmove ( &rw, &cl)) {
            break;
        }
        if ( rw > row - 4) {
            rw = row - 4;
        }
        if ( cl > col - 2) {
            cl = col - 2;
        }
        move ( r, c);
        printw ( " ");
        move ( rw, cl);
        printw ( "o");
        refresh ( );
    }
    endwin ( );
    return 0;
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM