如何同时移动两个对象(Ncurses)
How to move two objects simultaneously (Ncurses)
我正在尝试让玩家和敌人同时进行基本的动作。有什么方法可以正确完成此操作吗?
下面是粗略的实现方式。我想移动 而 x 也在移动,但我一次只能让其中一个工作。我尝试使用 while 循环,但也许还需要其他东西...
有什么建议吗?
#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;
}
首先,这些函数 声明
char theplayer();
char theenemy();
是 C 的 obsolescent feature,也就是说这些函数将采用 未指定 但固定数量的参数。有了这个,编译器就无法推断出这些函数的调用应该是什么样子。
这隐藏了您的程序有 undefined behaviour 的事实。两个函数 definitions 都需要一个 WINDOW *
参数,但你调用它们时没有参数。
while(1)
{
theplayer();
theenemy();
}
这个程序能按原样运行在任何程度上纯属偶然。始终在声明中使用正确的函数原型
WINDOW *createwindow(void);
char theplayer(WINDOW *);
char theenemy(WINDOW *);
这将有助于发现错误。
对 Sleep
使用 <windows.h>
会降低程序的可移植性。您已经在使用 curses
,它提供了非常相似的 napms
功能。
至于“同步移动”,大意是只有一个主事件循环。每次迭代,这个循环
- 处理输入
- 更新实体
- 重绘屏幕
没有其他东西应该阻止程序的执行(即,永远循环)。
要更新你的敌人,你需要一些方法来跟踪已经过了多少时间。这可以像 delta timing 一样高级,也可以像帧计数器一样简单,如下所示。
这是一个粗略的示例,可以帮助您入门:
#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 */
wclear(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);
}
我正在尝试让玩家和敌人同时进行基本的动作。有什么方法可以正确完成此操作吗?
下面是粗略的实现方式。我想移动 而 x 也在移动,但我一次只能让其中一个工作。我尝试使用 while 循环,但也许还需要其他东西...
有什么建议吗?
#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;
}
首先,这些函数 声明
char theplayer();
char theenemy();
是 C 的 obsolescent feature,也就是说这些函数将采用 未指定 但固定数量的参数。有了这个,编译器就无法推断出这些函数的调用应该是什么样子。
这隐藏了您的程序有 undefined behaviour 的事实。两个函数 definitions 都需要一个 WINDOW *
参数,但你调用它们时没有参数。
while(1)
{
theplayer();
theenemy();
}
这个程序能按原样运行在任何程度上纯属偶然。始终在声明中使用正确的函数原型
WINDOW *createwindow(void);
char theplayer(WINDOW *);
char theenemy(WINDOW *);
这将有助于发现错误。
对 Sleep
使用 <windows.h>
会降低程序的可移植性。您已经在使用 curses
,它提供了非常相似的 napms
功能。
至于“同步移动”,大意是只有一个主事件循环。每次迭代,这个循环
- 处理输入
- 更新实体
- 重绘屏幕
没有其他东西应该阻止程序的执行(即,永远循环)。
要更新你的敌人,你需要一些方法来跟踪已经过了多少时间。这可以像 delta timing 一样高级,也可以像帧计数器一样简单,如下所示。
这是一个粗略的示例,可以帮助您入门:
#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 */
wclear(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);
}