通過 ncurses 在終端建立一個冒險遊戲
怎樣使用 curses 函式讀取鍵盤並操作螢幕。
我之前的文章介紹了 ncurses 庫,並提供了一個簡單的程式展示了一些將文字放到螢幕上的 curses 函式。在接下來的文章中,我將介紹如何使用其它的 curses 函式。
探險
當我逐漸長大,家裡有了一臺蘋果 II 電腦。我和我兄弟正是在這臺電腦上自學瞭如何用 AppleSoft BASIC 寫程式。我在寫了一些數學智力遊戲之後,繼續創造遊戲。作為 80 年代的人,我已經是龍與地下城桌遊的粉絲,在遊戲中角色扮演一個追求打敗怪物並在陌生土地上搶掠的戰士或者男巫,所以我建立一個基本的冒險遊戲也在情理之中。
AppleSoft BASIC 支援一種簡潔的特性:在標準解析度圖形模式(GR 模式)下,你可以檢測螢幕上特定點的顏色。這為建立一個冒險遊戲提供了捷徑。比起建立並更新週期性傳送到螢幕的記憶體地圖,我現在可以依賴 GR 模式為我維護地圖,我的程式還可以在玩家的角色(LCTT 譯註:此處 character 雙關一個代表玩家的角色,同時也是一個字元)在螢幕四處移動的時候查詢螢幕。通過這種方式,我讓電腦完成了大部分艱難的工作。因此,我的自頂向下的冒險遊戲使用了塊狀的 GR 模式圖形來展示我的遊戲地圖。
我的冒險遊戲使用了一張簡單的地圖,上面有一大片綠地伴著山脈從中間蔓延向下和一個在左上方的大湖。我要粗略地為桌遊戰役繪製這個地圖,其中包含一個允許玩家穿過到遠處的狹窄通道。
圖 1. 一個有湖和山的簡單桌遊地圖
你可以用 curses 繪製這個地圖,並用字元代表草地、山脈和水。接下來,我描述怎樣使用 curses 那樣做,以及如何在 Linux 終端建立和進行類似的一個冒險遊戲。
構建程式
在我的上一篇文章,我提到了大多數 curses 程式以相同的一組指令獲取終端型別和設定 curses 環境:
initscr();
cbreak();
noecho();
在這個程式,我新增了另外的語句:
keypad(stdscr, TRUE);
這裡的 TRUE
標誌允許 curses 從使用者終端讀取小鍵盤和功能鍵。如果你想要在你的程式中使用上下左右方向鍵,你需要使用這裡的 keypad(stdscr, TRUE)
。
這樣做了之後,你現在可以開始在終端螢幕上繪圖了。curses 函式包括了一系列在螢幕上繪製文字的方法。在我之前的文章中,我展示了 addch()
和 addstr()
函式以及在新增文字之前先移動到指定螢幕位置的對應函式 mvaddch()
和 mvaddstr()
。為了在終端上建立這個冒險遊戲的地圖,你可以使用另外一組函式:vline()
和 hline()
,以及它們對應的函式 mvvline()
和 mvhline()
。這些 mv 函式接受螢幕座標、一個要繪製的字元和要重複此字元的次數的引數。例如,mvhline(1, 2, '-', 20)
將會繪製一條開始於第一行第二列並由 20 個橫線組成的線段。
為了以程式設計方式繪製地圖到終端螢幕上,讓我們先定義這個 draw_map()
函式:
#define GRASS ' '
#define EMPTY '.'
#define WATER '~'
#define MOUNTAIN '^'
#define PLAYER '*'
void draw_map(void)
{
int y, x;
/* 繪製探索地圖 */
/* 背景 */
for (y = 0; y < LINES; y++) {
mvhline(y, 0, GRASS, COLS);
}
/* 山和山道 */
for (x = COLS / 2; x < COLS * 3 / 4; x++) {
mvvline(0, x, MOUNTAIN, LINES);
}
mvhline(LINES / 4, 0, GRASS, COLS);
/* 湖 */
for (y = 1; y < LINES / 2; y++) {
mvhline(y, 1, WATER, COLS / 3);
}
}
在繪製這副地圖時,記住填充大塊字元到螢幕所使用的 mvvline()
和 mvhline()
函式。我繪製從 0 列開始的字元水平線(mvhline
)以建立草地區域,直到佔滿整個螢幕的高度和寬度。我繪製從 0 行開始的多條垂直線(mvvline
)在此上新增了山脈,繪製單行水平線新增了一條山道(mvhline
)。並且,我通過繪製一系列短水平線(mvhline
)建立了湖。這種繪製重疊方塊的方式看起來似乎並沒有效率,但是記住在我們呼叫 refresh()
函式之前 curses 並不會真正更新螢幕。
繪製完地圖,建立遊戲就還剩下進入迴圈讓程式等待使用者按下上下左右方向鍵中的一個然後讓玩家圖示正確移動了。如果玩家想要移動的地方是空的,就應該允許玩家到那裡。
你可以把 curses 當做捷徑使用。比起在程式中例項化一個版本的地圖並複製到螢幕這麼複雜,你可以讓螢幕為你跟蹤所有東西。inch()
函式和相關聯的 mvinch()
函式允許你探測螢幕的內容。這讓你可以查詢 curses 以瞭解玩家想要移動到的位置是否被水填滿或者被山阻擋。這樣做你需要一個之後會用到的一個幫助函式:
int is_move_okay(int y, int x)
{
int testch;
/* 如果要進入的位置可以進入,返回 true */
testch = mvinch(y, x);
return ((testch == GRASS) || (testch == EMPTY));
}
如你所見,這個函式探測行 x
、列 y
並在空間未被佔據的時候返回 true
,否則返回 false
。
這樣我們寫移動迴圈就很容易了:從鍵盤獲取一個鍵值然後根據是上下左右鍵移動使用者字元。這裡是一個這種迴圈的簡單版本:
do {
ch = getch();
/* 測試輸入的值並獲取方向 */
switch (ch) {
case KEY_UP:
if ((y > 0) && is_move_okay(y - 1, x)) {
y = y - 1;
}
break;
case KEY_DOWN:
if ((y < LINES - 1) && is_move_okay(y + 1, x)) {
y = y + 1;
}
break;
case KEY_LEFT:
if ((x > 0) && is_move_okay(y, x - 1)) {
x = x - 1;
}
break;
case KEY_RIGHT
if ((x < COLS - 1) && is_move_okay(y, x + 1)) {
x = x + 1;
}
break;
}
}
while (1);
為了在遊戲中使用這個迴圈,你需要在迴圈裡新增一些程式碼來啟用其它的鍵(例如傳統的移動鍵 WASD),以提供讓使用者退出遊戲和在螢幕上四處移動的方法。這裡是完整的程式:
/* quest.c */
#include
#include
#define GRASS ' '
#define EMPTY '.'
#define WATER '~'
#define MOUNTAIN '^'
#define PLAYER '*'
int is_move_okay(int y, int x);
void draw_map(void);
int main(void)
{
int y, x;
int ch;
/* 初始化curses */
initscr();
keypad(stdscr, TRUE);
cbreak();
noecho();
clear();
/* 初始化探索地圖 */
draw_map();
/* 在左下角初始化玩家 */
y = LINES - 1;
x = 0;
do {
/* 預設獲得一個閃爍的游標--表示玩家字元 */
mvaddch(y, x, PLAYER);
move(y, x);
refresh();
ch = getch();
/* 測試輸入的鍵並獲取方向 */
switch (ch) {
case KEY_UP:
case 'w':
case 'W':
if ((y > 0) && is_move_okay(y - 1, x)) {
mvaddch(y, x, EMPTY);
y = y - 1;
}
break;
case KEY_DOWN:
case 's':
case 'S':
if ((y < LINES - 1) && is_move_okay(y + 1, x)) {
mvaddch(y, x, EMPTY);
y = y + 1;
}
break;
case KEY_LEFT:
case 'a':
case 'A':
if ((x > 0) && is_move_okay(y, x - 1)) {
mvaddch(y, x, EMPTY);
x = x - 1;
}
break;
case KEY_RIGHT:
case 'd':
case 'D':
if ((x < COLS - 1) && is_move_okay(y, x + 1)) {
mvaddch(y, x, EMPTY);
x = x + 1;
}
break;
}
}
while ((ch != 'q') && (ch != 'Q'));
endwin();
exit(0);
}
int is_move_okay(int y, int x)
{
int testch;
/* 當空間可以進入時返回true */
testch = mvinch(y, x);
return ((testch == GRASS) || (testch == EMPTY));
}
void draw_map(void)
{
int y, x;
/* 繪製探索地圖 */
/* 背景 */
for (y = 0; y < LINES; y++) {
mvhline(y, 0, GRASS, COLS);
}
/* 山脈和山道 */
for (x = COLS / 2; x < COLS * 3 / 4; x++) {
mvvline(0, x, MOUNTAIN, LINES);
}
mvhline(LINES / 4, 0, GRASS, COLS);
/* 湖 */
for (y = 1; y < LINES / 2; y++) {
mvhline(y, 1, WATER, COLS / 3);
}
}
在完整的程式清單中,你可以看見使用 curses 函式建立遊戲的完整佈置:
- 初始化 curses 環境。
- 繪製地圖。
- 初始化玩家座標(左下角)
- 迴圈:
- 繪製玩家的角色。
- 從鍵盤獲取鍵值。
- 對應地上下左右調整玩家座標。
- 重複。
- 完成時關閉curses環境並退出。
開始玩
當你執行遊戲時,玩家的字元在左下角初始化。當玩家在遊戲區域四處移動的時候,程式建立了“一串”點。這樣可以展示玩家經過了的點,讓玩家避免經過不必要的路徑。
圖 2. 初始化在左下角的玩家
圖 3. 玩家可以在遊戲區域四處移動,例如湖周圍和山的通道
為了建立上面這樣的完整冒險遊戲,你可能需要在他/她的角色在遊戲區域四處移動的時候隨機建立不同的怪物。你也可以建立玩家可以發現在打敗敵人後可以掠奪的特殊道具,這些道具應能提高玩家的能力。
但是作為起點,這是一個展示如何使用 curses 函式讀取鍵盤和操縱螢幕的好程式。
下一步
這是一個如何使用 curses 函式更新和讀取螢幕和鍵盤的簡單例子。按照你的程式需要做什麼,curses 可以做得更多。在下一篇文章中,我計劃展示如何更新這個簡單程式以使用顏色。同時,如果你想要學習更多 curses,我鼓勵你去讀位於 Linux 文件計劃的 Pradeep Padala 寫的如何使用 NCURSES 程式設計。
via: http://www.linuxjournal.com/content/creating-adventure-game-terminal-ncurses
相關文章
- 冒險遊戲已逝?冒險遊戲萬歲!遊戲
- 為冒險解密遊戲設計一個好謎題解密遊戲設計
- 在《JOJO的奇妙冒險》裡,我們能看到哪些冒險遊戲的設計要素?遊戲
- 不要錯過第一款基於機器學習的冒險遊戲機器學習遊戲
- 有玩家用20萬頁的PDF做了一個冒險遊戲遊戲
- 紙藝歷險Papetura Mac - 點選冒險遊戲Mac遊戲
- 深度解析冒險遊戲必不可少的幾大元素,它們讓“冒險”更有遊戲性遊戲
- 2-幀動畫-從零開始寫一個武俠冒險遊戲動畫遊戲
- 《太空羅賓遜》:標準過頭的 Roguelike 射擊冒險遊戲遊戲
- 《健身環大冒險》:健身遊戲化,一個相當不錯的答案遊戲
- 5-使用協程-從零開始寫一個武俠冒險遊戲遊戲
- 3-地圖生成-從零開始寫一個武俠冒險遊戲地圖遊戲
- 1-狀態原型-從零開始寫一個武俠冒險遊戲原型遊戲
- 位元組跳動的遊戲大冒險遊戲
- 動作冒險遊戲俠盜獵車手遊戲
- 在遊戲裡看番是一種怎樣的體驗?演出式燃魂冒險卡牌手遊《終焉誓約》終極測試開啟!遊戲
- 賽博朋克喵《Stray》:如何控制一隻貓靈活地在遊戲世界中冒險遊戲
- 冒險解謎遊戲都玩過,那操控場景本身的你試過嗎?遊戲
- 4-第一次整合-從零開始寫一個武俠冒險遊戲遊戲
- 冒險島143服務端/米米143服務端
- 網易推出全新工作室Worlds Untold,動作冒險遊戲在研遊戲
- 6-用GPU提升效能(3)-從零開始寫一個武俠冒險遊戲GPU遊戲
- 6-用GPU提升效能(1)-從零開始寫一個武俠冒險遊戲GPU遊戲
- 6-用GPU提升效能(2)-從零開始寫一個武俠冒險遊戲GPU遊戲
- 遇見最初的冒險! 《冒險島:楓之傳說》騰訊遊戲釋出會宣佈定檔遊戲
- AVG冒險遊戲消亡史(一):源於跑團桌遊 亦是恐怖遊戲鼻祖遊戲
- Mac海洋冒險遊戲:潛水員戴夫Dave The Diver 遊戲下載Mac遊戲
- 《冒險之門》9月10日App Store首發,一起趣萌動冒險吧APP
- 在終端畫畫、炒股、玩遊戲遊戲
- 文字冒險遊戲AI Dungeon 故事由AI寫就遊戲AI
- 《雨中冒險》: 教科書式好玩的Roguelike遊戲遊戲
- H5 遊戲開發:指尖大冒險H5遊戲開發
- 庫洛遊戲《鳴潮》:一場廢土開放世界的獨特冒險遊戲
- 通過8個技巧讓你成為一個超強的Linux終端使用者Linux
- 通過終端除錯 AngularJS 應用除錯AngularJS
- 《FANTASIAN》Fami 通評測:在熟悉的「阪口風格」下體驗新的冒險
- 0-開發框架Codea簡介-從零開始寫一個武俠冒險遊戲框架遊戲
- 大航海時代4威力加強版 for Mac(冒險遊戲)Mac遊戲