( CAVEAT: тут я використовую два наближення: перше приймає d як довжину дуги, а друге сприймає це як ортогональну довжину. Обидва ці наближення повинні бути хорошими для відносно невеликих значень d, але вони не виконують точне запитання, як уточнено в коментарях.)
Математика з цього питання, на щастя, відносно проста. Перш за все, ми можемо знайти відносний вектор від нашого центрального положення до поточного положення:
deltaX = oX-cX;
deltaY = oY-cY;
І як тільки ми маємо цей відносний вектор, то ми можемо знати радіус кола, над яким працюємо, знайшовши його довжину:
radius = sqrt(deltaX*deltaX+deltaY*deltaY);
Більше того, з нашого відносного вектора ми можемо знайти точний кут, на якому знаходиться лінія від cX до oX:
curTheta = atan2(deltaX, deltaY);
Тепер все стає дещо складніше. Перш за все зрозумійте, що окружність кола - тобто «довжина дуги» дуги з кутовою мірою 2π - дорівнює 2πr. Загалом довжина дуги дуги з кутовою мірою θ вздовж кола радіуса r просто θr. Якби ми використали d у вашій діаграмі як довжину дуги, і оскільки ми знаємо радіус, ми можемо знайти зміну тети, щоб перевести нас до нового положення, просто розділивши:
deltaTheta = d/radius; // treats d as a distance along the arc
У випадку, коли d має бути лінійною відстані, справи дещо складніші, але, на щастя, не набагато. Там d - одна сторона трикутника ізоцели, дві інші сторони якої є радіусом кола (від cX / cY до oX / oY та aX / aY відповідно), а ділення цього трикутника ізоцелей дає нам два правильних трикутника, кожен з яких має d / 2 як одну сторону і радіус як гіпотенузу; це означає, що синус половини нашого кута дорівнює (d / 2) / радіус, і тому повний кут удвічі більший за цей:
deltaTheta = 2*asin(d/(2*radius)); // treats d as a linear distance
Зверніть увагу, як якби ви вийняли асин з цієї формули і скасували 2, це буде те саме, що і остання формула; це те саме, що говорити, що sin (x) - приблизно x для малих значень x, що є корисним наближенням.
Тепер ми можемо знайти новий кут, просто додаючи або віднімаючи:
newTheta = curTheta+deltaTheta; // This will take you to aX, aY. For bX/bY, use curTheta-deltaTheta
Після того, як у нас з'явиться новий кут, ми можемо використати основний триггер, щоб знайти наш оновлений відносний вектор:
newDeltaX = radius*cos(newTheta);
newDeltaY = radius*sin(newTheta);
і з нашого центрального положення та нашого відносного вектора ми можемо (нарешті) знайти цільову точку:
aX = cX+newDeltaX;
aY = cY+newDeltaY;
Тепер, маючи все це, є кілька великих застережень, про які слід знати. Для одного, ви помітите, що ця математика здебільшого з плаваючою точкою, і насправді це мало бути; намагаючись використовувати цей метод для оновлення в циклі і округлення назад до цілих значень на кожному кроці, можна зробити все - від того, щоб зробити коло не закритим (або спіралью всередину або назовні кожен раз, коли ви обходите цикл), щоб не почати його спочатку місце! (Якщо ваш d занадто малий, ви можете виявити, що округлені версії aX / aY або bX / bY - саме там, де було ваше початкове положення oX / oY.) Для іншого це дуже дорого, особливо для того, що він намагається робити; загалом, якщо ви знаєте, що ваш персонаж рухається круговою дугою, ви повинні заздалегідь спланувати всю дугу, а неПоставте галочку від кадру до кадру, як це робиться, оскільки багато найдорожчих розрахунків тут можуть бути передньо завантажені, щоб зменшити витрати. Ще одним хорошим способом зменшити витрати, якщо ви дійсно хочете поступово оновлюватись так, це не використовувати спочатку триггер; якщо d малий і вам не потрібно, щоб він був точним, але був дуже близьким, тоді ви можете зробити «трюк», додавши вектор довжини d до oX / oY, ортогональний вектору до вашого центру (зауважте, що a вектор, ортогональний до (dX, dY), задається (-dY, dX)), а потім зменшиться до потрібної довжини. Я не буду пояснювати цей код так крок за кроком, але, сподіваюся, він матиме сенс, враховуючи те, що ви бачили досі. Зауважте, що ми «скорочуємо» новий дельта-вектор неявно на останньому кроці,
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лінійна відстань чи це дуга?