Search…

Đồ Hoạ trên Cửa Sổ Dòng Lệnh - Console Graphics

Vũ Quang HuyVũ Quang Huy
11/09/20206 min read
Các thư viện đồ họa đã phát triển rất mạnh mẽ, tận dụng gần như tối đa sức mạnh của phần cứng đồ họa nên đồ họa trên cửa sổ dòng lệnh dần bị rơi vào quên lãng. Nhưng không vì thế mà vai trò lịch sử của của nó bị lãng quên.

Giới thiệu

Ở thập niên 80, thời điểm máy tính cá nhân vừa xuất hiện, giao diện đồ họa chỉ có trên một số ít máy Macintosh của Apple, giao diện cửa sổ dòng lệnh là phương tiện giao tiếp chính giữa người sử dụng và máy tính. Trong thời điểm này, máy tính cá nhân có giá thành đắt đỏ và gần như chỉ thuần phục vụ cho công việc: nhập liệu văn bản, thống kê với bảng tính, ... cũng như lập trình.

IBM PC (Model 5150) chạy hệ điều hành MS-DOS và Macintosh của Apple là hai dòng máy tính tiêu biểu trong giai đoạn này.

1980s_IBM_PC
IBM PC Model 5051 (Wikipedia)
1980s_Macintosh
Macintosh 1984 (Wikipedia)

Dẫu vậy, với máy tính cá nhân người dùng vẫn đòi hỏi hơn chỉ là một thiết bị phục vụ công việc. Do đó, các trò chơi lần lượt ra đời phục vụ cho nhu cầu giải trí. Với giới hạn phần cứng hạn hẹp trong giai đoạn này, các trò chơi ra đời hầu hết thuộc nhóm text-based - một dạng như tiểu thuyết cho phép người chơi tương tác trực tiếp vào trong câu chuyện thông qua các lựa chọn xử lý tình huống xuyên suốt câu chuyện, và phần kết của câu chuyện sẽ phụ thuộc vào những quyết định của người chơi trong suốt quá trình chơi.

wizzard_castle_90s
The Wizzard's Castle (Wikipedia)

Sáng tạo hơn, một số nhà phát triển đã dựa trên những kí tự ASCII có sẵn, kết hợp với việc điều chỉnh tọa độ khi in kí tự đó ra trên màn hình, và từ đó những game kinh điển dần dần được ra đời cho PC mà ta gọi với tên quen thuộc như rắn săn mồi, xếp gạch, đỡ bóng, ...

1980s_rogue
Rogue - 1980s (Wikipedia)

Đứng trên phương diện là một lập trình viên, để biến màn hình giao điện xử lý kí tự trở nên linh động và sặc sỡ thì các kỹ thuật sau cần phải được thực hiện (có thể tự xử lý được hệ điều hành hỗ trợ).

  • Di chuyển thiết bị vẽ tới một vị trí bất kì trên màn hình
  • Chọn màu vẽ
  • Vẽ đối tượng đồ họa

Lặp đi lặp lại quá trình này, màn hình sẽ được lấp đầy theo như quy tắc vẽ quy định từ trước. Với mỗi hệ điều hành, các thao tác để có thể thực hiện những kĩ thuật được đề cập bên trên có thể khác nhau.

Tiền đề bài viết

Tôi có được may mắn tiếp cận với máy tính từ rất sớm, và trong suốt thời gian đó tôi đã lần lượt đi qua từ hệ điều hành MS-DOS cổ điển, hệ điều hành Windows đầu tiên - Windows 1.0, rồi đến Windows 3.1, Windows 95, Windows 98, ... cho đến Windows 10.

Tuy nhiên, ấn tượng với tôi vẫn là những trò chơi đầy màu sắc trên chiếc PC chạy MS-DOS khoảng những năm 1990s. Mãi cho đến sau này khi tôi bước chân vào ngành lập trình tôi mới tìm được câu trả lời cho mình.

Bài viết này hướng dẫn tương tác với các hàm của hệ thống và vẽ lên màn hình như ý muốn.

Tương tác với cửa sổ dòng lệnh

Kể từ Windows 2000, môi trường MS-DOS đã bị loại bỏ hoàn toàn khỏi Windows. Do đó, cửa sổ dòng lệnh ở các phiên bản Windows trở về sau cũng là một ứng dụng trực thuộc quyền quản lý của hệ điều hành Windows - cũng như các thành phần khác, được Windows cấp cho một định danh duy nhất trong suốt quá trình ứng dụng hoạt động. Định danh này được lấy ra bằng cách sử dụng hàm:

HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);

Thay đổi vị trí thiết bị vẽ

Theo mặc định, khi sử dụng hàm printf hay cout, giá trị trong tham số hàm sẽ được vẽ ra trên màn hình theo thứ tự nối tiếp nhau. Ngoài ra, ta có thể vẽ tại một vị trí bất kì trên cửa sổ dòng lệnh bằng cách đặt lại tọa độ bắt đầu vẽ như sau:

COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(consoleHandle, coord);

Trong đó, xy là tọa độ muốn di chuyển tới và consoleHwnd là định danh của cửa sổ đang thao tác.

Chọn màu vẽ

Mục đích ban đầu cửa sổ dòng lệnh được tạo để phục vụ cho công việc nên số lượng màu được hỗ trợ trên cửa sổ dòng lệnh rất hạn chế - chỉ bao gồm 16 màu mang giá trị trong khoảng [0 - 15] theo bảng sau:

color_table

Để thiết lập màu vẽ cho, sử dụng hàm SetConsoleTextAttribute, hàm này có cấu trúc sau

BOOL WINAPI SetConsoleTextAttribute(
  _In_ HANDLE hConsoleOutput,
  _In_ WORD   wAttributes
);

Hàm này sử dụng một biến WORD để quy định các thông tin về màu chữ, màu nền của kí tự và các thông số khác liên quan tới việc vẽ ký tự ra cửa sổ dòng lệnh. Trong biến kiểu WORD này quy định:

  • 4 bit đầu - thông tin màu ký tự
  • 4 bit sau - thông tin màu nền ký tự
  • 8 bit còn lại - thông tin khác

Ví dụ muốn vẽ ký tự màu đỏ trên nền trắng, tham số truyền vào sẽ là:

SetConsoleTextAttribute(consoleHandle, (15 << 4) | 12);

Và sử dụng hàm printf để in dòng chữ STDIO Hello Console!

stdio_hello_console

Vẽ đối tượng đồ họa

Do đang tương tác trực tiếp trên cửa sổ dòng lệnh, các đối tượng đồ họa chỉ là một cách sắp xếp khéo léo các ký tự thuộc bảng mã ASCII. Ví dụ như trong game Pong, cần vẽ một ô vuông bao quanh màn chơi và một vạch kẻ để phân định hai người chơi với nhau - sử dụng ký tự █ (mã 219) và ░ (mã 176).

Mặc định trên Windows cũng hỗ trợ xuất các ký tự này bằng cách nhấn giữ phím ALT và nhập mã kí tự cần. Ví dụ như ╜(mã 189).

printf("%c", 219);		// print character █
printf("%c", 176);		// print character ░

Với một chút khéo léo sẽ tạo được hình như bên dưới

pong_board
Pong

Hướng ứng dụng

Ở thời điểm hiện tại, các thư viện đồ họa đã phát triển rất mạnh mẽ, tận dụng gần như tối đa sức mạnh của phần cứng đồ họa (bộ xử lý đồ họa tích hợp / rời) nên gần như đồ họa trên cửa sổ dòng lệnh bị rơi vào quên lãng. Tuy nhiên với người mới tiếp xúc về khía cạnh lập trình đồ họa và lập trình game, đây là nơi bắt đầu khá tốt vì sẽ không phải lệ thuộc vào bất kì thư viện hay công nghệ nào, chỉ đơn giản nắm ở kĩ thuật và sáng tạo.

Cuối cùng, với một chút khéo léo hơn, có thể dễ dàng biến cửa sổ dòng lệnh chỉ có màn hình đen, chữ trắng đơn điệu thành một tác phẩm nghệ thuật.

stdio_tree
IO Stream

IO Stream Co., Ltd

developer@iostream.co
383/1 Quang Trung, ward 10, Go Vap district, Ho Chi Minh city
Business license number: 0311563559 issued by the Department of Planning and Investment of Ho Chi Minh City on February 23, 2012

©IO Stream, 2013 - 2024