Làm thế nào tôi có thể chặn đối tượng bằng một chuyển động tròn


23

Tôi đang tạo ra một trò chơi không gian 2d và cần phải làm cho tàu vũ trụ đánh chặn một hành tinh. Tôi có mã làm việc cho các đường thẳng chặn nhưng không thể tìm ra cách tính vị trí các hành tinh theo quỹ đạo tròn.

Trò chơi không chính xác về mặt khoa học nên tôi không lo lắng về quán tính, trọng lực, quỹ đạo hình elip, v.v.

Tôi biết vị trí và tốc độ tàu vũ trụ và cả quỹ đạo của các hành tinh (Bán kính) và tốc độ

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


1
Không, tôi đang cố tính toán góc mà con tàu cần di chuyển để đánh chặn hành tinh.
Ausa

4
Điều này có thể sẽ hoạt động tốt hơn trong math.stackexchange.com ..
Jari Komppa

2
Là tàu của bạn có thể thay đổi tốc độ và hướng, hoặc là những hằng số? Ngoài ra, câu hỏi này về việc tránh có tên lửa khoanh tròn mục tiêu có thể hữu ích.
thegrinner

4
Để làm rõ, là tình hình? đưa ra cho hành tinh: trung tâm quỹ đạo, bán kính quỹ đạo, tốc độ góc, vị trí hiện tại; cho tàu : vị trí hiện tại, tốc độ hiện tại; xác định hướng chuyển động cho tàu để đánh chặn hành tinh
AakashM

6
Như một ghi chú lịch sử thú vị: các hành tinh thường quay cùng hướng với quỹ đạo của chúng, do đó cũng ngược chiều kim đồng hồ khi nhìn từ phía trên bán cầu bắc. Từ thực tế này, chúng ta có thể suy luận rằng đồng hồ mặt trời được phát minh ở bán cầu bắc . Nếu đồng hồ mặt trời được phát minh ở bán cầu nam thì chiều kim đồng hồ sẽ là cách khác .
Eric Lippert

Câu trả lời:


3

Một giải pháp phân tích cho điều này là khó khăn, nhưng chúng ta có thể sử dụng tìm kiếm nhị phân để tìm một giải pháp trong độ chính xác cần thiết.

Con tàu có thể đạt đến điểm gần nhất trên quỹ đạo trong thời gian t_min :

shipOrbitRadius = (ship.position - planet.orbitCenter).length;
shortestDistance = abs(shipOrbitRadius - planet.orbitRadius);
t_min = shortestDistance/ship.maxSpeed;

Con tàu có thể đạt tới bất kỳ điểm nào trên quỹ đạo trong thời gian nhỏ hơn hoặc bằng t_max :

(Ở đây, để đơn giản, tôi cho rằng con tàu có thể lái xe qua mặt trời. Nếu bạn muốn tránh điều này thì bạn sẽ cần phải chuyển sang đường không thẳng trong ít nhất một số trường hợp. "Vòng tròn hôn" có thể trông đẹp và quỹ đạo cơ học-y, không thay đổi thuật toán nhiều hơn một yếu tố không đổi)

if(shipOrbitRadius > planet.orbitRadius)
{
   t_max = planet.orbitRadius * 2/ship.maxSpeed + t_min;
}
else
{
   t_max = planet.orbitRadius * 2/ship.maxSpeed - t_min;
}

Nếu thời gian quỹ đạo của chúng ta ngắn, chúng ta có thể cải thiện giới hạn trên bằng cách chọn t_maxlần đầu tiên sau khi t_minhành tinh tiến gần nhất đến vị trí xuất phát của con tàu. Lấy bất kỳ giá trị nào trong hai giá trị t_maxnày là nhỏ hơn. Xem câu trả lời sau này cho một dẫn xuất tại sao điều này hoạt động.

Bây giờ chúng ta có thể sử dụng tìm kiếm nhị phân giữa các cực trị này, t_mint_max . Chúng tôi sẽ tìm kiếm một giá trị t có lỗi gần bằng 0:

error = (planet.positionAtTime(t) - ship.position).squareMagnitude/(ship.maxSpeed*ship.maxSpeed) - t*t;

(Sử dụng cấu trúc này, lỗi @ t_min> = 0 và lỗi @ t_max <= 0, do đó phải có ít nhất một lần chặn với lỗi = 0 cho giá trị t ở giữa)

trong đó, để hoàn thiện, chức năng vị trí giống như ...

Vector2 Planet.positionAtTime(float t)
{
  angle = atan2(startPosition - orbitCenter) + t * orbitalSpeedInRadians;
  return new Vector2(cos(angle), sin(angle)) * orbitRadius + orbitCenter;
}

Lưu ý rằng nếu chu kỳ quỹ đạo của hành tinh rất ngắn so với tốc độ của tàu, chức năng lỗi này có thể thay đổi các dấu hiệu nhiều lần trong khoảng từ t_min đến t_max. Chỉ cần theo dõi cặp + ve sớm nhất mà bạn gặp phải và tiếp tục tìm kiếm giữa chúng cho đến khi lỗi đủ gần bằng 0 ("đủ gần" nhạy cảm với các đơn vị và bối cảnh chơi trò chơi của bạn. hoạt động tốt - đảm bảo việc chặn chính xác trong khung)

Khi bạn có một lỗi giảm thiểu lỗi tốt, bạn có thể chỉ con tàu vào hành tinh.poseitionAtTime (t) và đi hết tốc lực, tự tin rằng hành tinh sẽ đạt đến điểm đó cùng lúc với bạn.

Bạn luôn có thể tìm thấy giải pháp trong các lần lặp Log_2 ((2 * orbitRadius / ship.maxSpeed) / errorThrưỡng). Vì vậy, ví dụ, nếu tàu của tôi có thể đi qua quỹ đạo trong 60 khung hình và tôi muốn đánh chặn chính xác trong một khung hình, tôi sẽ cần khoảng 6 lần lặp.


1
Có rất nhiều câu trả lời hay ở đây, cũng có một số lựa chọn thay thế thú vị nhưng từ những gì tôi đã có giải pháp này có vẻ tốt nhất cho ví dụ của tôi. Tôi đã tạo một bản demo JavaScript nhỏ về kết quả của mình. Bản demo
Ausa

11

Chúng ta đừng quá phức tạp điều này. Đây không phải là một giải pháp "hoàn hảo" nhưng sẽ hoạt động trong hầu hết các trò chơi và mọi sự không hoàn hảo sẽ vô hình với người chơi.

if(!OldTargetPoint)
  TargetPoint = PlanetPosition;
else
  TargetPoint = OldTargetPoint;
Distance = CurPosition - TargetPoint;
TimeNeeded = Distance / Speed;
TargetPoint = PlanetPositionInFuture(TimeNeeded);
SteerTowards(TargetPoint);
[...repeat this every AI update, for example every second...]
  1. Tính thời gian cần thiết để đạt đến điểm mục tiêu.
  2. Tính toán tại vị trí hành tinh sẽ ở thời điểm tính toán.
  3. Di chuyển về phía điểm tính toán.
  4. Nói lại

Điều này hoạt động bởi vì tàu càng gần càng thấp thì lỗi càng thấp. Vì vậy, tính toán trở nên ổn định hơn theo thời gian.

Lỗi là sự khác biệt giữa thời gian cần thiết được tính để đến hành tinh (TimeNeeded) và thời gian thực tế cần thiết để đến hành tinh (sau khi tính đến TargetPoint mới).


1
Bạn có thể muốn chạy 2 lần lặp này khi bắt đầu khóa học đánh chặn, nếu không bạn có thể thấy con tàu nhấp nháy giữa hai hướng trong giây lát (lần đoán thứ hai có thể tốt hơn lần đầu tiên và dẫn đến một tiêu đề rất khác - đặc biệt là nếu con tàu gần hoặc trong quỹ đạo của hành tinh)
DMGregory

1
@DMGregory ơi! Chúng ta chỉ có thể lấy Vị trí hiện tại của Hành tinh thay vì Trung tâm quỹ đạo làm điểm khởi đầu. Khi chúng ta ở gần mà gần hơn nhiều, nếu chúng ta ở xa thì không vấn đề gì.
API-Beast

Cũng đáng lưu ý rằng điều này hoạt động tốt nhất khi hành tinh di chuyển chậm so với con tàu. Nếu tốc độ của hành tinh tương đương hoặc lớn hơn tàu, bạn có thể thấy dao động trên đường đi của tàu. Ở tỷ lệ tốc độ bệnh lý, con tàu có thể đuổi theo hành tinh mãi mãi trên quỹ đạo đồng tâm. Nếu các hành tinh của bạn nhanh và bạn nhận thấy điều này xảy ra, bạn có thể muốn lập kế hoạch cho toàn bộ khóa học đánh chặn của mình lên phía trước thay vì lặp lại giữa chuyến bay.
DMGregory

3

Hãy bắt đầu bằng cách xem xét toán học đằng sau vấn đề.

Bước 1:

Tìm giao điểm giữa đường thẳng và hình chỉ là vấn đề chèn phương trình của đường thẳng vào phương trình của hình, đây là một đường tròn trong trường hợp này.

Đường thẳng giao với đường tròn

Lấy một đường tròn có tâm c và bán kính r . Một điểm p nằm trên đường tròn nếu

|p-c|2= =r2

p= =p0+μv

|p0+μv-c|2= =r2

Khoảng cách bình phương có thể được viết lại dưới dạng một sản phẩm chấm ( http://en.wikipedia.org/wiki/Dot_product ).

(p0+μv-c)(p0+μv-c)= =r2

một= =c-p0(μv-một)(μv-một)= =r2

μ2(vv)-2μ(mộtv)+mộtmột= =r2

|v|= =1

μ22μ(av)+|a|2r2=0

đó là một phương trình bậc hai đơn giản, và chúng ta đi đến giải pháp

μ=av+sqrt((av)2a2r2)

μ<0

μ=0

μ

Bước 2:

μ

Chúng ta có thể làm gì với điều này? Chà, bây giờ chúng ta đã biết quãng đường mà con tàu phải đi và điểm cuối cùng sẽ đến!

p=p0+μvμv

Bây giờ, tất cả những gì còn lại phải làm là tính toán hành tinh sẽ ở đâu khi con tàu bắt đầu tiến về quỹ đạo của nó. Điều này có thể dễ dàng tính toán với cái gọi là Polar phối hợp ( http://mathworld.wolfram.com/PolarCoordins.html )

x=c+rcos(θ)

y=c+rsin(θ)

tangularVelocity

Tóm lược

Chọn một dòng cho tàu của bạn và chạy toán học để xem nó có va chạm với quỹ đạo của các hành tinh không. Nếu có, hãy tính thời gian cần thiết để đi đến điểm đó. Sử dụng thời gian này để quay trở lại quỹ đạo từ thời điểm này với hành tinh để tính toán hành tinh sẽ ở đâu khi con tàu bắt đầu di chuyển.


8
Phân tích tốt, nhưng dường như không trả lời được câu hỏi (được làm rõ trong một bình luận): "Không, tôi đang cố gắng tính toán góc mà con tàu cần di chuyển để đánh chặn hành tinh." Bạn đang lấy góc của con tàu như một sự cho trước và tính toán vị trí của hành tinh, thay vì cách khác.
Chaosed0

4
Sẽ không đánh giá thấp điều này bởi vì nó là phân tích hữu ích, nhưng tôi đồng ý với @ Chaosed0 rằng nó không trả lời câu hỏi. Trong tóm tắt của bạn, bạn nói "Chọn một dòng cho tàu của bạn ..." nhưng chọn dòng đó chính xác là phần khó.
Drake

1

Đây là hai giải pháp hơi "ngoài lề".

Câu hỏi đặt ra là: cho rằng con tàu di chuyển theo một đường thẳng với vận tốc nhất định và hành tinh di chuyển theo một vòng tròn bán kính nhất định với vận tốc góc cho trước, và vị trí bắt đầu của hành tinh và con tàu, xác định hướng của tàu đường thẳng nên được vẽ để vẽ một khóa học đánh chặn.

Giải pháp một: Từ chối tiền đề của câu hỏi. Đại lượng "trượt" trong câu hỏi là góc. Thay vào đó, hãy sửa nó. Chỉ con tàu thẳng vào trung tâm của quỹ đạo.

  • Tính vị trí mà con tàu sẽ gặp hành tinh này; thật dễ dàng
  • Tính khoảng cách từ tàu đến vị trí đánh chặn; cũng dễ
  • Tính thời gian cần thiết cho đến khi hành tinh tiếp theo đạt đến vị trí đánh chặn. Dễ dàng.
  • Chia khoảng cách từ con tàu đến đánh chặn theo thời gian cho đến khi hành tinh được đánh chặn.
  • Nếu nó nhỏ hơn hoặc bằng tốc độ tối đa của tàu, bạn đã hoàn thành. Đặt con tàu di chuyển với tốc độ đó thẳng về phía mặt trời.
  • Nếu không, hãy thêm thời gian quỹ đạo của hành tinh vào thời gian và thử lại. Tiếp tục làm điều đó cho đến khi bạn nhận được một tốc độ trong lý do cho con tàu.

Giải pháp hai: Đừng làm điều đó trên chế độ lái tự động. Tạo một trò chơi nhỏ trong đó người chơi phải sử dụng bộ đẩy để tiếp cận hành tinh và nếu họ đánh nó với tốc độ quá cao, họ sẽ nổ tung, nhưng họ cũng bị hạn chế nhiên liệu. Làm cho người chơi tìm hiểu làm thế nào để giải quyết vấn đề đánh chặn!


1

(x,y,t)

tv=x2+y2

v

Vị trí của hành tinh trong không gian và thời gian có thể được tham số hóa bằng ví dụ

x=x0+rcos(wu+a)y=y0+rsin(wu+a)t=u

u0wau

uv=(x0+rcos(wu+a))2+(y0+rsin(wu+a))2u2v2=(x0+rcos(wu+a))2+(y0+rsin(wu+a))2u2v2=x02+y02+r2+2x0rcos(wu+a)+2y0rsin(wu+a)

Phương trình này cần phải được giải quyết bằng số. Nó có thể có nhiều giải pháp. Bằng cách nhìn nó, có vẻ như nó luôn có một giải pháp


1

Đây là một phần của giải pháp. Tôi đã không hoàn thành nó đúng lúc. Tôi sẽ thử lại sau.

Nếu tôi hiểu chính xác, bạn có vị trí và vận tốc của một hành tinh, cũng như vị trí và tốc độ của một con tàu. Bạn muốn có được hướng di chuyển của con tàu. Tôi cho rằng tốc độ của tàu và hành tinh là không đổi. Tôi cũng cho rằng, không mất tính tổng quát, rằng con tàu đang ở (0,0); để làm điều này, trừ vị trí của con tàu khỏi hành tinh và thêm vị trí của con tàu trở lại kết quả của hoạt động được mô tả dưới đây.

Thật không may, không có latex , tôi không thể định dạng câu trả lời này rất tốt, nhưng chúng tôi sẽ cố gắng thực hiện. Để cho:

  • s_s = tốc độ của tàu (s_s.x, s_s.y, tương tự)
  • s_a= ổ trục của tàu (góc di chuyển, những gì chúng ta muốn tính toán )
  • p_p = vị trí ban đầu của hành tinh, các hợp đồng toàn cầu
  • p_r = khoảng cách (bán kính) của hành tinh từ tâm quỹ đạo, có thể lấy được từ p_p
  • p_a = góc ban đầu của hành tinh tính bằng radian, so với tâm quỹ đạo
  • p_s = vận tốc góc của hành tinh (rad / giây)
  • t = thời gian va chạm (điều này hóa ra cũng là thứ chúng ta phải tính toán)

Đây là các phương trình cho vị trí của hai cơ thể, được chia thành các thành phần:

ship.x = s_s.x * t * cos(s_a)
ship.y = s_s.y * t * sin(s_a)

planet.x = p_r * cos(p_a + p_s * t) + p_p.x
planet.y = p_r * sin(p_a + p_s * t) + p_p.y

Vì chúng tôi muốn ship.x = planet.xship.y = planet.yngay lập tức t, chúng tôi có được phương trình này ( ytrường hợp gần như đối xứng):

   s_s.x * t * cos(s_a) = p_r * cos(p_a + p_s * t) + p_p.x
   s_s.y * t * sin(s_a) = p_r * sin(p_a + p_s * t) + p_p.y

Giải phương trình đỉnh cho s_a:

   s_s.x * t * cos(s_a) = p_r * cos(p_a + p_s * t) + p_p.x
=> s_a = arccos((p_r * cos(p_a + p_s * t) + p_p.x) / (s_s.x * t))

Thay thế điều này vào phương trình thứ hai dẫn đến một phương trình khá kinh hoàng mà Wolfram alpha sẽ không giải quyết được cho tôi . Có thể có một cách tốt hơn để làm điều này không liên quan đến tọa độ cực. Nếu bất cứ ai muốn đưa ra phương pháp này, bạn đều được chào đón; Tôi đã biến nó thành wiki. Mặt khác, bạn có thể muốn đưa cái này đến Math StackExchange .


2
Tôi rất thích kích hoạt TeX cho trang web này. Nó sẽ làm cho một số thứ liên quan đến đồ họa (ví dụ như vectơ, ma trận, bậc bốn ..) dễ biểu diễn hơn.
mvw

0

Tôi sẽ sửa vị trí để chặn (sượt qua vòng tròn, ở phía "đi" của quỹ đạo.)

Bây giờ bạn chỉ cần điều chỉnh tốc độ của tàu vũ trụ để hành tinh và tàu đạt đến điểm đó cùng một lúc.

Lưu ý rằng điểm hẹn có thể là sau N nhiều quỹ đạo hơn, tùy thuộc vào khoảng cách của con tàu và hành tinh quay quanh ngôi sao nhanh như thế nào.

Chọn N mà kịp thời, đến gần nhất với thời gian hành trình của tàu với tốc độ hiện tại.

Sau đó tăng tốc hoặc làm chậm tàu ​​để khớp chính xác dấu thời gian cho các quỹ đạo N đó.

Trong tất cả điều này, khóa học thực tế đã được biết đến! Chỉ là không phải tốc độ.


Điều này có thể cung cấp cho các chuyến đi dài không cần thiết. Giả sử chúng ta định vị sao cho hành tinh đang tiến về phía chúng ta và chúng ta thực sự có thể đạt đến điểm chăn thả "đến" cùng lúc với hành tinh này. Nếu chúng ta chỉ nhìn vào điểm chăn thả "đi", thì cuối cùng chúng ta có thể dành nửa năm nữa để quá cảnh!
DMGregory

Đúng ... phụ thuộc vào tốc độ quỹ đạo. Nhưng nó cũng giảm thiểu tốc độ delta nếu bạn luôn gặm cỏ khi ra ngoài. Tại "đến" bạn có thể bị đốt cháy trong bầu khí quyển, trong khi ở "đi", bạn có nhiều khả năng bị khớp. @DMGregory
Bram
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.