อัลกอริทึมสำหรับแผนที่ 2D ขั้นตอนที่มีเส้นทางเชื่อมต่อ


26

ปัญหาที่จะต้องแก้ไข:สร้างแผนที่ดันเจี้ยน 2D แบบสุ่มสำหรับเกมแบบเรียงต่อกันที่ห้องทั้งหมดเชื่อมต่อกัน

ฉันกำลังมองหาวิธีแก้ปัญหาที่ดีกว่าสิ่งที่ฉันมีอยู่ในปัจจุบัน

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

ด้านล่างคือการใช้งานปัจจุบันของฉัน ขณะนี้ห้องพักไม่มีทางออกหรือออกในทิศทาง 2, 3 หรือ 4

สร้างห้องดันเจี้ยน

ตั้งค่า: ตั้งค่าห้องปัจจุบันเป็นห้องซ้ายบน

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

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

กำลังตรวจสอบเพื่อดูว่าห้องทั้งหมดเชื่อมต่อกันหรือไม่

การตั้งค่า: สร้างแผนที่ 2 มิติของจำนวนเต็มแทนเส้นทางและเริ่มต้นรายการเป็นค่า "ไม่ได้ประมวลผล" (ยังไม่ผ่านการสำรวจ), -1 ตั้งค่าจำนวนเต็มดัชนีพา ธ เริ่มต้นที่ติดตามเส้นทางปัจจุบันเป็น 1 ตั้งค่าห้องปัจจุบันเป็นห้องด้านซ้ายบนโดยเพิ่มลงในสแต็กห้องเพื่อตรวจสอบ

  1. หากสแต็กมีห้องที่ต้องตรวจสอบให้ pop มันตั้งค่าดัชนีพา ธ ของห้องเป็นดัชนีพา ธ ปัจจุบัน หากสแต็กไม่มีห้องใด ๆ ให้เพิ่มดัชนีพา ธ และลองรับห้องโดยเลื่อนคอลัมน์ทีละคอลัมน์ไปทีละแถวจนกว่าเราจะได้ห้องที่ยังไม่ได้ประมวลผล หากไม่มีห้องว่างเราก็เสร็จแล้ว
  2. ตรวจสอบดูว่าห้องมีทางออกด้านซ้ายหรือไม่ ถ้ามันเพิ่มห้องด้านซ้ายลงในสแต็กหากยังไม่ได้อยู่บนนั้น
  3. ทำซ้ำขั้นตอนที่ 2 สำหรับการลงทิศทางขวาและบนสุด (เนื่องจากเราใช้สแต็กซึ่งหมายความว่าห้องจะถูกสำรวจตามลำดับตามเข็มนาฬิกาเริ่มต้นด้วยทิศทางบนสุด)
  4. ทำซ้ำจากขั้นตอนที่ 1
  5. หากการนับดัชนีเส้นทางมีค่ามากกว่าหนึ่งแสดงว่ามีห้องที่ไม่ได้เชื่อมต่อ

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


1
คุณเช็คเอาต์"Dungeon Generation" บน PCG wikiหรือไม่ มันตอบคำถามของคุณหรือไม่
congusbongus

@congusbongus การอ่านที่มีประโยชน์แน่นอน เครื่องมือสร้าง donjon นั้นเชื่อมโยงกับหน้านั้นยอดเยี่ยม ขอบคุณ
user1323245

คำตอบ:


33

หนึ่งในอัลกอริทึมที่ดีที่สุดและใช้มากที่สุดที่ฉันเคยเห็นมีการสร้างดันเจี้ยนโดยใช้การแบ่งพาร์ติชันแบบไบนารี

คำอธิบายทั่วไปที่ดีที่สุดที่ฉันได้อ่านคือคำที่พบในThe Chronicles of Doryen (ท้ายที่สุดเพื่อจุดประสงค์ในการสำรองข้อมูล) เพราะอธิบายขั้นตอนโดยไม่ต้องใช้โค้ด

แบบฝึกหัดอื่น ๆ อีกสองเรื่องในหัวข้อเดียวกันพร้อมรหัสสามารถดูได้ที่


การสร้างแผนภูมิ BSP

เราเริ่มจากดันเจี้ยนสี่เหลี่ยมที่เต็มไปด้วยเซลล์ผนัง พวกเราจะแยกดันเจี้ยนนี้ซ้ำ ๆ จนกว่าดันเจี้ยนย่อยแต่ละตัวจะมีขนาดประมาณห้อง การแยกดันเจี้ยนใช้การดำเนินการนี้:

  • เลือกทิศทางแบบสุ่ม: การแยกในแนวนอนหรือแนวตั้ง
  • เลือกตำแหน่งสุ่ม (x สำหรับแนวตั้ง, y สำหรับแนวนอน)
  • แยกดันเจี้ยนเป็นสองดันเจี้ยนย่อย

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

ตอนนี้เรามีดันเจี้ยนย่อย A และ B สองอันเราสามารถใช้การดำเนินการเดียวกันกับทั้งคู่

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

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

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

อาคารดันเจี้ยน

ตอนนี้เราสร้างห้องที่มีขนาดสุ่มในแต่ละใบไม้ของต้นไม้ แน่นอนว่าห้องต้องอยู่ในดันเจี้ยนย่อยที่เกี่ยวข้อง ขอบคุณต้นไม้ BSP เราไม่สามารถมีสองห้องที่ทับซ้อนกันได้

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

เพื่อสร้างทางเดินเราวนรอบใบไม้ทั้งหมดของต้นไม้เชื่อมต่อแต่ละใบกับน้องสาวของมัน หากทั้งสองห้องมีผนังแบบหันหน้าเข้าหากันเราสามารถใช้ทางเดินตรง เราต้องใช้ทางเดินรูปตัว Z

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

ตอนนี้เราได้รับหนึ่งระดับในต้นไม้และทำซ้ำกระบวนการย่อยภูมิภาคพ่อ ตอนนี้เราสามารถเชื่อมต่อสองภูมิภาคย่อยด้วยการเชื่อมโยงระหว่างห้องสองห้องหรือทางเดินและห้องหรือสองทางเดิน

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

เราทำขั้นตอนนี้ซ้ำจนกว่าเราจะเชื่อมโยงสองดันเจี้ยนย่อย A และ B แรก

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


อาจไม่มีค่าอะไรเลยที่เทคนิคนี้จะไม่สร้างลูป แต่ฉันไม่แน่ใจว่ามีวิธีแก้ไขหรือไม่โดยไม่ต้องเพิ่มทางเดินแบบสุ่มมากขึ้น ยังเป็นคำตอบที่ดีมาก +1
Vality

นี่คือจุดเริ่มต้นที่มีแนวโน้ม เพียงแค่ต้องคิดหาวิธีในการเพิ่มลูปบางส่วน แต่ฉันควรแก้ไขปัญหานั้นมากกว่าดำเนินการตามเส้นทางที่ฉันอยู่ในปัจจุบัน ขอบคุณ
user1323245

2
เยี่ยมมาก! ฉันสนใจรหัสนั้นดังนั้นฉันจึงพยายามทำเล็กน้อย คุณต้องระมัดระวังเมื่อใช้แบบสุ่มไม่เช่นนั้นผลลัพธ์ที่แปลกเกินไปจะตามมา และฉันสงสัยว่าทางเดินไม่ควรถูกจัดการในระหว่างการแยกแบบวนซ้ำเพราะฉันไม่เห็นวิธีง่าย ๆ ในการสร้างทางเดินออกมาจากต้นไม้ ต่อไปสำหรับทุกคนซอที่สนใจอยู่ที่นี่: jsfiddle.net/gamealchemist/xt57zwb8
GameAlchemist

ในขณะที่ฉันพบสิ่งนี้ค่อนข้างมีปัญหาในการทำซ้ำขั้นตอน seeded ข้ามสภาพแวดล้อมขนาดใหญ่ มันอาจเป็นหนึ่งในวิธีที่ดีที่สุดที่ฉันเคยเห็นสำหรับการสร้างแบบนี้ให้คุณกำลังสร้างระดับทั้งหมดของคุณในครั้งเดียว ฉัน +1 สิ่งนี้
คนจรจัดนั่น

4

วิธี BSPเห็นได้ชัดคือวิธีที่นิยมมากที่สุดสำหรับการสร้างดันเจี้ยน แต่มันไม่ได้เป็นเพียงคนเดียว

เพื่อความสมบูรณ์ฉันจะอธิบายกำเนิดที่ทำงานให้ฉัน ฉันต้องยอมรับว่าฉันจำไม่ได้ว่าฉันอ่านอะไรเกี่ยวกับเรื่องนี้ดังนั้นฉันจะบอกว่ามันไม่ใช่สิ่งประดิษฐ์ของฉัน ( บทความเก่าโดยJamis Buckฟังดูคุ้น ๆ )

เขาวงกตพร้อมห้องพัก

แนวคิดพื้นฐานก็คือดันเจี้ยนเป็นเขาวงกตที่มีห้องพักเรียงลำดับจาก ดังนั้นขั้นตอนแรกสำหรับอัลกอริทึมนี้คือการสร้างเขาวงกต :

เขาวงกตที่สร้างขึ้นด้วยอัลกอริธึมของ Eller

ขั้นตอนต่อไปคือการทำให้เบาบาง (ลบปลายตาย):

ทำให้กระจัดกระจาย: ลบปลายตาย

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

จากนั้นสำหรับขั้นตอนที่ 4 เราต้องลบเซลล์ที่แยกได้:

ลบเซลล์ที่แยกได้

ณ จุดนี้เราทำกับทางเดินและเราพร้อมที่จะเพิ่มห้อง เพื่อที่เราจะทำสิ่งต่อไปนี้:

  1. สร้างชุดห้อง (ความกว้างและความสูง)
  2. สำหรับแต่ละห้องเราทำการวนซ้ำตำแหน่งที่เป็นไปได้ทั้งหมดและตัดสินใจเลือกทำเลที่ดีที่สุด
    • ตำแหน่งที่ดีที่สุดจะถูกคำนวณโดยการเพิ่มน้ำหนักให้กับเงื่อนไข (เช่นการติดกับทางเดิน)
  3. เราวางห้อง

จนถึงตอนนี้ดันเจี้ยนของเราจะมีหน้าตาแบบนี้: เพิ่มห้องแล้ว

ขั้นตอนสุดท้ายคือการเพิ่มการตกแต่ง

วาดประตูและหมายเลขห้อง

บางความคิดสุดท้าย

  • ผมใช้รุ่นปล้นลงของเอลเลอร์อัลกอริทึม
  • อัลกอริทึมเขาวงกตที่แตกต่างกันอาจส่งผลให้พื้นผิวที่แตกต่างกัน คุณอาจต้องการอัลกอริทึมอื่น ตัวอย่างเช่นภาพต่อไปนี้แสดงพื้นผิวที่แตกต่างที่เกิดจาก "Binary Tree" (ไบอัสแนวทแยง) และรูปแบบของ "Recursive Division" (อัลกอริธึมยาว): Binary Tree กับ Pseudo-Recursive Division

2
สิ่งที่ดี. ฉันกำลังมองหาวิธีที่แตกต่างในการทำเนื่องจากการใช้อัลกอริทึมที่แตกต่างกันสำหรับระดับที่แตกต่างกันสามารถทำให้เกมมีความหลากหลายมากยิ่งขึ้น
user1323245
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.