Làm cách nào để kiểm tra xem góc gạch có thể nhìn thấy trong không gian 2d không?


7

Tôi đang cố gắng thực hiện sương mù chiến tranh, và tôi đã gặp rắc rối. Tôi muốn kiểm tra xem liệu người chơi có thể nhìn thấy các góc của mỗi ô trong một bán kính nhất định hay không, tuy nhiên tôi không chắc chắn làm thế nào để kiểm tra xem tầm nhìn của các góc có bị cản trở hay không. Có một cách nhanh chóng để làm điều này? Tôi đã sử dụng một hệ thống vẽ một đường thẳng và kiểm tra xem các đường gạch trên đó có phải là các khối rắn chắc không, nhưng tôi không chắc liệu phương pháp này có phù hợp hay không, vì có thể nhìn thấy các phần của gạch, không giống như trong một rougelike trong đó nó là một thứ có hoặc không.

Ví dụ, ô màu đen đang cản trở tầm nhìn một phần của ô màu trắng. Tốt nhất là tốt nhất

Các đường màu đỏ biểu thị rằng người chơi có thể nhìn thấy góc, trong khi màu xanh biểu thị họ không thể (vì màu đen cản trở nó).


Một bản vẽ về tình huống mà bạn đang nói sẽ giúp làm cho câu hỏi này trở nên vững chắc.
MichaelHouse

Câu trả lời:


3

Để hiểu được câu trả lời của Nick một chút: khái niệm cốt lõi đằng sau thuật toán DDA (cũng hoạt động theo ba chiều) là với mỗi trục của lưới của bạn, bạn theo dõi 'điểm giao nhau' tiếp theo cho trục đó theo hướng của bạn tham số dòng; mỗi bước của thuật toán bao gồm tìm trục nào có điểm giao nhau tiếp theo (là so sánh đơn giản theo hai chiều), thực hiện bước thích hợp và cập nhật các giá trị giao nhau tiếp theo cho mỗi trục. Minh họa DDA

Dòng ở đây có thể được viết là '(x, y) = (x0, y0) + t * (m, n)', trong đó m = x1-x0 và n = y1-y0. Nếu kích thước của một ô lưới là gx và gy, thì dx - khoảng cách (tính theo tham số t) mà nó cần để vượt qua một ô lưới - có thể được tìm thấy với một chút đại số nhanh: từ cặp phương trình x = x0 + m t, (x + gx) = x0 + m (t + dx) ta được gx = m * dx, hay nói cách khác là dx = gx / m. Tương tự như vậy, dy = gy / n. Thuật toán theo dõi next_x (khoảng cách đến điểm đỏ tiếp theo dọc theo đường thẳng) và next_y (khoảng cách đến điểm xanh tiếp theo dọc theo đường) và cập nhật chúng mỗi khi nó chạm vào một điểm giao nhau khác, vì vậy vòng lặp trung tâm trông giống như thế này :

while ( cur_t < t_max) {
  if ( next_x < next_y ) {
    cell_x++;
    cur_t += next_x;
    next_y -= next_x;
    next_x = dx;
  } else {
    cell_y++;
    cur_t += next_y;
    next_x -= next_y;
    next_y = dy;
  }
  // Process the cell (cell_x, cell_y)
}

Lưu ý rằng mã này thiếu rất nhiều chi tiết - chẳng hạn, nó không cho bạn biết cách khởi tạo next_x và next_y. Có nhiều cách để loại bỏ hầu hết các đường phân chia, giúp dễ dàng xử lý các trường hợp đặc biệt như đường dọc và ngang. Việc bạn tăng hay giảm cell_x và cell_y tùy thuộc vào góc phần tư của bạn nằm ở đâu - lưu ý rằng đối với dòng ví dụ của tôi, bạn thực sự sẽ giảm cell_x mỗi dấu, vì m (x1 - x0) là âm. Bạn cũng phải quyết định cách bạn sẽ xử lý các trường hợp trong đó dòng của bạn đi chính xác qua góc giữa các ô, thay vì chuyển tiếp trên một cạnh; có rất nhiều chi tiết nhỏ có thể sai, và nó cần rất nhiều thử nghiệm. Tuy nhiên, hy vọng điều này sẽ cung cấp cho bạn một bức tranh về ý tưởng cốt lõi của thuật toán là gì.


1

Thuật toán DDA (Phân tích vi phân số) của John Amanatides & Andrew Woo cung cấp những gì bạn cần. Tôi đang di động rất tẻ nhạt để lấy liên kết mà không đóng trang này. DDA là O (n * m) trong đó n là số ô được đi dọc theo một tia / góc và m là số góc.

Nếu bạn cần kiểm tra xem các phần nhỏ hơn của ô có thể nhìn thấy rõ hơn không (chi tiết tốt hơn), bạn có thể chia từng ô thành một lưới riêng và thực hiện kiểm tra DDA ở cấp đó.

Sự thay thế đáng kể duy nhất khác mà tôi có thể thấy là quét raycast (kiểm tra giao cắt đường thẳng) là O (n * m) với n là số cạnh của gạch trong khu vực quan tâm và m là số góc rời rạc mà bạn kiểm tra cho trong mỗi lần quét vòng tròn (ngụ ý rằng ngay cả với phương pháp này, vẫn tồn tại các vấn đề về độ phân giải). Vì có nhiều cạnh cho mỗi ô, DDA có thể được xem là hiệu quả hơn.

Một cách tiếp cận cuối cùng xuất hiện trong tâm trí là điều chỉnh quét raycasrt bằng cách đặt một góc tia riêng lẻ lên cho mỗi giao điểm lưới riêng lẻ trong khu vực giới hạn của bạn. Bằng cách này, bạn có thể xác định chính xác nơi xảy ra tắc trong lưới của bạn (vì các đường tắc luôn luôn vượt qua các góc) mặc dù bạn sẽ cần hạn chế đáng kể khu vực quan tâm của mình vì sợ số lượng điểm xen kẽ xác định góc tia của bạn sẽ bị mất.

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.