Mô phỏng dòng sản phẩm của tầm nhìn trực tiếp với các chướng ngại vật trên lưới 2d?


10

Chạy vào một vấn đề thú vị. Tôi cần tìm ra cách mô phỏng đường ngắm - đủ đơn giản, chỉ trên lưới 2d có chướng ngại vật. Một ô lưới có thể nhìn thấy hoặc không.

Tôi có thể có được thứ gì đó thực sự thô sơ - như trải rộng n khoảng cách từ người chơi hoặc chặn lan truyền theo chiều ngang khi phát hiện chướng ngại vật liền kề, nhưng tôi không thể để mình sống với nó. Rất nhiều ứng dụng khác đang sử dụng các phương pháp tinh vi hơn làm dốc đường ngắm quanh các góc, v.v., và tôi muốn được ngang bằng.

Cho đến nay DCSS là nguồn cảm hứng của tôi khi tôi bị bối rối, tôi hy vọng sẽ có được thứ gì đó gần với những gì họ có: http://crawl.sz.org/ .

Bất kỳ cái nhìn sâu sắc sẽ được đánh giá cao - cảm ơn sự giúp đỡ!

(Tha thứ nếu điều này là vô nghĩa - chỉ mới bắt đầu trò chơi dev vài tuần trước, cố gắng hết sức để bắt kịp.)


2
Khi bạn nói "dốc đường ngắm quanh các góc", ý bạn chính xác là gì?
Djentman

Điều tốt nhất tôi có thể nói là kiểm tra một trò chơi trên crawl.sz.org. Ví dụ, khi người chơi đứng dưới một bức tường ngang 5 gạch rộng, đường ngắm phá vỡ trên mặt phẳng ngang của bức tường đó - nhưng không phi thực tế vượt ra ngoài nó. Điều tốt nhất tôi có thể ước chừng là giữ tầm nhìn ở mặt phẳng ngang của bức tường.
CodeMoose

Câu trả lời:


7

Đúc tia là một cách rất nhanh và hiệu quả để xác định tầm nhìn. Về cơ bản, nó liên quan đến việc gửi một tia (nghĩ về nó giống như một tia laser vô hạn không thể chuyển hướng) từ một vị trí nhất định theo một hướng nhất định. Sử dụng tia này, bạn có thể xác định những thứ như điểm mà nó giao nhau và cách điểm gốc của nó khi nó đi qua một điểm nhất định.

Vì vậy, ví dụ, trong kịch bản người chơi / kẻ thù, tia có thể bắt nguồn từ kẻ thù với hướng là vị trí của người chơi. Nếu tia va chạm với một khối đặc, kẻ thù không thể nhìn thấy người chơi. Nếu không, kẻ thù có thể nhìn thấy người chơi.

Đây là một hướng dẫn tuyệt vời sẽ giúp.

Bạn cũng có thể xem xét thuật toán dòng của Bresenham (tóm tắt, nó tạo ra các dòng) cho một cái gì đó có thể dễ dàng thu nhỏ hơn cho các ô.


1
Có vẻ như con đường để đi - đặc biệt là của bresenham. Cảm ơn sự giúp đỡ của djent!
CodeMoose

3

Tôi đã viết mã để tính toán đường ngắm từ bản đồ chiều cao. Một bản đồ phẳng đơn giản với các chướng ngại vật chỉ là một bản đồ có chiều cao rất phẳng và việc thực hiện này vẫn hoàn toàn có thể áp dụng được.

nhập mô tả hình ảnh ở đây

Đây là C ++ và nó O(n); nếu bạn biết chiều cao tối đa trong bản đồ, bạn có thể theo dõi đường quét không còn tia nào dưới độ cao đó và xuất hiện sớm:

typedef std::vector<float> visbuf_t;

inline void map::_visibility_scan(const visbuf_t& in,visbuf_t& out,const vec_t& eye,int start_x,int stop_x,int y,int prev_y) {
    const int xdir = (start_x < stop_x)? 1: -1;
    for(int x=start_x; x!=stop_x; x+=xdir) {
        const int x_diff = abs(eye.x-x), y_diff = abs(eye.z-y);
        const bool horiz = (x_diff >= y_diff);
        const int x_step = horiz? 1: x_diff/y_diff;
        const int in_x = x-x_step*xdir; // where in the in buffer would we get the inner value?
        const float outer_d = vec2_t(x,y).distance(vec2_t(eye.x,eye.z));
        const float inner_d = vec2_t(in_x,horiz? y: prev_y).distance(vec2_t(eye.x,eye.z));
        const float inner = (horiz? out: in).at(in_x)*(outer_d/inner_d); // get the inner value, scaling by distance
        const float outer = height_at(x,y)-eye.y; // height we are at right now in the map, eye-relative
        if(inner <= outer) {
            out.at(x) = outer;
            vis.at(y*width+x) = VISIBLE;
        } else {
            out.at(x) = inner;
            vis.at(y*width+x) = NOT_VISIBLE;
        }
    }
}

void map::visibility_add(const vec_t& eye) {
    const float BASE = -10000; // represents a downward vector that would always be visible
    visbuf_t scan_0, scan_out, scan_in;
    scan_0.resize(width);
    vis[eye.z*width+eye.x-1] = vis[eye.z*width+eye.x] = vis[eye.z*width+eye.x+1] = VISIBLE;
    scan_0.at(eye.x) = BASE;
    scan_0.at(eye.x-1) = BASE;
    scan_0.at(eye.x+1) = BASE;
    _visibility_scan(scan_0,scan_0,eye,eye.x+2,width,eye.z,eye.z);
    _visibility_scan(scan_0,scan_0,eye,eye.x-2,-1,eye.z,eye.z);
    scan_out = scan_0;
    for(int y=eye.z+1; y<height; y++) {
        scan_in = scan_out;
        _visibility_scan(scan_in,scan_out,eye,eye.x,-1,y,y-1);
        _visibility_scan(scan_in,scan_out,eye,eye.x,width,y,y-1);
    }
    scan_out = scan_0;
    for(int y=eye.z-1; y>=0; y--) {
        scan_in = scan_out;
        _visibility_scan(scan_in,scan_out,eye,eye.x,-1,y,y+1);
        _visibility_scan(scan_in,scan_out,eye,eye.x,width,y,y+1);
    }
}

Điều này là tốt, nhưng tôi nghĩ nhiều hơn anh ta sau nếu những gì anh ta muốn là bất cứ điều gì giống như liên kết anh ta đăng.
Djentman

Rất sâu sắc và ấn tượng, nhưng djent là đúng - ra khỏi phạm vi của tôi. Cảm ơn các bài mặc dù!
CodeMoose

@CodeMoose eh mã làm việc của nó; chỉ cần cắt-dán, dịch theo nghĩa đen sang bất kỳ ngôn ngữ nào bạn đang nhắm mục tiêu. Đây là một triển khai của Bresenham, được thực hiện tăng dần để nó chỉ ghé thăm mỗi quảng trường một lần. Nếu bạn, đối với mỗi ô vuông, thực hiện một dòng Bresenham cho người chơi, bạn sẽ thấy nó chậm hơn.
Sẽ

Điểm tốt sẽ
CodeMoose
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.