Re: [问题] 贪食蛇遇到阻断式getch问题

楼主: EdisonX (卡卡兽)   2015-08-14 00:36:08
< 原文恕删 >
推 EdisonX: 为什么我觉得最大的问题是在 getch() @@ 08/13 23:22
→ EdisonX: 不知道 linux 有没有像 windows 类似 GetKeyState 的东西 08/13 23:22
→ Feis: 看你怎么想. getch 感觉没什么错啊. 只是他乱用 08/13 23:25
→ EdisonX: @Feis : 但 getch 不是 Blocking 吗 ? 08/13 23:26
→ Feis: nodelay 08/13 23:27
→ EdisonX: 试了一下, 原来是我误会了 @@ 08/13 23:35
嗯,为了庆祝原来我以前误会了一些东西,所以 reply ,
( 虽然 reply 的东西和 getch 没有什么太大关联 ... )
然后原 po 抱歉,我没仔细看你的 code ,
提一个 "我觉得可行" , 但还勉强用不到 Timer , Thread 的方案 。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
首先,小弟以前发过这篇, #1EuwQVAG (C_and_CPP) ,
在 wins 下跑的 , 附 Code , http://codepad.org/qV4nZln0 ,
一些 functions porting 后应该是可以在 linux 底下 run。
架构和程式码说明应该算清楚 , 有提到 Single Thread 流畅度 (Flex) 概念,
只是当时的范例不太好 , 当时是一个 * , 按方向键一下就跟着跑一下 ,
对于动态游戏而言大概不会是 "动一下才跑一下" ,而是画面一直在更新 ,
所以我们原本的架构直接拿来改 , 改成按了某个方向 , 这个点就会一直往
这个方向跑,这种情况下,流畅度设多少就不是很重要,甚至不要有流畅度
都无所谓,然后请先阅过上面这篇文章。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
在原文阅过之后,只有二个地方要注意
(1) 原本的 key_control 里,是做 "取方向键" 、"依方向键执行 Func"
这里的 key_control 改成非常简单的 "状态改变"
什么是状态改变?简单的说,目前移动的方向用一个变量去纪录,移动方向
就是状态,但不做画面更新 , code 如下所示。
void key_control()
{
switch( int ch = getch() )
{
case VK_UP_X : g_dir = DIR_UP ; break;
case VK_DOWN_X : g_dir = DIR_DOWN ; break;
case VK_LEFT_X : g_dir = DIR_LEFT ; break;
case VK_RIGHT_X : g_dir = DIR_RIGHT ; break;
}
}
(2) 画面更新放到主循环 ( code 里面的 while(!Exit) ) ,
也就是主循环变成这样
clock_t t = clock();
while(!Exit){
for(int i=0; i<Flex; ++i){
if(kbhit())
{ // 有按键时再判断
t = clock(); // 计时器重数
key_control();
}
MoveDraw();
Sleep(Delay);
}
// 3 秒没动自动退出
// if( (clock()-t) > CLK_TCK * SECS ) Exit=true;
}
然后注意的是,因为这游戏的画面是一直更新的,所以必须在每个 Frame
都要更新一次状态 (这游戏来说也就是 position )
于是 MoveDraw() 变这样
void MoveDraw()
{
last_x = x , last_y = y;
switch(g_dir) {
case DIR_UP : y = (y ? y-1 : H-1); break;
case DIR_DOWN : y = (y < H ? y+1 : 0 ); break;
case DIR_LEFT : x = (x ? x-1 : W-1 ); break;
case DIR_RIGHT : x = (x < W ? x+1 : 0 ); break;
}
Cls();
DRAW();
}
以上两点修改后,完整的 code 如下
http://codepad.org/gvG1ZhSI
变量弄得很乱 , global 到处飞 , 见谅。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
整个架构有一个大重点:while(!Exit) 一次循环的时间不能太长 ,
不然会抓不到键盘输入 , 或是会觉得非常卡!
大多花时间的地方是在于 DRAW() 里面,由于这范例简单 ,
DRAW 没花到什么时间。如果 DRAW 花时间的话那还是开 Thread 吧。
再来是贪食蛇重绘的方式可能较复杂,但为了避免闪烁,一定不会用
类似 clear_all_screen() 的方式,一定都是用 "擦掉" 的概念,
所以我的例子里加了 last_x , last_y ,就是为了 "擦掉" 。
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
以上,若有意见的话,欢迎补充。
作者: andrew771027 (老柏~)   2015-08-14 13:27:00
谢谢你的意见,晚点拜读,用手机看很崩溃

Links booklink

Contact Us: admin [ a t ] ucptt.com