嗨大家好,這裡是鐵匠史密斯!
昨天我們建立了一塊畫布(wchar_t* screen
),今天我要正式把這塊畫布「貼」到 Console 畫面上!
說真的,我對 windows.h
和 Win32 API 其實還不太熟 😂
不過在研究 javidx9 的程式碼時,我慢慢搞懂了幾個重要函式的作用,像是:
CreateConsoleScreenBuffer
)
SetConsoleActiveScreenBuffer
)
WriteConsoleOutputCharacter
)
下面我就用我的版本示範一次!
CreateConsoleScreenBuffer
)目前已經有80 * 30 = 2400 elements 的 1-D wchar_t*
矩陣 screen
(畫布)
那我們要把這個畫布變成 Console 主控台的自定義畫面緩衝區
// Create console handler
HANDLE hConsole { CreateConsoleScreenBuffer(
GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL) };
該行意思就是: 請Windows幫我們建立一個自定義畫面緩衝區
第一個參數很重要,我們需要把畫布寫到畫面緩衝區,所以一定要 GENERIC_WRITE !! GENERIC_READ 可加可不加,但這算是慣用寫法: GENERIC_READ | GENERIC_WRITE = 兩個權限都給!
其餘參數均是默認參數,詳情可以詳見 Reference 的 微軟主控台緩衝區資訊
SetConsoleActiveScreenBuffer
)既然我們有屬於自己的自定義緩衝區 hConsole
了,接下來,就是:
將自定義畫面緩衝區設定為 「作用中的畫面緩衝區」
SetConsoleActiveScreenBuffer(hConsole);
簡單來說,原本Windows默認的Console 「作用中的畫面緩衝區」 長得像這樣:
既然我們已經有了自定義的畫面緩衝區 hConsole
了,會什麼不讓它變成 「作用中的畫面緩衝區」= 顯示在畫面的緩衝區 呢? 這樣我們 Console 顯示的結果就會替換成我們的畫布了,就像這樣:
WriteConsoleOutputCharacter
)接下來,就是要把畫布 screen
寫在已成為「作用中」的畫面緩衝區 hConsole
上
→ 程式執行時可以將畫布順利地顯示在主控台畫面上!!
while (true) {
// Write cavas into console to show screen
WriteConsoleOutputCharacter(hConsole, screen, nScreenWidth * nScreenHeight, { 0,0 }, &dwBytesWritten);
}
Windows( Windows.h
)提供的函式 WriteConsoleOutputCharacter
所表達的意思是:
將我的1-D矩陣(畫布)
screen
寫入到我的自訂義作用畫面緩衝區hConsole
內, 共有nScreenWidth x nScreenHeight
個字元,從緩衝區(畫面)的第一個位置{ 0, 0 }
開始寫入字元, 並用dwBytesWritten
來紀錄共寫入了幾個字元
關於參數的詳細資訊,可以參照 微軟的WriteConsoleOutputCharacter
如此,就可以在while迴圈內一直顯示我們的畫面了(前1000個字元是 ' '
,後面1400個字元是 '%'
),結果如下:
對了,之所以會設定寬 nScreenWidth
、高 nScreenHeight
,就是為了讓我們可以調整Console主控台的大小,現在我們的主控台大小是80(寬) * 30(高):
const int nScreenWidth { 80 };
const int nScreenHeight { 30 };
所以呢,主控台大小需要調整,可以從主控台按右鍵 -> 啟動大小進行調整,如圖:
CreateConsoleScreenBuffer
)
SetConsoleActiveScreenBuffer
)
WriteConsoleOutputCharacter
)
目前進度的程式碼 main.cpp 如下:
#include <iostream>
#include <Windows.h>
int main()
{
const int nScreenWidth { 80 };
const int nScreenHeight { 30 };
// Create canva
wchar_t* screen = new wchar_t[nScreenWidth * nScreenHeight];
for (int i = 0; i < nScreenWidth * nScreenHeight; i++)
{
if (i < 1200)
screen[i] = L' ';
else
screen[i] = L'%';
}
screen[nScreenWidth * nScreenHeight - 1] = '\0'; // null terminator
// Create console handler (custom screen buffer)
HANDLE hConsole { CreateConsoleScreenBuffer(
GENERIC_READ | GENERIC_WRITE, 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL) };
// Set Active Screen Buffer so that console will show this buffer first
SetConsoleActiveScreenBuffer(hConsole);
DWORD dwBytesWritten { 0 };
while (true) {
// Write cavas into console to show screen
WriteConsoleOutputCharacter(hConsole, screen, nScreenWidth * nScreenHeight, { 0,0 }, &dwBytesWritten);
}
return 0;
}
好啦,畫布我們貼上去了,畫面也成功印到 Console 上了!
那接下來要畫什麼呢?
沒錯 —— 我們要開始畫地圖啦!
下一篇我會開始介紹 wstring map
,也就是這款遊戲裡的迷宮地圖是怎麼用字串做出來的?
讓我們繼續走下去~