วิธี จำกัด การเคลื่อนไหว click'n'drag ไปยังพื้นที่ใด


11

ฉันขอโทษสำหรับชื่อทั่วไปค่อนข้าง ฉันมีเงื่อนงำไม่มากเกี่ยวกับวิธีการทำสิ่งที่ฉันพยายามทำซึ่งทำให้ยากยิ่งขึ้นแม้จะค้นคว้าวิธีแก้ปัญหาที่เป็นไปได้

ฉันพยายามใช้เครื่องหมายบอกทาง (อาจจะมีชื่อที่เหมาะสมที่สุดสำหรับมัน แต่นี่คือสิ่งที่ดีที่สุดที่ฉันสามารถหาได้)

ด้านหน้าของผู้เล่นจะมีเครื่องหมายบอกทางซึ่งจะเป็นตัวกำหนดว่าผู้เล่นจะเคลื่อนที่อย่างไรเมื่อเขาวางแผนที่จะเสร็จ ผู้เล่นสามารถคลิกและลากเครื่องหมายไปยังตำแหน่งที่พวกเขาเลือก แต่เครื่องหมายสามารถเคลื่อนย้ายภายในพื้นที่ทำงานที่กำหนดไว้ (บิตสีเทา)

แผนภาพเครื่องหมายเส้นทาง

ดังนั้นตอนนี้ฉันติดอยู่กับปัญหาที่สอง:

ก่อนอื่นฉันจะกำหนดพื้นที่ทำงานได้อย่างไร ฉันสามารถจินตนาการได้ว่าเวกเตอร์สองตัวที่มีผู้เล่นเป็นจุดเริ่มต้นในการสร้างมุมที่ใช้งานได้และบางทีอาร์คทั้งสองนั้นอาจมาจากวงกลมที่มีศูนย์กลางอยู่ที่ผู้เล่นอยู่ แต่ฉันไม่รู้ว่าจะเอาสิ่งนี้ทั้งหมด ด้วยกัน.

และประการที่สองหลังจากที่ฉันได้กำหนดพื้นที่ที่สามารถวางเครื่องหมายได้ฉันจะบังคับได้อย่างไรว่าเครื่องหมายควรอยู่ในพื้นที่นั้นเท่านั้น ตัวอย่างเช่นหากผู้เล่นคลิกและลากเครื่องหมายไปรอบ ๆ มันอาจเคลื่อนที่ได้อย่างอิสระภายในพื้นที่ทำงาน แต่ต้องไม่ออกจากขอบเขตของพื้นที่ ตัวอย่างเช่นหากผู้เล่นเริ่มลากเครื่องหมายขึ้นด้านบนมันจะเลื่อนขึ้นไปจนถึงจุดสิ้นสุดของพื้นที่ทำงาน (แผนภาพแรกด้านล่าง) แต่ถ้าหลังจากผู้เล่นเริ่มลากไปด้านข้างเครื่องหมายจะต้องติดตามการลากในขณะที่ยังคงอยู่ ภายในพื้นที่ (แผนภาพที่สองด้านล่าง)

First Diagram: เลื่อนขึ้นด้านบน แผนภาพที่สอง: ติดตามการลาก

ฉันหวังว่ามันจะไม่ทำให้สับสนทั้งหมด ขอบคุณเพื่อน.

แก้ไข:ในกรณีที่สร้างความแตกต่างฉันใช้ C ++ กับ Marmalade SDK


ฉันคิดว่าคำที่คุณกำลังมองหาคือ "waypoint" และคุณสามารถกำหนดพื้นที่สีเทาได้หรือไม่? วิธีแก้ปัญหาของคุณอาจจะง่ายกว่านี้ถ้าเป็นเช่นนั้น
John McDonald

Arent waypoints ที่เกี่ยวข้องกับการค้นหาเส้นทางและเช่นนั้น? นอกจากนี้การกำหนดพื้นที่สีเทาทางคณิตศาสตร์เป็นหนึ่งในปัญหาของฉัน: PI คิดว่าฉันสามารถคิดออกบางสิ่งบางอย่างเช่นรูปสี่เหลี่ยมผืนผ้าหรือแม้กระทั่งวงกลม เหนือหัวฉันนิดหน่อย
Vexille

คุณจะต้องระบุภาษาและ / หรือชุดเครื่องมือที่คุณใช้เนื่องจากโซลูชันนั้นขึ้นอยู่กับแพลตฟอร์มเป็นหลัก
Raceimaztion

จริงๆ? ฉันคิดว่าวิธีแก้ปัญหา algorhithmic หรือแม้แต่ pseudocode จะช่วยได้ ฉันจะแก้ไขคำถามอย่างไรก็ตามในกรณี
Vexille

กำหนดรูปร่างในพิกัดเชิงขั้ว (มุมสูงสุดจากมุมตัวอักษรและระยะห่างขั้นต่ำ / สูงสุดจากตัวอักษร) จากนั้นอัปเดต waypoint เป็นตำแหน่งที่เมาส์อยู่หากเมาส์อยู่ภายในขอบเขตเหล่านั้น หากเกินค่า Extreems ใด ๆ เหล่านั้นให้เปลี่ยนเป็นค่า Extreem ที่สุดที่เป็นไปได้ เริ่มอัปเดตเมื่อคลิกภายในพื้นที่และหยุดเมื่อปล่อยเมาส์
ClassicThunder

คำตอบ:


8

คุณสามารถกำหนดพื้นที่ที่สามารถทำงานได้เช่นเดียวกับคำถามของคุณด้วยค่าสามค่า:

float innerRadius;
float outerRadius;
float maxAngle;

ค่าเหล่านี้จะขึ้นอยู่กับจุดศูนย์กลางซึ่งอาจหรืออาจไม่ใช่ตำแหน่งของผู้เล่น รูปร่างของพื้นที่ที่สามารถทำงานได้ขึ้นอยู่กับตำแหน่งที่คุณวางจุดนี้

ป้อนคำอธิบายรูปภาพที่นี่

ในตัวอย่างด้านบนตำแหน่งกึ่งกลางอยู่ระยะทางหนึ่ง (สมมติว่า 50 หน่วย) ด้านหลังผู้เล่น สามารถคำนวณได้อย่างง่ายดายดังนี้:

float offset = -50;
Vector2 centerPosition = playerPosition + offset * playerForward;

หากต้องการ จำกัด ตำแหน่งของเครื่องหมายไปยังพื้นที่ที่สามารถใช้งานได้อันดับแรกให้ย้ายเครื่องหมายตามที่คุณต้องการ จากนั้นตรวจสอบระยะห่างระหว่างจุดกึ่งกลางและเครื่องหมาย:

Vector2 direction = markerPosition - centerPosition;
float distance = direction.Length();
direction.Normalize();
markerPosition = centerPosition + direction * clamp(distance, innerRadius, outerRadius);

ในที่สุดตรวจสอบมุมของเครื่องหมายไปยังช่วงที่ระบุ ฉันจะใช้รหัสปลอมสำหรับอันนี้:

- Find angle between vector C->M and vector playerForward
- If abs(angle) <= maxAngle Then do nothing
- Else If angle > 0 Then rotate M around C by maxAngle-angle
- Else If angle < 0 Then rotate M around C by -maxAngle-angle

ลองดูวิธีหมุนจุดรอบ ๆ ดู สามารถทำได้ทั้งตรีโกณมิติหรือเมทริกซ์การแปลง

คุณอาจต้องการคำนึงถึงขนาดของเครื่องหมายและทำให้รัศมีและมุมเล็กลงเพื่อชดเชย

แก้ไข: ในความคิดที่สองมันอาจดูเป็นธรรมชาติมากขึ้นถ้าคุณตรวจสอบมุมก่อนแล้วตามระยะทางดังนั้นลองใช้ทางเลือกทั้งสอง!


สุดยอดทางออก! ฉันเจอสิ่งที่เกี่ยวข้องกับวงกลมสองวงและสามเหลี่ยม แต่โซลูชันของคุณทำให้มันง่ายขึ้น เกี่ยวกับการตรวจสอบมุมฉันคิดบางอย่างตามแนวการมีเวกเตอร์ปกติที่ยืนที่ maxAngle (และอีกอันที่ -maxAngle) จาก playerForward ซึ่งสามารถคูณด้วยความยาวของ C-> M ในกรณีที่มันมีขอบเขต มุมที่ฉลาด ฉันสมมติว่าวิธีแก้ปัญหาการหมุน M รอบ C จะมีค่าใช้จ่ายน้อยลงใช่ไหม?
Vexille

@Vexille เอาละการหมุนเกี่ยวข้องกับ a cosและการsinปฏิบัติการดังนั้นฉันไม่แน่ใจ แต่ในการคำนวณเวกเตอร์สองตัวนั้นคุณต้องหมุนมันด้วยแม้ว่าคุณจะต้องทำมันก็ต่อเมื่อเวกเตอร์ไปข้างหน้าเปลี่ยนไป ไม่ควรมีความสำคัญมากเลือกตัวเลือกที่คุณต้องการใช้
David Gouveia

10

ฉันกำลังคิดว่าจะแก้ไขปัญหาได้อย่างไรหากรูปร่างไม่สม่ำเสมอและไม่มีใครสามารถกำหนดได้ในเชิงคณิตศาสตร์ คำเตือน: นี่เป็นวิธีการแก้ปัญหาที่สกปรกไม่ใช่สำหรับคนใจร้อน

1. ใช้พื้นที่ของคุณ:

ป้อนคำอธิบายรูปภาพที่นี่

2. และแปลงเป็นบิตแมปขาวดำ:

ป้อนคำอธิบายรูปภาพที่นี่ และตั้งชื่อเป็น scale_0

3. โคลนบิตแมปและลดขนาดเป็น 50%:

ป้อนคำอธิบายรูปภาพที่นี่ และตั้งชื่อเป็น scale_1

4. และต่อ ๆ ไปจนกว่าจะมีบิตแมปน้อยกว่า 4 พิกเซลกว้าง / สูง:

ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ป้อนคำอธิบายรูปภาพที่นี่ ขนาด: 2, 3, 4, 5, 6

5. ตอนนี้เรามีพื้นที่ของเราเป็นบิตแมปขาวดำของความละเอียดที่แตกต่างกัน: ป้อนคำอธิบายรูปภาพที่นี่

6. ถ่ายภาพสุดท้าย (ที่นี่ "scale_6") แล้ววนซ้ำพิกเซลทั้งหมด

  • แปลพิกัดพิกเซลแต่ละตัวเป็นพิกัดหน้าจอx = Math.pow ( 2, scale_level );โดยที่ scale_level คือหมายเลขที่เราเพิ่มหลังจาก "scale_" เราอาจเรียกมันว่าระดับต้นไม้สี่ทิศแม้ว่าเราจะไม่ได้ทำงานกับต้นไม้รูปสี่เหลี่ยม ทำเช่นเดียวกันกับ y
  • ตรวจสอบว่าพิกเซลที่แปล x & y เป็นสีดำ ถ้าไม่เช่นนั้นก็ไม่ได้เป็นส่วนหนึ่งของรูปร่างและคุณควรcontinueไปยังขั้นตอนต่อไปของวง
  • ตรวจสอบว่าพิกเซลอยู่ใกล้เคอร์เซอร์ของเมาส์มากกว่าพิกเซลที่เคยตรวจสอบก่อนหน้านี้หรือไม่ถ้าใช่บันทึกพิกัดของพิกเซล - ใช้พิกัดก่อนการแปลนั่นคือพิกัดภายในบิตแมป
  • ที่ส่วนท้ายของลูปให้คูณพิกัดเหล่านี้ด้วย 2: x *= 2; y*=2;เพื่อแปลเป็นพิกัดในภาพถัดไป (ระดับก่อนหน้า)

7. ถ่ายภาพก่อนหน้า (ที่นี่ "scale_5") แต่อย่าวนซ้ำพิกเซลทั้งหมด เริ่มต้นที่ x = save_x และลงท้ายด้วย x = hidden_x + 2 เหมือนกับ y นั่นคือตั้งแต่ตอนนี้คุณจะวนลูปผ่าน 4 พิกเซลสำหรับทุกระดับเท่านั้น! ส่วนที่เหลือเป็นใน p 6

8. ถ่ายภาพแรก (ที่ใหญ่ที่สุด = หนึ่งที่มีความละเอียดมากที่สุด) วนซ้ำถึง 4 พิกเซลและในที่สุดคุณก็มีพิกเซลที่ใกล้เคียงกับเคอร์เซอร์ของเมาส์มากที่สุด:

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

9. อย่างไรก็ตามฉันถือว่า "M" เป็นจุดตรงนี้ ถ้าคุณต้องการให้มันเป็นวงกลมที่ลงตัวพอดีคุณจะต้องหด (หด) รูปร่างเป็นcircle.radiusพิกเซลก่อน

ฉันคิดว่าฉันจะเพิ่มว่าอัลกอริทึมนี้จะใช้งานได้ถ้าคุณจะใช้ภาพที่ไม่ใช่สีเดียว แต่เป็นสีเทาและใช้พิกเซลเป็น "เต็ม" หากไม่ใช่สีขาวและเป็น "ว่าง" ถ้าเป็นสีขาว ... หรือหากคุณปรับขนาด อัลกอริทึมเปลี่ยนทุกกลุ่มพิกเซล 4 เป็น 1 พิกเซลสีดำทุกครั้งเมื่ออย่างน้อยหนึ่งพิกเซลเหล่านี้ 4 ไม่ขาว


2
+1 สำหรับคำตอบสำหรับรูปร่างที่ยาก (ถ้าเป็นไปไม่ได้) ในการแสดงทางคณิตศาสตร์
Cypher

ว้าวน่าสนใจมาก +1 ด้วย: D
Vexille

ฉันใช้มันในโครงการจริงและฉันต้องบอกว่ามีปัญหาเกิดขึ้น โดยทั่วไปคุณต้องการที่จะทำให้รายการของเซลล์ตารางที่คุณใช้มือถือของตารางที่ใกล้เคียงที่สุดชื่อclosestและตรวจสอบระยะทางไปไกลจุดในclosest- furthest_distชื่อให้ของระยะทาง ตอนนี้คุณต้องลบออกจากรายการเซลล์ทั้งหมดที่มีจุดที่ใกล้ที่สุดไกลกว่าfurthest_distและไประดับลึก ดังนั้นแทนที่จะเป็นอย่างนี้: i.imgur.com/4UuFo.pngมันเป็นแบบนี้: i.imgur.com/dyTT3.png
Markus von Broady
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.