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