การใช้ระบบ L เพื่อสร้างเมืองแบบเป็นขั้นตอน


10

ฉันกำลังสร้างแอพที่เน้นเนื้อหาที่สร้างตามขั้นตอนเป็นจำนวนมาก จนถึงตอนนี้ฉันประสบความสำเร็จในการนำการสร้างภูมิประเทศและรูปร่างของแผนที่โดยใช้สัญญาณรบกวนแบบง่าย ๆ ฉันพอใจจริงๆกับรูปลักษณ์ ตอนนี้ฉันพยายามทำแบบเดียวกันกับเมืองต่างๆ ฉันแค่ต้องสร้างเลย์เอาต์ 2D ของถนนและอาคาร ฉันได้ดูแล้วดูเหมือนว่าคนส่วนใหญ่แนะนำให้ใช้ L-Systems อย่างไรก็ตามฉันไม่สามารถคาดศีรษะโอบรอบพวกเขาได้ ฉันได้รับแนวคิด แต่ไม่ใช่การนำไปใช้เป็นโค้ด ใครบ้างมีตัวอย่างรหัสของ L-Systems สำหรับเมืองที่สร้างขึ้นตามขั้นตอนหรือคำแนะนำเกี่ยวกับวิธีอื่น ๆ ในการจัดการเมือง?


ที่เกี่ยวข้อง: gamedev.stackexchange.com/questions/18799/…
congusbongus

+1 Hurray สำหรับL-Systems !
luser droog

วิธีที่ฉันทำสิ่งที่คล้ายกันคือการสร้างตารางของโหนดแทนจุดตัดจากนั้นสุ่มเชื่อมต่อโหนดที่อยู่ติดกัน สร้างเลย์เอาต์ที่เหมือนเขาวงกต แต่ถนนไม่ได้เชื่อมต่อกันทั้งหมดดังนั้นการนำทางจริงจึงเป็นไปไม่ได้
user137

athority อ้างกันทั่วไปสำหรับเมืองที่สร้าง L-ระบบคือตำบลMüllerและกระดาษ: การสร้างแบบจำลองกระบวนการของเมือง ฉันยังพบตัวอย่างที่ดีของการดำเนินงาน เป็นจุดเริ่มต้นที่ดี แต่ขึ้นอยู่กับความต้องการที่แน่นอนของคุณคุณอาจต้องเปลี่ยนแปลงบางสิ่งรอบตัว
Anders Ryndel

คำตอบ:


20

L-Systemsจากสิ่งที่ฉันสามารถบอกได้ * เป็นชุดของกฎการแทนที่ไวยากรณ์ที่คุณสามารถนำไปใช้ซ้ำเพื่อให้ได้ผลลัพธ์ที่ "น่าสนใจ"

พืชเป็นที่ที่มักใช้ระบบ L เนื่องจากพวกมันมีการเติบโตแบบวนซ้ำ (เช่นกิ่งไม้แยกออกเป็นหลายสาขา) ตัวอย่างง่ายๆฉันจะแสดงทรี "lollipop" ที่สร้างขึ้นโดยใช้ระบบ L:

variables : | o              (these are the things that will grow)
start  : o
         |                   (this is what we start with)
rules  : (o  o   o)         (these are the substitution rules that we apply
               \ /            one step at a time)

ดังนั้นในรุ่นที่ 1 เราเพิ่งเริ่มต้น:

o
|

ที่เจนเนอเรชั่น 2 เราปฏิบัติตามกฎแต่ละข้อและทดแทนส่วนที่มีอยู่ตามกฎ เราแทนที่ "balls" ด้วย "two-sticks-and-balls":

o   o
 \ /
  |

รุ่นที่ 3:

o o   o o
 \|   |/
   \ /
    |

ในไม่ช้าเราจะมีต้นไม้ใหญ่สวย (เส็งเคร็ง)!

ในการทำรหัสคุณสามารถทำซ้ำ (เช่น DFS) ใช้กฎอย่างต่อเนื่องในส่วนเดียวกันจนกว่าคุณจะถึงจุดสิ้นสุดหรือคุณสามารถทำซ้ำ (เช่น BFS) ตามที่เราทำในตัวอย่างนี้ ดำเนินการหนึ่งกฎ "ส่ง" ในองค์ประกอบทั้งหมดและทำซ้ำหลายขั้นตอน นั่นคือ:

ซ้ำ:

tree = start
grow(tree, start)

func grow(tree, part)
    if this part of the tree is big enough
        stop
    if part is 'o'
        replace part with 'o\/o'
        grow(tree, the left 'o')
        grow(tree, the right 'o')

ซ้ำ:

tree = start
for a number of iterations
    for each part in tree
        if part is 'o':
            replace with 'o\/o'

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

variables: block_vertical block_horizontal road_vertical road_horizontal
start: block_vertical
rules: (block_vertical  block_horizontal road_vertical block_horizontal)
       (block_horizontal  block_vertical road_horizontal block_vertical)

จะทำให้รู้สึกในไม่กี่นาที

รุ่นที่ 1:

+--------------------+
|                    |
|                    |
|                    |
|        V           |
|                    |
|                    |
|                    |
+--------------------+

บล็อกแนวตั้งแนวเดียวที่น่าเบื่อ (V หมายถึงแนวตั้ง)

รุ่นที่ 2: เราแทนที่บล็อกแนวตั้งด้วยบล็อกแนวนอนด้วยถนนแนวตั้งที่อยู่ตรงกลาง

+--------------------+
|       r            |
|       r            |
|       r            |
|   H   r      H     |
|       r            |
|       r            |
|       r            |
+--------------------+

r หมายถึงถนน! ฉันเว้นระยะห่างแบบสุ่มเราไม่ต้องการชิ้นส่วนปกติที่น่าเบื่อใน PCG

รุ่นที่ 3: เราแทนที่บล็อกแนวนอนด้วยบล็อกแนวตั้งแยกออกเป็นถนนแนวนอน ถนนที่มีอยู่ยังคงอยู่; ไม่มีกฎสำหรับพวกเขา

+--------------------+
|   V   r            |
|       r            |
|rrrrrrrr            |
|       r      V     |
|   V   r            |
|       rrrrrrrrrrrrr|
|       r      V     |
+--------------------+

สังเกตว่าถนนเชื่อมต่อกันซึ่งเป็นถนนที่ดี ทำซ้ำพอแล้วและคุณจะพบกับสิ่งนี้ (ฉีกคำตอบที่เกี่ยวข้องอย่างโจ๋งครึ่ม):

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

โปรดสังเกตว่ามีรายละเอียดมากมายที่ฉันไม่ได้กล่าวถึงและผลลัพธ์นี้มีลักษณะ "ชัดเจน" ที่สร้างขึ้น - เมืองที่แท้จริงดูเหมือนแตกต่างกันบ้าง นั่นคือสิ่งที่ทำให้ PCG สนุก / ยาก มีหลายสิ่งที่คุณสามารถปรับแต่งและปรับปรุงผลลัพธ์ของคุณได้ แต่การไม่เกี่ยวข้องกับ L-Systems ฉันจะทิ้งคำตอบไว้ที่นี่ หวังว่าสิ่งนี้จะช่วยให้คุณเริ่มต้นได้

* - ฉันยังไม่ได้ศึกษาระบบ L อย่างเป็นทางการแม้ว่าฉันจะได้พบกับประเภทเฉพาะเช่นไวยากรณ์และพืชผัก PCG; โปรดแก้ไขให้ฉันด้วยหากฉันพบคำจำกัดความหรือแนวคิดที่ผิด


1

@congusbongus คำตอบยอดเยี่ยมให้ฉันเพิ่มบางสิ่ง

บล็อกจะต้องแยกออกเป็นพื้นที่อาคารตามถนนทุกสายที่อยู่ติดกัน เมื่อคุณมีถนนรอบ ๆ ลวดลายโดยรวมเป็นวงแหวน ดูลิงค์นี้สำหรับตัวอย่าง: http://oldurbanist.blogspot.fr/2012/01/city-blocks-spaces-in-between.html

(ขึ้นอยู่กับความหนาแน่นอาจไม่มีที่ว่างในจุดศูนย์กลางวงแหวนดูที่เกาลูน)

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

และเพื่อเพิ่มชีวิตให้กับสิ่งนี้คุณอาจต้องการสร้างอิทธิพลให้กับคนรุ่นนี้ด้วยสภาพแวดล้อมเช่นภูมิประเทศหรือแผนที่เศรษฐกิจ: ถนน (ยกเว้นในซานฟรานซิสโก) มีแนวโน้มที่จะไปรอบ ๆ เนินเขาใหญ่แทนที่จะไปทางตรงและบ้านประเภทนั้น ได้รับอิทธิพลจากส่วนหนึ่งของเมืองที่พวกเขาอยู่

มีความสุข.

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