Khám Phá ANSI Escape Code Và Cách Đóng Gói Trong Lua
Gần đây, tôi nảy ra một ý tưởng thú vị và quyết định xây dựng một bản prototype đơn giản. Vì dự án liên quan đến tương tác người-máy, tôi cần vẽ một số yếu tố đồ họa cơ bản trên màn hình. Dù hiện nay có rất nhiều công cụ hỗ trợ, nhưng tôi muốn thử nghiệm một cách tiếp cận hoài cổ hơn: sử dụng các ký tự ASCII trong môi trường console.
Hành trình tìm về quá khứ
Trong vài năm trở lại đây, tôi đắm chìm vào các trò chơi kiểu RogueLike. Điều này khiến tôi nhớ lại những ngày tháng tuổi thơ với chiếc máy tính Apple ][. Tôi muốn tái hiện cảm giác ấy bằng cách tạo ra các hình ảnh ASCII trong console, không dùng bất kỳ thư viện đồ họa phức tạp nào như ncurses. Mục tiêu là thiết lập môi trường phát triển chỉ trong vài phút.
Giải pháp ANSI Escape Code
Lựa chọn tối ưu chính là sử dụng ANSI Escape Code thông qua luồng xuất chuẩn. Đặc biệt, các chuỗi CSI (Control Sequence Introducer) cho phép kiểm soát vị trí con trỏ, vượt qua giới hạn xuất văn bản theo dòng truyền thống.
Các lệnh CSI phổ biến bao gồm:
\x1b[n;mH
: Di chuyển con trỏ đến tọa độ cụ thể\x1b[nJ
: Xóa màn hình\x1b[n(A/B/C/D)
: Di chuyển con trỏ theo hướng\x1b[s
/\x1b[u
: Lưu/trả lại vị trí con trỏ
Đóng gói trong Lua
Tôi đã tạo một module Lua đơn giản với hai API chính:
|
|
Ví dụ sử dụng:
|
|
Tạo hiệu ứng động
Để tạo hoạt ảnh, tôi sử dụng coroutine với framework đơn giản:
|
|
Xử lý đầu vào bàn phím
Vấn đề lớn nằm ở stdin:
- Chế độ canonical của terminal yêu cầu nhấn Enter mới nhận dữ liệu
- Không có API chuẩn để thiết lập chế độ không chặn
Giải pháp: Viết chương trình C chuyển terminal sang chế độ non-canonical, đồng thời tạo thread định kỳ gửi tín hiệu. Trên Windows cần xử lý riêng biệt do không hỗ trợ POSIX.
Cải tiến hàm run:
|
|
Kết luận
Với bộ công cụ nhỏ gọn này, bạn có thể thỏa sức sáng tạo các trò chơi kiểu RogueLike trên mọi nền tảng chỉ với Lua. Điều tuyệt vời nhất? Bạn không cần bất kỳ thư viện đồ họa phức tạp nào - chỉ cần nắm vững sức mạnh của ANSI Escape Code và sự linh hoạt của Lua!