Thuật toán đường dẫn động cho trò chơi phòng thủ tháp


16

Tôi đang thực hiện một Tower Defense và tôi cần một thuật toán đường dẫn tốt cho nó.

Tôi đã nghĩ về Dijkstra nhưng tôi cần một thứ có thể năng động; nó phải có khả năng tự cập nhật khi một cạnh bị loại bỏ hoặc thêm vào mà không cần tính toán lại đầy đủ.

Tôi đang mã hóa bằng C # nếu nó giúp.

Câu trả lời:


8

Nhìn chung bạn sẽ muốn sử dụng A *, trừ khi có thứ gì đó quan trọng khác mà bạn đang tìm kiếm.


Nếu tôi không quen thuộc với A *, tôi sẽ giải quyết các môi trường thay đổi linh hoạt như thế nào? Tính lại ở mọi khung? Tại va chạm?
Justin L.

1
Nói chung, bạn sẽ đường dẫn lại từng khung hình trong một trò chơi đơn giản như thế này. Lưới bản đồ có thể sẽ rất nhỏ và số lượng đại lý nhiều nhất là hàng trăm. Nếu nó trở thành một vấn đề hiệu năng lớn bằng cách nào đó bạn có thể tối ưu hóa nó sau này bằng cách không xây dựng lại cây trừ khi cần thiết.
coderanger

6
Nếu nó chậm chạp, khuyến nghị của tôi: đừng tính đường dẫn cho mọi mob. Có khả năng, tất cả họ đều đi chung một con đường. Tôi chỉ tính lại vị trí tháp mới, và tòa tháp đang ở trong đường dẫn hiện tại . Ngay cả sau đó, Chỉ thực hiện lại một lần nữa cho quái vật tại các điểm trên con đường trước quảng trường khối, không phải cho các mob đã qua nó và do đó không quan tâm. Và sau đó, để làm cho đường dẫn ngắn hơn, bạn có thể giới hạn nó để tìm đường đến hình vuông sau hình vuông bị chặn, vì bạn đã biết đường dẫn từ đó.
seanmonstar

4
Trên thực tế, "mob" là biệt ngữ công nghiệp (và người chơi MMO / MUD) cho "đối tượng di động".

3
Bất kể, nó đã có từ lâu, có niên đại từ MUD1, và đủ tiêu chuẩn để xuất hiện trong nhiều ấn phẩm. vi.wikipedia.org/wiki/Mob_%28computer_gaming%29

19

Tôi cần phải giải quyết một vấn đề tương tự: tìm đường trên một lưới giống như mê cung lớn với "chi phí" và rào cản thay đổi liên tục.

Vấn đề là, trong trò chơi phòng thủ tháp, số lượng thực thể cần giải quyết đường dẫn cho chúng thường lớn hơn nhiều so với số nút trong biểu đồ. A * không phải là thuật toán thích hợp nhất để xử lý việc này, bởi vì bạn sẽ cần giải quyết nó một lần nữa mỗi khi có gì đó thay đổi. Vâng, nó phù hợp nếu bạn chỉ cần tìm một đường dẫn, nhưng trong trường hợp của tôi, tôi cần có khả năng xử lý các thực thể có thể xuất hiện ở các vị trí khác nhau và mỗi đường dẫn có một đường dẫn riêng.

Các Floyd-Warshall thuật toán là xa thích hợp hơn, mặc dù đối với trường hợp của tôi, tôi đã viết một thuật toán tùy chỉnh mà bất cứ khi nào một thay đổi nút, nó lại tính toán chi phí để mà nút từ tất cả các nước láng giềng, và sau đó nếu những người hàng xóm đã được thay đổi nó được gọi đệ quy về chúng.

Vì vậy, vào đầu trò chơi, tôi chỉ kích hoạt thuật toán này trên tất cả các nút "mục tiêu" của mình. Sau đó, bất cứ khi nào một nút duy nhất thay đổi (ví dụ, trở nên không thể vượt qua), tôi chỉ cần kích hoạt nó trên nút đó và thay đổi được truyền đến tất cả các nút sẽ bị ảnh hưởng và sau đó dừng lại. Vì vậy, không cần tính toán lại toàn cầu và thuật toán hoàn toàn độc lập với số lượng thực thể sẽ yêu cầu tìm đường.

Thuật toán của tôi về cơ bản là một cái gì đó giống như (mã giả):

update_node method in Node class:
    $old <- $my_score
    find $neighbor node among all neighbors such that
        $neighbor.score + distance_to($neighbor) is minimal
    $my_score <- $neighbor.score + distance_to($neighbor)
    $next_node <- $neighbor
    if ($my_score != $old)
        for each $neighbor
            $neighbor.update_node()

Với số điểm ban đầu tùy thuộc vào việc nút là mục tiêu hay một loại rào cản nào đó.


1
Cũng có thể dễ dàng tự động trải rộng điều này trên các khung khi tải CPU thay đổi.
tenpn

+1 cho A * không phải là thuật toán phù hợp để sử dụng.
Ricket

5

Thuật toán định tuyến tôi đã sử dụng trên TD của mình ngược với đường dẫn A * thông thường do số lượng thực thể tôi có trong trò chơi. Thay vì định tuyến từ mục tiêu đến kẻ xấu, tôi chuyển từ mục tiêu đến mọi ô vuông trống trên bảng.

Điều này không mất nhiều thời gian, bạn chỉ cần lặp lại bảng cho đến khi bạn tìm thấy "chi phí" của mình và nó cung cấp phản hồi tốt cho các tuyến đường bị chặn (nếu bạn đang làm những việc đó). Sử dụng thuật toán của Floyd rất nhanh và thân thiện với bộ đệm so với A * vì nó không thực hiện tra cứu phụ thuộc dữ liệu, nó chỉ tải và hoạt động trên dữ liệu theo luồng.

Bắt đầu với bảng của bạn được đặt thành chi phí vô hạn, sau đó đặt bình phương mục tiêu thành chi phí bằng 0, sau đó lặp lại kiểm tra bảng để xem liệu một ô lân cận có chi phí thấp hơn chi phí hiện tại cộng với chi phí đi lại hay không. Chi phí đi lại là nơi bạn đặt heuristic (trong trường hợp của tôi, chi phí đi theo đường chéo là vô hạn, nhưng chi phí di chuyển qua một tòa tháp cao, vì vậy họ được phép ăn qua tháp, nhưng không được trừ khi họ không có sự lựa chọn)

Khi bạn đã có được lưới chi phí của mình, bạn có thể nhanh chóng xây dựng lưới "dòng chảy" từ đó bằng cách kiểm tra độ dốc chi phí cao nhất trên các ô. Điều này hoạt động thực sự tốt cho số lượng lớn kẻ xấu bởi vì không ai trong số họ từng phải tìm đường, họ chỉ đi theo các biển chỉ dẫn ảo.

Một lợi ích khác là theo cách này, bạn chỉ phải chạy nhiệm vụ này mỗi khi bạn điều chỉnh vật cản (hoặc trong trò chơi của tôi, khi một con creep ăn qua một trong những tòa tháp của bạn). Không phải mỗi khi một creep / mob xâm nhập vào lĩnh vực này (mà với hàng ngàn mob và hàng chục mỗi giây sẽ khá đau đầu).


4

Tìm đường nhanh, và trên một cái gì đó có kích thước của một trò chơi phòng thủ tháp bình thường, bạn sẽ không gặp khó khăn gì khi chạy vượt qua A * hoặc Dijkstra đầy đủ mỗi khi có gì đó thay đổi. Chúng tôi đang nói chuyện tốt dưới một phần nghìn giây để làm mới hoàn toàn. Bất kỳ loại tìm đường thích ứng nào kết thúc phức tạp khủng khiếp. Chỉ cần làm theo cách đơn giản, trừ khi bạn đang tạo lưới phòng thủ tháp lớn nhất thế giới.


1
Điều đáng chú ý là Tower Defense rất phổ biến trên điện thoại di động, nơi việc tìm đường không nhanh. Đặc biệt là trên các thiết bị cũ hơn một chút, như các thiết bị Sidekick hoặc Android 1.6.
seanmonstar

1
Các nhà phát triển đã sử dụng các thuật toán tìm đường như A * và Dijkstra trên phần cứng kém mạnh mẽ hơn nhiều trong nhiều thập kỷ (nghĩ là Game Boy). Bất kỳ điện thoại nào đủ mới để có màn hình phù hợp để chơi game đều không có vấn đề gì, tất nhiên với điều kiện là việc triển khai có hiệu quả hợp lý. Có một số tối ưu hóa tiện lợi được thảo luận ở đây: harablog.files.wordpress.com/2009/06/beyondastar.pdf
Mike Strobel

+1. Tôi đã đi đến kết luận tương tự khi tôi đang phát triển bản sao DTD của riêng mình. Tôi đã cố gắng cập nhật các đường dẫn tăng dần nhưng thuật toán trở nên quá phức tạp. Sau khi dành một ngày cho nó, tôi chuyển sang một recalc đầy đủ cho mỗi thay đổi. Điều đó đã làm việc, và với một vài điều chỉnh tôi đã có thể làm cho nó đủ nhanh.
Finnw


2

Điều này có thể là quá mức cho giải pháp của bạn, nhưng hãy nghĩ đến việc định tuyến ngược thay vì chuyển tiếp.

Trong một trò chơi TD, kẻ thù thường cố gắng đạt được một mục tiêu cụ thể. Định tuyến ngược từ mục tiêu đó đến kẻ thù đầu tiên, sau đó lưu lại đường dẫn đó. Trên đường dẫn tạo cho kẻ thù tiếp theo, sử dụng đường dẫn đầu tiên làm điểm bắt đầu, v.v. Nếu bạn có nhiều điểm truy cập của kẻ thù hoặc nhiều mục tiêu, hãy bắt đầu một loạt các đường dẫn được lưu trong bộ nhớ cache.


1

Tìm đường dẫn điểm có thể là tốt nhất cho trò chơi td, bởi vì nói chung dựa trên cấp độ, ai đi theo một đường dẫn trực tiếp. Về cơ bản, bạn đặt các nút hoặc điểm tham chiếu của mình sau đó có điểm "ai" về phía đường đi và đi đến điểm đó, một khi nó đủ gần để nó đi đến điểm tiếp theo, hãy đối mặt với nó và tiến về phía nó.


Điều này chỉ hoạt động đối với những trò chơi TD mà bạn chỉ có thể đặt tháp pháo ở bên cạnh đường dẫn - không phải trò chơi cho phép đặt tháp ở bất cứ đâu trên bảng.
Iain

vâng, ban đầu tác giả không chỉ định loại anh ta muốn nên tôi cho là không năng động.
Loktar

1

Vì ai đó đã hỏi, bạn giải quyết các môi trường thay đổi linh hoạt bằng cách tính lại đường dẫn mỗi khi người chơi đặt hoặc xóa tháp và bạn chỉ lưu trữ đường dẫn đó trong bộ nhớ trong thời gian trung bình. Môi trường không thay đổi trên mọi khung hình.

Lưu ý rằng một số trò chơi TD có đường dẫn được thiết lập và không cho phép bạn đặt tháp trên đó, vì vậy chúng giải quyết việc tìm đường một cách dễ dàng: bằng cách mã hóa một đường dẫn và không cho phép bạn chặn nó :)


1

Một giải pháp đơn giản là gian lận.

Thiết kế bản đồ trước để đảm bảo rằng không có ngõ cụt. Sau đó, trong mỗi giao lộ, thêm một trình kích hoạt làm cho nhân vật chọn tuyến đường (ví dụ: luôn rẽ trái, luôn rẽ phải hoặc ngẫu nhiên).


1
Có lẽ anh ta đang nói về một cái gì đó giống như Desktop TD nơi người dùng đang tạo bản đồ một cách nhanh chóng. Tuy nhiên, đối với những kẻ thù "ngu ngốc" có thể là một giải pháp tốt để bạn có thể khiến kẻ thù có AI tốt hơn một chút khó khăn.
coderanger
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.