Tôi đang làm một trò chơi RTS, và giống như hầu hết các RTS khác, bạn có thể thấy những gì đang diễn ra trong một phần của bản đồ chỉ khi bạn có một đơn vị ở đó.
Tôi có vài ý tưởng làm thế nào để thực hiện điều này, nhưng có vấn đề với chúng.
Vấn đề là:
- Thuật toán phải hiệu quả.
- Tôi cần thông báo cho người chơi (qua mạng), khi kẻ thù xuất hiện.
- Làm thế nào để tôi giải thích cho các chướng ngại vật cản trở tầm nhìn (như vách đá).
Cách tiếp cận ngây thơ sẽ như thế này:
// pseudocode
func calculate_visibility:
vector<Bitfield> visible;
for all units on map:
let unit = enumerated unit
for all human players:
let player = enumerated player
for all units of player:
let player_unit = enumerated unit
if player_unit sees unit
visible[unit.id][player.id] = true
process next player
Và sau đó chạy phép tính này từng khung, so sánh kết quả với khung trước đó và gửi các sự kiện, như đơn vị kẻ thù đã phát hiện ra.
Tôi đã thực hiện một số điểm chuẩn và sử dụng cách tiếp cận như thế này có thể mất tới 2/3 khung hình, điều này không thể chấp nhận được.
Tôi đã tìm ra một cách tốt hơn để tính toán đơn vị nào có thể nhìn thấy. Cách tiếp cận này là sử dụng bản đồ tầm nhìn.
- Chia nhỏ bản đồ thành các ô N × M.
- Mỗi ô được đánh dấu bằng ID của người chơi có thể nhìn thấy ô.
- Để xác định người chơi nào có thể thấy một đơn vị, tôi chỉ cần kiểm tra các ô có chứa đơn vị đã cho.
Tuy nhiên, tôi không biết làm thế nào để điền vào bản đồ ở nơi đầu tiên. Tôi có thể lặp qua tất cả các đơn vị và sử dụng thuật toán vẽ vòng tròn.
Nhưng tôi sẽ phải vẽ lại bản đồ hiển thị mọi khung hình, vì vậy điều này trông không hiệu quả hơn nhiều so với cách tiếp cận đầu tiên. Trừ khi tôi cập nhật nó ở tốc độ thấp hơn, nhưng sau đó có vấn đề với các đơn vị chuyển động nhanh.
Và làm cách nào để phát hiện khi đơn vị xuất hiện trong tầm nhìn của người chơi, ngoại trừ việc lặp qua mọi đơn vị và so sánh với khung trước đó?
Làm thế nào điều này được thực hiện trong RTS hiện đại, chẳng hạn như StarCraft 2?