( ถ้ำ:ฉันใช้การประมาณสองค่าที่นี่: อันแรกใช้ความยาวส่วนโค้งและส่วนที่สองใช้เป็นความยาวมุมฉากการประมาณทั้งสองนี้ควรจะดีสำหรับค่า 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 คือด้านหนึ่งของรูปสามเหลี่ยม isoceles ซึ่งอีกสองด้านคือรัศมีของวงกลม (จาก cX / cY ถึง oX / oY และ aX / aY ตามลำดับ) และแบ่งครึ่งสามเหลี่ยม isoceles นี้ให้เราสองสามเหลี่ยมมุมฉากซึ่งแต่ละอัน มี d / 2 เป็นด้านเดียวและมีรัศมีเท่ากับด้านตรงข้ามมุมฉาก นี่หมายความว่าไซน์ของครึ่งมุมของเราคือ (d / 2) / รัศมีและมุมเต็มเป็นสองเท่านี้:
deltaTheta = 2*asin(d/(2*radius)); // treats d as a linear distance
โปรดสังเกตว่าถ้าคุณนำสารออกจากสูตรนี้และยกเลิก 2s สิ่งนี้จะเหมือนกับสูตรสุดท้าย นี่ก็เหมือนกับที่บอกว่าบาป (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, orthogonal ให้กับเวกเตอร์ไปยังศูนย์กลางของคุณ (โปรดสังเกตว่า เวกเตอร์ orthogonal ถึง (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
ระยะทางที่เส้นหรือมันเป็นโค้ง?