简体   繁体   English

如何同时移动两个对象(Ncurses)

[英]How to move two objects simultaneously (Ncurses)

I am trying to get a basic simultaneous movement of both a player and an enemy working.我正在尝试让玩家和敌人同时进行基本的动作。 Is there any way I can accomplish this correctly?有什么办法可以正确地完成这个吗?

Below is a crude way of accomplishing.下面是一种粗略的实现方式。 I would like to move while the x is also moving but I can only get one of them at a time to work.我想在 x 也在移动的同时移动,但我一次只能让其中一个工作。 I tried using while loops but perhaps something else is needed...我尝试使用 while 循环,但也许还需要其他东西......

Any tips?有小费吗?

#include <stdio.h>
#include <stdlib.h>
#include <curses.h>
#include <windows.h>

WINDOW* createwindow();
char theplayer();
char theenemy();

int main()
{
    initscr();

    WINDOW* border=createwindow();

    while(1)
    {
    theplayer();
    theenemy();
    }
    wgetch(border);
    endwin();
    return 0;
}

WINDOW* createwindow()

{
    WINDOW* temp=newwin(15,40,10,10);
    box(temp,0,0);
    return temp;
}

char theplayer(WINDOW* border)
{
    int playerlocationy=3;
    int playerlocationx=3;
    int input;
    char player='@';
    keypad(border,true);

    mvwprintw(border,3,3,"%c",player);

    while(1)
    {
        input=wgetch(border);

        switch (input)
        {
            case KEY_LEFT:
            mvwprintw(border,playerlocationy,playerlocationx,"%c",' ');
            playerlocationx--;
            mvwprintw(border,playerlocationy,playerlocationx,"%c", player);
            break;
            case KEY_RIGHT:
            mvwprintw(border,playerlocationy,playerlocationx,"%c",' ');
            playerlocationx++;
            mvwprintw(border,playerlocationy,playerlocationx,"%c", player);
            break;
            case KEY_UP:
            mvwprintw(border,playerlocationy,playerlocationx,"%c",' ');
            playerlocationy--;
            mvwprintw(border,playerlocationy,playerlocationx,"%c", player);
            break;
            case KEY_DOWN:
            mvwprintw(border,playerlocationy,playerlocationx,"%c",' ');
            playerlocationy++;
            mvwprintw(border,playerlocationy,playerlocationx,"%c", player);
            break;
            default:
            break;
        }
break;
    }
return player;
}

char theenemy(WINDOW* border)
{
    char enemy='X';
    int enemylocationy=9;
    int enemylocationx=9;

    while(1)
    {
        mvwprintw(border,enemylocationy,enemylocationx,"%c", enemy);

        mvwprintw(border,enemylocationy,enemylocationx,"%c",' ');
        enemylocationx++;
        mvwprintw(border,enemylocationy,enemylocationx,"%c", enemy);
        wrefresh(border);
        Sleep(1000);
    }
return 0;
}

To start, these function declarations首先,这些 function声明

char theplayer();
char theenemy();

are an obsolescent feature of C, that say these functions will take an unspecified but fixed number of arguments. With this, the compiler cannot reason about what an invocation of these functions should look like.是 C 的过时功能,表示这些函数将采用未指定但固定的数字 arguments。有了这个,编译器无法推断这些函数的调用应该是什么样子。

This is hiding the fact that your program has undefined behaviour .这隐藏了您的程序具有未定义行为的事实。 Both function definitions require a WINDOW * argument, but you call them with no arguments.两个 function定义都需要一个WINDOW *参数,但您调用它们时没有 arguments。

while(1)
{
    theplayer();
    theenemy();
}

To any extent that this program functions as is, is pure chance.在任何程度上,该程序按原样运行纯属偶然。 Always use proper function prototypes in your declarations始终在声明中使用正确的function 原型

WINDOW *createwindow(void);
char theplayer(WINDOW *);           
char theenemy(WINDOW *);

which will help to find errors.这将有助于发现错误。


Using <windows.h> for Sleep reduces the portability of your program.使用<windows.h>进行Sleep会降低程序的可移植性。 You are already using curses , which provides the very similar napms function.您已经在使用curses ,它提供非常相似的napms function。


As for "simultaneous movement", the general idea is to have only one main event loop.至于“同步移动”,大意是只有一个主事件循环。 Every iteration, this loop每次迭代,这个循环

  1. handles input处理输入
  2. updates entities更新实体
  3. redraws the screen重绘屏幕

Nothing else should block execution of the program (ie, loop forever).没有其他东西应该阻止程序的执行(即,永远循环)。

To update your enemy, you will need some way of tracking how much time has passed.要更新你的敌人,你需要一些方法来跟踪已经过去了多少时间。 This can be as advanced as delta timing or as simple as a frame counter, as shown below.这可以像增量定时一样先进,也可以像帧计数器一样简单,如下所示。

Here is a cursory example to get you started:这是一个粗略的示例,可以帮助您入门:

#include <curses.h>

struct entity {
    int y;
    int x;
    unsigned char repr;
};

void update_player(struct entity *, int);
void update_enemy(struct entity *, unsigned);
void draw_entity(struct entity *, WINDOW *);

int main(void)
{
    initscr();
    noecho();
    curs_set(0);

    WINDOW *field = newwin(15, 40, 10, 10);
    keypad(field, TRUE);
    wtimeout(field, 0);

    struct entity player = { 3, 3, '@' };
    struct entity enemy = { 9, 9, 'X' };
    unsigned tick = 1;

    while (1) {
        /* handle input */
        int c = wgetch(field);

        if ((c & A_CHARTEXT) == 'q')
            break;

        /* update stuff */
        update_player(&player, c);
        update_enemy(&enemy, tick);

        /* draw things */
        werase(field);
        box(field, 0, 0);
        draw_entity(&player, field);
        draw_entity(&enemy, field);
        wrefresh(field);

        tick = (tick > 60) ? 0 : tick + 1;
        napms(16);
    }

    delwin(field);
    endwin();
}

void update_player(struct entity *p, int ch)
{
    switch (ch) {
        case KEY_LEFT:
            p->x--;
            break;
        case KEY_RIGHT:
            p->x++;
            break;
        case KEY_UP:
            p->y--;
            break;
        case KEY_DOWN:
            p->y++;
            break;
    }
}

void update_enemy(struct entity *e, unsigned t)
{
    if (t == 60)
        e->x++;
}

void draw_entity(struct entity *et, WINDOW *f)
{
    mvwaddch(f, et->y, et->x, et->repr);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM