Tôi sẽ giả định rằng bạn có chuyển động vật lý chính xác cho tàu của bạn, vì nếu không phân tích này sẽ không giữ được. Bạn cần một cái gì đó mạnh hơn hiệu quả để giải quyết vấn đề này đúng cách.
Mỗi bộ đẩy sẽ tạo ra hai hiệu ứng trên chuyển động của tàu: tuyến tính và góc. Đây có thể được xem xét độc lập. Nếu bộ đẩy tạo ra một lực f
theo một hướng dir
và được bù từ tâm khối lượng bằng một vectơ r
(không phải tâm hình học hoặc tâm của sprite!), Thì hiệu ứng trên thành phần tuyến tính là:
t = f * dir // f is a scalar, dir is unit length
Ảnh hưởng đến vận tốc góc được cho bởi mô-men xoắn:
tau = f * <dir.x, dir.y, 0> CROSS <r.x, r.y, 0> // cross product
t
là một vectơ lực (tức là lực đẩy tuyến tính). tau
là một vô hướng đã ký mà khi chia cho mômen quán tính khối lượng sẽ cho gia tốc góc. Điều quan trọng là dir
và r
cả hai trong cùng một không gian tọa độ, tức là cả hai tọa độ cục bộ hoặc cả hai tọa độ thế giới.
Gia tốc tuyến tính tổng thể của con tàu được tính bằng tổng của t
mỗi bộ đẩy chia cho khối lượng của con tàu. Tương tự, gia tốc góc chỉ là tổng của các mômen chia cho mômen quán tính khối lượng (là một vô hướng khác). Con tàu sẽ không quay nếu tổng mô-men bằng không. Tương tự, nó sẽ không di chuyển nếu tổng lực đẩy bằng không. Mô-men xoắn nhớ lại là một vô hướng nhưng lực đẩy (tổng của t
') là một vectơ 2D.
Điểm của giải trình này là bây giờ chúng ta có thể viết vấn đề của mình dưới dạng Chương trình tuyến tính . Nói trước tiên chúng tôi muốn tàu của chúng tôi rẽ mà không di chuyển . Chúng tôi có một biến cho mỗi bộ đẩy, $ x_1, x_2, ... $, đó là lượng lực đẩy mà bộ đẩy sẽ cung cấp. Một tập hợp các ràng buộc là:
0 <= x_i < fmax_i //for each i
đâu fmax
là lực tối đa cho bộ đẩy đó (điều này cho phép chúng ta có những lực mạnh hơn hoặc yếu hơn). Tiếp theo, chúng tôi nói rằng cả hai đẳng thức:
0 = Sum_i x_i * dir_i.x
0 = Sum_i x_i * dir_i.y
Điều này mã hóa các ràng buộc mà chúng ta sẽ không áp dụng gia tốc tuyến tính, bằng cách nói tổng lực đẩy bằng không (lực đẩy là một vectơ, vì vậy chúng ta chỉ nói mỗi phần bằng 0).
Bây giờ chúng tôi muốn tàu của chúng tôi rẽ. Có lẽ chúng tôi muốn làm như vậy càng nhanh càng tốt, vì vậy chúng tôi muốn:
max (Sum_i x_i * c_i)
where c_i = <dir_i.x, dir_i.y, 0> CROSS <r_i.x, r_i.y, 0>
Giải quyết vấn x_i
đề trong khi thỏa mãn sự bất bình đẳng và công bằng ở trên, trong khi tối đa hóa tổng kết ở trên, sẽ cho chúng ta lực đẩy mong muốn. Hầu hết các ngôn ngữ lập trình đều có thư viện LP dành cho họ. Chỉ cần đặt vấn đề trên vào nó và nó sẽ tạo ra câu trả lời của bạn.
Một vấn đề tương tự sẽ cho phép chúng ta di chuyển mà không quay đầu. Giả sử chúng ta viết lại vấn đề của mình trong một hệ tọa độ mà chúng ta muốn di chuyển theo hướng x dương. Sau đó, các ràng buộc là:
0 <= x_i < fmax_i //for each i
max Sum_i x_i * dir_i.x
0 = Sum_i x_i * dir_i.y
0 = (Sum_i x_i * c_i)
where c_i = <dir_i.x, dir_i.y, 0> CROSS <r_i.x, r_i.y, 0> // as before
Với sự hạn chế rằng các bộ đẩy chỉ có thể tạo ra lực đẩy theo một hướng duy nhất, sẽ có giới hạn cho loại quay và vận tốc tuyến tính mà bạn sẽ có thể đạt được. Điều này sẽ biểu hiện như là giải pháp 0 = x_1 = x_2 = ... = x_n
, có nghĩa là bạn sẽ không bao giờ đi đến bất cứ đâu. Để giảm thiểu điều này, tôi khuyên bạn nên thêm một cặp bộ đẩy nhỏ, yếu (giả sử 5% hoặc 10%) cho mỗi người chơi đặt bộ đẩy ở góc 45 độ ở hai bên. Điều này sẽ giúp giải pháp linh hoạt hơn, bởi vì chúng có thể được sử dụng để chống lại các tác động thứ yếu yếu của các bộ đẩy chính.
Cuối cùng, để có thể vượt qua 100 thruster, giải pháp cho LP đủ nhanh để thực hiện trên mỗi khung hình. Tuy nhiên, vì giải pháp không phụ thuộc vào vị trí hoặc trạng thái hiện tại, bạn có thể tính toán trước giải pháp cho từng tổ hợp đầu vào bộ điều khiển hợp lý bất cứ khi nào hình dạng thay đổi (điều này bao gồm thêm các bộ đẩy không thay đổi mô men quán tính hoặc khối lượng của tàu, bởi vì sau đó các bộ đẩy ở một vị trí khác so với tâm khối lượng!). Đây là 24 khả năng (tức là 8 lần hướng {quay trái, không quay, quay phải}).