Làm thế nào để thực hiện một chùm máy kéo?


8

Tôi đang làm việc trong một trò chơi mà người chơi có thể nhặt các vật bằng cách sử dụng một cái gì đó như chùm máy kéo và mang chúng đi khắp nơi.

Thu hút đối tượng về phía tâm của chùm tia không khó. Nhưng một khi đối tượng đủ gần trung tâm, tôi cần giữ nó ở đó trong khi người chơi di chuyển, đó là điều tôi đang gặp vấn đề. Tôi có thể nghĩ ra hai cách để làm điều đó và cả hai đều có vấn đề:

  1. Cập nhật vị trí của đối tượng bất cứ khi nào vị trí người chơi thay đổi, giữ cho nó tập trung vào chùm tia.

  2. Cập nhật vận tốc của vật thể để hướng thẳng vào tâm của chùm tia, càng đi xa, vận tốc càng nhiều.

Di chuyển và xoay chỉ hoạt động tốt với cả hai phương pháp, nhưng vật lý bị sai khi vật mang theo va chạm với các vật khác:

Với cách tiếp cận đầu tiên, vật lý hoàn toàn bị bỏ qua. Các đối tượng mang theo chỉ cần đẩy bất cứ điều gì ra khỏi đường đi. Đó là bởi vì thay đổi vị trí chỉ được cho là được thực hiện như một phần của vật lý thế giới, dựa trên vận tốc.

Với cách tiếp cận thứ hai, vật lý về cơ bản hành xử theo cách họ nên, nhưng phản ứng thái quá. Vấn đề là: Để giữ vật mang ở trung tâm của chùm tia ngay cả khi quay và di chuyển, tôi cần sử dụng các giá trị vận tốc cao. Vì vậy, một khi vật mang theo chạm vào một vật khác, nó sẽ nhận được quá nhiều vận tốc từ vụ va chạm.

Làm thế nào tôi có thể thực hiện điều này đúng? Dự đoán tốt nhất của tôi ngay bây giờ là đi theo cách tiếp cận thứ hai và thêm xử lý đặc biệt cho các vật mang theo vào vật lý thế giới, giảm vận tốc xuống các giá trị lành mạnh cho va chạm hoặc khi người chơi ngừng mang chúng. Nhưng đó có vẻ là một cách giải quyết không phù hợp.

Chỉnh sửa: Thêm một số mã giả để minh họa cách thức hoạt động của nó ngay bây giờ (đó là cách tiếp cận thứ hai ở trên)

void attract_object(object, ticks) {
    Vector distance = beam_center - object.center;
    // If the object is not close to the beam center, attract it slowly
    if (magnitude(distance) > 10) {
        object.velocity += distance.normalized() * ticks * 0.1;
        return;
    }

    // Here comes the part we're talking about. That magic 0.5 is just high enough
    // that the object isn't lost while moving around. But it's still so high that
    // other objects are repelled with way too much force.
    object.velocity = distance * ticks * 0.5;
}

Từ những gì tôi thấy, điều này xảy ra khi đối tượng mang theo đẩy một đối tượng khác đi:

  1. Vật mang theo va chạm với vật khác
  2. Vận tốc của các vật thể được phân phối hợp lý, do đó vật mang theo bị đẩy ra khỏi tâm chùm trong quá trình
  3. Đoạn mã trên làm cho vật được mang trở về trung tâm của chùm tia, với vận tốc lớn đến mức nó sẽ nhanh chóng quay trở lại đó
  4. Khi vật mang theo di chuyển về phía trung tâm của chùm tia, một nửa vận tốc cao của nó được truyền sang vật khác, đẩy lùi nó dữ dội. Vì vận tốc ban đầu của vật mang có vẻ là lành mạnh, tôi có thể tưởng tượng rằng các bước 2 đến 4 được lặp lại nhiều lần, tạo nên một vận tốc cao như vậy.

Đó dường như là nguyên nhân. Tôi không thể nghĩ ra một cách hay để sửa nó :(


1
Chào mừng bạn đến sự phức tạp của một lò phản ứng nhiệt hạch Tokomak. Bạn có lợi ích khi chỉ cần xây dựng một mô hình toán học hoạt động, không phải là chai từ tính hoạt động, nhưng toán học là giống hệt nhau và không tầm thường. Những gì bạn đang cố gắng là có thể làm được, nhưng bạn sẽ cần suy nghĩ kỹ về mô hình toán học của mình trước khi mã hóa.
Pieter Geerkens

Câu trả lời:


1

Về cơ bản những gì bạn đang tìm kiếm có đối tượng 'chùm' hoạt động chính xác như thể bạn sẽ nắm lấy nó bằng tay của bạn.
Một lựa chọn sẽ là làm cho nó chia sẻ gia tốc a / o tốc độ của 'bàn tay' giữ nó thay vì điều chỉnh vận tốc của nó để lấp đầy khoảng trống với tâm của chùm tia.

Giả sử trung tâm của chùm tia là bàn tay nắm giữ. nếu nhân vật của bạn xoay 90 độ sang trái trong 1 giây, thì vận tốc của tay sẽ là:

If R = length of the arm: which is the radius of the rotation circle
R^2 *PI /4 would be the distance traveled over a second.
làm cho nó nhân với thời gian trôi qua của khung hình để tìm tốc độ bạn phải áp dụng cho đối tượng của mình. Tìm chiều ngang bình thường với chùm tia để tìm vectơ chỉ phương của nó.

Quan điểm của tôi là bạn không phải giải quyết vấn đề nếu bạn thử các triển khai khác không gây ra vấn đề đó ngay từ đầu.

Tôi sẽ đi chơi với súng trọng lực trong HL2 để có cảm hứng về vấn đề này, nhưng tôi có kế hoạch khác cho ngày hôm nay.

EDIT: tôi xin lỗi tôi nghĩ rằng nó là cho một khẩu súng ngắn 3D, nhưng về cơ bản nó giống với 2D ngoại trừ các trục là khác nhau (và không có hình học phức tạp)


Sau khi thử nhiều bản hack khác nhau, đây là những gì giúp tôi đi đúng hướng, kết quả rất tốt. Vận tốc va chạm vẫn còn hơi cao, nhưng tôi nghĩ tôi có thể tìm ra điều đó. Có thể chỉ bằng cách không thu hút bất kỳ vật thể nào có vận tốc cao theo một hướng khác.
futlib

Có thể khi 'bàn tay' đang va chạm với một bức tường, bạn có thể tính toán vị trí hợp lý (không va chạm) gần nhất cho bàn tay và sử dụng nó làm 'bàn tay tạm thời' trong khi xảy ra va chạm. Tôi thường thích tham gia vào các vấn đề từ một quan điểm khác. Tôi vui vì tôi có thể giúp với điều đó;).
icosamuel

4

Làm thế nào về việc thêm một kết nối lò xo, tức là buộc đối tượng mang theo phải di chuyển trở lại vị trí mang theo dựa trên khoảng cách, nhưng vẫn cho phép nó bị đẩy đi bởi những vật rắn (như bức tường).

Liên tục điều chỉnh vận tốc của vật mang theo (bằng cách thay đổi gia tốc dựa trên vị trí / khoảng cách) để hướng về vị trí của chùm máy kéo (tức là cách tiếp cận thứ hai của bạn). Nếu đối tượng bị đẩy đi quá xa, hãy bỏ kết nối (và đối tượng).

Tôi không thực sự chắc chắn tại sao bạn cần vận tốc cao. Đặc biệt trường hợp "người chơi cho phép đi" sẽ chỉ ra rằng tốc độ quay của bạn có thể quá cao hoặc không thực tế. Cũng đừng quên những thứ như sức cản không khí và trọng lực.


Chỉnh sửa: Xem xét mã được cập nhật, vấn đề khá khó tìm:

if (magnitude(distance) > 10) {
    object.velocity += distance.normalized() * ticks * 0.1;
    return;
}

Vấn đề ở đây là trường hợp khoảng cách của đối tượng đến vị trí mục tiêu của nó liên tục quá xa (tức là > 10). Miễn là điều kiện này là đúng, vận tốc của nó chỉ đơn giản là tăng lên nhiều lần (tức là vô thời hạn).

Hai giải pháp khả thi cho việc này:

Xác định vận tốc tối đa:

object.velocity = min(object.velocity + distance.normalized() * ticks * 0.1, max_velocity);

Áp dụng vận tốc cố định thay vì tăng tốc:

object.velocity = distance.normalized() * ticks * magic_factor;

Chỉ cần tăng tốc trong khi quá xa chắc chắn là một cách tiếp cận sai ở đây. Điều quan trọng về việc kéo một lò xo hoặc dây cao su: Sẽ không có vấn đề gì nếu bạn giữ nó trong một giây hoặc một phút. Cuối cùng, nó sẽ tăng tốc theo cùng một cách (xem xét nó đã không chuyển động và không có lực lượng nào khác được áp dụng).


Đó là những gì tôi mô tả trong phương pháp 2, phải không? Đó là vật lý mùa xuân cơ bản AFAIK. Tôi sẽ thêm một số mã cho câu hỏi trên để minh họa nó.
futlib

Cũng loại bỏ phần về vận tốc không chính xác ở trên, nó thực sự tốt, chỉ cần kiểm tra nó. Vì vậy, đó chỉ là sự va chạm với các đối tượng khác đang bị rối tung.
futlib

Vâng, đó thực chất là cách tiếp cận thứ hai của bạn. Cập nhật câu trả lời của tôi.
Mario

Đã thử cả hai cách tiếp cận, nhưng nó không có ích. Có vẻ như cường độ (khoảng cách)> 10 trường hợp không phải là thủ phạm ở đây. Tôi đã cố gắng giới hạn vận tốc cho trường hợp <=, nhưng đó là vấn đề thông thường: Vận tốc thấp đến mức vật thể bị rơi hoặc cao đến mức nó đẩy lùi người khác một cách dữ dội.
futlib

"Cao đến mức nó đẩy lùi người khác một cách dữ dội": Bạn nên di chuyển các vật thể khác dựa trên vận tốc hiệu quả, chứ không phải vận tốc phía sau hậu trường (tức là thiết lập lại vận tốc do va chạm).
Mario
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.