( Nên biết trước: Tôi đang sử dụng hai xấp xỉ ở đây: người đầu tiên mất d như chiều dài hồ quang, và lần thứ hai mất nó như là một chiều dài trực giao Cả hai xấp xỉ nên được tốt cho các giá trị tương đối nhỏ của d, nhưng họ không thực hiện đầy đủ. câu hỏi chính xác như được làm rõ trong các ý kiến.)
Toán học về điều này, may mắn thay, là tương đối đơn giản. Trước hết, chúng ta có thể tìm thấy vectơ tương đối từ vị trí trung tâm của chúng ta đến vị trí hiện tại của chúng ta:
deltaX = oX-cX;
deltaY = oY-cY;
Và một khi chúng ta có vectơ tương đối này, thì chúng ta có thể biết bán kính của vòng tròn chúng ta đang làm việc bằng cách tìm độ dài của nó:
radius = sqrt(deltaX*deltaX+deltaY*deltaY);
Hơn nữa, từ vectơ tương đối của chúng ta, chúng ta có thể tìm thấy góc chính xác mà đường thẳng từ cX đến oX nằm ở:
curTheta = atan2(deltaX, deltaY);
Bây giờ mọi thứ trở nên phức tạp hơn một chút. Trước hết, hãy hiểu rằng chu vi của một vòng tròn - nghĩa là 'chiều dài cung' của một cung có số đo góc là 2π - là 2πr. Nói chung, độ dài cung của một cung có số đo góc dọc theo vòng tròn bán kính r chỉ là θr. Nếu chúng ta sử dụng d trong sơ đồ của bạn làm độ dài cung và vì chúng ta biết bán kính, chúng ta có thể tìm thấy sự thay đổi trong theta để đưa chúng ta đến vị trí mới bằng cách chia ra:
deltaTheta = d/radius; // treats d as a distance along the arc
Đối với trường hợp d cần một khoảng cách tuyến tính, mọi thứ phức tạp hơn một chút, nhưng may mắn là không nhiều. Ở đó, d là một cạnh của một tam giác isocele có hai cạnh còn lại là bán kính của đường tròn (từ cX / cY đến oX / oY và aX / aY) và chia đôi tam giác isocele này cho chúng ta hai tam giác vuông, mỗi cạnh có d / 2 là một bên và bán kính là cạnh huyền; điều này có nghĩa là sin của một nửa góc của chúng ta là (d / 2) / bán kính, và do đó, góc đầy đủ chỉ là hai lần này:
deltaTheta = 2*asin(d/(2*radius)); // treats d as a linear distance
Lưu ý làm thế nào nếu bạn lấy asin ra khỏi công thức này và hủy 2 giây, đây sẽ giống như công thức cuối cùng; điều này giống như nói rằng sin (x) xấp xỉ x đối với các giá trị nhỏ của x, đây là một xấp xỉ hữu ích cần biết.
Bây giờ chúng ta có thể tìm thấy góc mới bằng cách thêm hoặc bớt:
newTheta = curTheta+deltaTheta; // This will take you to aX, aY. For bX/bY, use curTheta-deltaTheta
Khi chúng ta có góc mới, sau đó chúng ta có thể sử dụng một số trig cơ bản để tìm vectơ tương đối được cập nhật của mình:
newDeltaX = radius*cos(newTheta);
newDeltaY = radius*sin(newTheta);
và từ vị trí trung tâm và vectơ tương đối của chúng ta, cuối cùng chúng ta có thể tìm thấy điểm mục tiêu:
aX = cX+newDeltaX;
aY = cY+newDeltaY;
Bây giờ, với tất cả điều này, có một số lớn hãy cẩn thận phải nhận thức được. Đối với một người, bạn sẽ nhận thấy rằng toán học này chủ yếu là dấu phẩy động, và trên thực tế nó gần như phải như vậy; cố gắng sử dụng phương pháp này để cập nhật trong một vòng lặp và làm tròn trở lại các giá trị số nguyên ở mỗi bước có thể làm mọi thứ từ làm cho vòng tròn của bạn không đóng (xoắn ốc vào trong hoặc ra ngoài mỗi khi bạn đi vòng vòng) để không bắt đầu trong vòng đầu tiên địa điểm! (Nếu d của bạn quá nhỏ, thì bạn có thể phát hiện ra rằng các phiên bản tròn của aX / aY hoặc bX / bY chính xác là vị trí bắt đầu của bạn oX / oY.) Đối với người khác, điều này rất tốn kém, đặc biệt là những gì nó đang cố gắng làm; nói chung, nếu bạn biết nhân vật của mình sẽ di chuyển theo hình vòng cung, bạn nên lên kế hoạch trước cho toàn bộ cung và khôngđánh dấu nó từ khung này sang khung khác như thế này, vì nhiều tính toán đắt nhất ở đây có thể được tải trước để cắt giảm chi phí. Một cách tốt khác để cắt giảm chi phí, nếu bạn thực sự muốn cập nhật tăng dần như thế này, là không sử dụng trig ở nơi đầu tiên; nếu d nhỏ và bạn không cần chính xác nhưng chỉ cần rất gần, thì bạn có thể thực hiện một 'mẹo' bằng cách thêm một vectơ có chiều dài d vào oX / oY, trực giao với vectơ về phía trung tâm của bạn (lưu ý rằng vectơ trực giao với (dX, dY) được cho bởi (-dY, dX)), và sau đó thu nhỏ nó xuống đúng chiều dài. Tôi sẽ không giải thích mã này từng bước một, nhưng hy vọng nó sẽ có ý nghĩa với những gì bạn đã thấy cho đến nay. Lưu ý rằng chúng tôi 'thu nhỏ' vectơ delta mới ở bước cuối cùng,
deltaX = oX-cX; deltaY = oY-cY;
radius = sqrt(deltaX*deltaX+deltaY*deltaY);
orthoX = -deltaY*d/radius;
orthoY = deltaX*d/radius;
newDeltaX = deltaX+orthoX; newDeltaY = deltaY+orthoY;
newLength = sqrt(newDeltaX*newDeltaX+newDeltaY*newDeltaY);
aX = cX+newDeltaX*radius/newLength; aY = cY+newDeltaY*radius/newLength;
d
một khoảng cách tuyến tính hay là một vòng cung?