อัลกอริทึมการปูกระเบื้องแผนที่


153

แผนที่

ฉันกำลังสร้าง RPG แบบเรียงต่อกันพร้อมจาวาสคริปต์โดยใช้ความสูงของเสียง perlin จากนั้นกำหนดประเภทของไทล์ตามความสูงของเสียง

แผนที่จะมีลักษณะดังนี้ (ในมุมมองย่อแผนที่)

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

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

จากนั้นเอ็นจิ้นจะกำหนดไทล์จากค่าในอาเรย์แล้วนำไปวางบนผืนผ้าใบ ดังนั้นฉันจึงจบลงด้วยโลกที่น่าสนใจที่มีคุณสมบัติการมองที่เหมือนจริง: ภูเขาทะเล ฯลฯ

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

นี่คือตัวอย่างของสิ่งที่ผู้ใช้จะเห็นในแผนที่ แต่มันไม่ใช่ตำแหน่งเดียวกับวิวพอร์ตด้านบนแสดง!

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

มันอยู่ในมุมมองนี้ที่ฉันต้องการให้การเปลี่ยนแปลงเกิดขึ้น

อัลกอริทึม

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

ตัวอย่างของโปรไฟล์ไทล์

นี่เป็นสถานการณ์ตัวอย่างของสิ่งที่เอ็นจิ้นอาจต้องเรนเดอร์โดยไทล์ปัจจุบันจะถูกทำเครื่องหมายด้วย X

อาร์เรย์ 3x3 ถูกสร้างขึ้นและอ่านค่ารอบ ๆ ดังนั้นตัวอย่างนี้อาร์เรย์จะมีลักษณะเช่นนี้

[
    [1,2,2]
    [1,2,2]
    [1,1,2]
];

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

if(profile[0][1] != profile[1][1]){
     //draw a tile which is half sand and half transparent
     //Over the current tile -> profile[1][1]
     ...
}

ซึ่งให้ผลลัพธ์นี้:

ผลลัพธ์

ซึ่งทำงานเป็นช่วงการเปลี่ยนภาพจาก[0][1]เป็น[1][1]แต่ไม่ใช่จาก[1][1]ถึง[2][1]เป็นแบบขอบแข็ง ดังนั้นฉันจึงคิดว่าในกรณีนั้นจะต้องใช้มุมกระเบื้อง ฉันสร้างแผ่นสไปรต์ 3x3 สองแผ่นที่ฉันคิดว่าจะเก็บชุดที่เป็นไปได้ทั้งหมดที่อาจจำเป็น จากนั้นฉันทำซ้ำสิ่งนี้สำหรับไทล์ทั้งหมดที่มีอยู่ในเกม (พื้นที่สีขาวโปร่งใส) สิ่งนี้จะกลายเป็น 16 แผ่นสำหรับแต่ละประเภทของกระเบื้อง (แผ่นกลางในแต่ละ spritesheet ไม่ได้ใช้)

ทรายSand2

ผลลัพธ์ในอุดมคติ

ดังนั้นด้วยไทล์ใหม่และอัลกอริทึมที่ถูกต้องส่วนตัวอย่างจะมีลักษณะดังนี้:

แก้ไข

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

ทางออกหรือไม่?

ดังนั้นหากใครก็ตามสามารถเสนอทางเลือกอื่นได้ว่าฉันจะสร้างเอฟเฟกต์นี้ได้อย่างไรหรือทิศทางใดที่จะเขียนอัลกอริธึมการทำโปรไฟล์ฉันจะขอบคุณมาก!


7
มีลักษณะที่บทความนี้และบทความที่เชื่อมโยงได้เป็นอย่างดีโดยเฉพาะอย่างยิ่งคนนี้ บล็อกนั้นมีแนวคิดมากมายที่สามารถใช้เป็นจุดเริ่มต้นได้ นี่คือภาพรวม
Darcara

คุณควรทำให้อัลกอริทึมของคุณง่ายขึ้น ตรวจสอบดังนี้: Two-Dimensional-Cellular-Automata
user1097489

คำตอบ:


117

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

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

ขอบกระเบื้อง

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

กระเบื้องเรียบ

โปรดทราบว่าจริงๆแล้วมีหลายประเภทไม่แตกต่างกัน เราต้องการกระเบื้องด้านนอกแปดตัวจากหนึ่งใน 3x3 สแควร์ส แต่มีเพียงสี่มุมสแควร์จากอีกอันหนึ่งเนื่องจากมีการค้นพบกระเบื้องที่มีขอบตรงในจัตุรัสแรก ซึ่งหมายความว่ามีทั้งหมด 12 กรณีเราต้องแยกความแตกต่างระหว่าง

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

หกกรณี

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

กระเบื้องเรียบที่มีตัวเลข

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

เลือก 5a หรือ 5b

การแจงนับขั้นสุดท้ายสำหรับตัวอย่างดั้งเดิมจะมีลักษณะเช่นนี้

การแจงนับขั้นสุดท้าย

และหลังจากเลือกไทล์ขอบที่สอดคล้องกันขอบจะมีลักษณะเช่นนี้

ผลสุดท้าย

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


1
นี่เป็นสิ่งที่ดีและเป็นประโยชน์กับฉันมาก ฉันกำลังจัดการกับกรณีที่ไทล์บางอันไม่สามารถเปลี่ยนเป็นโดยตรงได้ ตัวอย่างเช่นกระเบื้อง "ดิน" สามารถเปลี่ยนเป็น "หญ้าสีอ่อน" และ "หญ้าสีอ่อน" สามารถเปลี่ยนเป็น "หญ้าขนาดกลาง" Tiled (mapeditor.org) ทำงานได้อย่างยอดเยี่ยมในการจัดการสิ่งนี้โดยใช้การค้นหาต้นไม้บางชนิดเพื่อใช้แปรงภูมิประเทศ ฉันยังไม่สามารถทำซ้ำได้
Clay

12

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

heatplate

ปัญหาในการค้นหาอุณหภูมิในแต่ละจุดสามารถแก้ไขได้ในฐานะ "ปัญหาค่าขอบเขต" อย่างไรก็ตามวิธีที่ง่ายที่สุดในการจัดการความร้อนในแต่ละจุดคือการทำแบบจำลองแผ่นเป็นตาราง เรารู้จุดบนกริดที่อุณหภูมิคงที่ เราตั้งอุณหภูมิของจุดที่ไม่รู้จักทั้งหมดให้เป็นอุณหภูมิห้อง (ราวกับว่าช่องระบายอากาศเพิ่งเปิดใช้งาน) จากนั้นเราปล่อยให้ความร้อนกระจายผ่านแผ่นจนกว่าจะถึงการบรรจบกัน สิ่งนี้ทำโดยการวนซ้ำ: เราวนซ้ำตามแต่ละจุด (i, j) เราตั้งค่าจุด (i, j) = (จุด (i + 1, j) + จุด (i-1, j) + จุด (i, j + 1) + จุด (i, j-1)) / 4 [เว้นแต่ จุด (i, j) มีการระบายความร้อนที่อุณหภูมิคงที่]

หากคุณใช้สิ่งนี้กับปัญหาของคุณมันคล้ายกันมากเพียงแค่สีเฉลี่ยแทนที่จะเป็นอุณหภูมิ คุณอาจต้องการการวนซ้ำประมาณ 5 ครั้ง ฉันแนะนำให้ใช้กริด 400x400 นั่นคือ 400x400x5 = น้อยกว่า 1 ล้านรอบซึ่งจะเร็ว หากคุณใช้การวนซ้ำ 5 ครั้งคุณอาจไม่ต้องกังวลเกี่ยวกับการจับจุดสีคงที่เนื่องจากจะไม่เปลี่ยนสีมากเกินไปจากความเป็นจริง (อันที่จริงแล้วเฉพาะจุดที่อยู่ในระยะ 5 จากสีเท่านั้นที่สามารถเปลี่ยนสีได้) รหัสหลอก:

iterations = 5
for iteration in range(iterations):
    for i in range(400):
        for j in range(400):
            try:
                grid[i][j] = average(grid[i+1][j], grid[i-1][j],
                                     grid[i][j+1], grid[i][j+1])
            except IndexError:
                pass

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

1
แต่ละตารางจุดกริด [i] [j] สามารถวาดลงบนผืนผ้าใบเป็นสี่เหลี่ยมเล็ก ๆ (หรือแต่ละพิกเซล) ของสีที่เหมาะสม
เบิร์

5

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

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

ต่อไปนี้เป็นอัลกอริธึมง่ายๆที่ไม่ได้ให้ผลลัพธ์ที่สมบูรณ์แบบ แต่นั่นเป็นรางวัลที่ดีมากโดยใช้ความพยายามต่ำ

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

[1] [*] [2]
[*] [1] [*]
[1] [*] [2]

คือการผสมกระเบื้องที่ติดดาวในเมทริกซ์ด้านบนเท่านั้นหรือ

สมมติว่าขั้นตอนที่ได้รับอนุญาตเท่านั้นที่มีมูลค่าคือหนึ่งครั้งต่อครั้งคุณมีเพียงไม่กี่แผ่นในการออกแบบ ...

A    [1]      B    [2]      C    [1]      D    [2]      E    [1]           
 [1] [*] [1]   [1] [*] [1]   [1] [*] [2]   [1] [*] [2]   [1] [*] [1]   etc.
     [1]           [1]           [1]           [1]           [2]           

จะมีทั้งหมด 16 รูปแบบ หากคุณใช้ประโยชน์จากความสมมาตรการหมุนและการสะท้อนแสงจะมีน้อยลง

'A' จะเป็นไทล์สไตล์ธรรมดา [1] 'D' จะเป็นแนวทแยง

จะมีความไม่ต่อเนื่องเล็กน้อยที่มุมของแผ่นกระเบื้อง แต่สิ่งเหล่านี้จะเล็กน้อยเมื่อเทียบกับตัวอย่างที่คุณให้

ถ้าฉันสามารถฉันจะอัปเดตโพสต์นี้ด้วยภาพในภายหลัง


ฟังดูดีฉันจะสนใจดูด้วยภาพบางภาพเพื่อให้ได้แนวคิดที่ดีขึ้นว่าคุณหมายถึงอะไร
ด่านเจ้าชาย

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

3

ฉันกำลังเล่นกับสิ่งที่คล้ายกับนี้มันไม่ได้จบลงด้วยเหตุผลหลายประการ; แต่โดยทั่วไปมันจะใช้เมทริกซ์ที่ 0 และ 1, 0 เป็นพื้นและ 1 เป็นกำแพงสำหรับแอปพลิเคชันตัวสร้างเขาวงกตใน Flash เนื่องจาก AS3 คล้ายกับ JavaScript จึงไม่ยากที่จะเขียนใหม่ใน JS

var tileDimension:int = 20;
var levelNum:Array = new Array();

levelNum[0] = [1, 1, 1, 1, 1, 1, 1, 1, 1];
levelNum[1] = [1, 0, 0, 0, 0, 0, 0, 0, 1];
levelNum[2] = [1, 0, 1, 1, 1, 0, 1, 0, 1];
levelNum[3] = [1, 0, 1, 0, 1, 0, 1, 0, 1];
levelNum[4] = [1, 0, 1, 0, 0, 0, 1, 0, 1];
levelNum[5] = [1, 0, 0, 0, 0, 0, 0, 0, 1];
levelNum[6] = [1, 0, 1, 1, 1, 1, 0, 0, 1];
levelNum[7] = [1, 0, 0, 0, 0, 0, 0, 0, 1];
levelNum[8] = [1, 1, 1, 1, 1, 1, 1, 1, 1];

for (var rows:int = 0; rows < levelNum.length; rows++)
{
    for (var cols:int = 0; cols < levelNum[rows].length; cols++)
    {
        // set up neighbours
        var toprow:int = rows - 1;
        var bottomrow:int = rows + 1;

        var westN:int = cols - 1;
        var eastN:int = cols + 1;

        var rightMax =  levelNum[rows].length;
        var bottomMax = levelNum.length;

        var northwestTile =     (toprow != -1 && westN != -1) ? levelNum[toprow][westN] : 1;
        var northTile =         (toprow != -1) ? levelNum[toprow][cols] : 1;
        var northeastTile =     (toprow != -1 && eastN < rightMax) ? levelNum[toprow][eastN] : 1;

        var westTile =          (cols != 0) ? levelNum[rows][westN] : 1;
        var thistile =          levelNum[rows][cols];
        var eastTile =          (eastN == rightMax) ? 1 : levelNum[rows][eastN];

        var southwestTile =     (bottomrow != bottomMax && westN != -1) ? levelNum[bottomrow][westN] : 1;
        var southTile =         (bottomrow != bottomMax) ? levelNum[bottomrow][cols] : 1;
        var southeastTile =     (bottomrow != bottomMax && eastN < rightMax) ? levelNum[bottomrow][eastN] : 1;

        if (thistile == 1)
        {
            var w7:Wall7 = new Wall7();
            addChild(w7);
            pushTile(w7, cols, rows, 0);

            // wall 2 corners

            if      (northTile === 0 && northeastTile === 0 && eastTile === 1 && southeastTile === 1 && southTile === 1 && southwestTile === 0 && westTile === 0 && northwestTile === 0)
            {
                var w21:Wall2 = new Wall2();
                addChild(w21);
                pushTile(w21, cols, rows, 270);
            }

            else if (northTile === 0 && northeastTile === 0 && eastTile === 0 && southeastTile === 0 && southTile === 1 && southwestTile === 1 && westTile === 1 && northwestTile === 0)
            {
                var w22:Wall2 = new Wall2();
                addChild(w22);
                pushTile(w22, cols, rows, 0);
            }

            else if (northTile === 1 && northeastTile === 0 && eastTile === 0 && southeastTile === 0 && southTile === 0 && southwestTile === 0 && westTile === 1 && northwestTile === 1)
            {
                var w23:Wall2 = new Wall2();
                addChild(w23);
                pushTile(w23, cols, rows, 90);
            }

            else if (northTile === 1 && northeastTile === 1 && eastTile === 1 && southeastTile === 0 && southTile === 0 && southwestTile === 0 && westTile === 0 && northwestTile === 0)
            {
                var w24:Wall2 = new Wall2();
                addChild(w24);
                pushTile(w24, cols, rows, 180);
            }           

            //  wall 6 corners

            else if (northTile === 1 && northeastTile === 1 && eastTile === 1 && southeastTile === 0 && southTile === 1 && southwestTile === 1 && westTile === 1 && northwestTile === 1)
            {
                var w61:Wall6 = new Wall6();
                addChild(w61);
                pushTile(w61, cols, rows, 0); 
            }

            else if (northTile === 1 && northeastTile === 1 && eastTile === 1 && southeastTile === 1 && southTile === 1 && southwestTile === 0 && westTile === 1 && northwestTile === 1)
            {
                var w62:Wall6 = new Wall6();
                addChild(w62);
                pushTile(w62, cols, rows, 90); 
            }

            else if (northTile === 1 && northeastTile === 1 && eastTile === 1 && southeastTile === 1 && southTile === 1 && southwestTile === 1 && westTile === 1 && northwestTile === 0)
            {
                var w63:Wall6 = new Wall6();
                addChild(w63);
                pushTile(w63, cols, rows, 180);
            }

            else if (northTile === 1 && northeastTile === 0 && eastTile === 1 && southeastTile === 1 && southTile === 1 && southwestTile === 1 && westTile === 1 && northwestTile === 1)
            {
                var w64:Wall6 = new Wall6();
                addChild(w64);
                pushTile(w64, cols, rows, 270);
            }

            //  single wall tile

            else if (northTile === 0 && northeastTile === 0 && eastTile === 0 && southeastTile === 0 && southTile === 0 && southwestTile === 0 && westTile === 0 && northwestTile === 0)
            {
                var w5:Wall5 = new Wall5();
                addChild(w5);
                pushTile(w5, cols, rows, 0);
            }

            //  wall 3 walls

            else if (northTile === 0 && eastTile === 1 && southTile === 0 && westTile === 1)
            {
                var w3:Wall3 = new Wall3();
                addChild(w3);
                pushTile(w3, cols, rows, 0);
            }

            else if (northTile === 1 && eastTile === 0 && southTile === 1 && westTile === 0)
            {
                var w31:Wall3 = new Wall3();
                addChild(w31);
                pushTile(w31, cols, rows, 90);
            }

            //  wall 4 walls

            else if (northTile === 0 && eastTile === 0 && southTile === 1 && westTile === 0)
            {
                var w41:Wall4 = new Wall4();
                addChild(w41);
                pushTile(w41, cols, rows, 0);
            }

            else if (northTile === 1 && eastTile === 0 && southTile === 0 && westTile === 0)
            {
                var w42:Wall4 = new Wall4();
                addChild(w42);
                pushTile(w42, cols, rows, 180);
            }

            else if (northTile === 0 && northeastTile === 0 && eastTile === 1 && southeastTile === 0 && southTile === 0 && southwestTile === 0 && westTile === 0 && northwestTile === 0)
            {
                var w43:Wall4 = new Wall4();
                addChild(w43);
                pushTile(w43, cols, rows, 270);
            }

            else if (northTile === 0 && northeastTile === 0 && eastTile === 0 && southeastTile === 0 && southTile === 0 && southwestTile === 0 && westTile === 1 && northwestTile === 0)
            {
                var w44:Wall4 = new Wall4();
                addChild(w44);
                pushTile(w44, cols, rows, 90);
            }

            //  regular wall blocks

            else if (northTile === 1 && eastTile === 0 && southTile === 1 && westTile === 1)
            {
                var w11:Wall1 = new Wall1();
                addChild(w11);
                pushTile(w11, cols, rows, 90);
            }

            else if (northTile === 1 && eastTile === 1 && southTile === 1 && westTile === 0)
            {
                var w12:Wall1 = new Wall1();
                addChild(w12);
                pushTile(w12, cols, rows, 270);
            }

            else if (northTile === 0 && eastTile === 1 && southTile === 1 && westTile === 1)
            {
                var w13:Wall1 = new Wall1();
                addChild(w13);
                pushTile(w13, cols, rows, 0);
            }

            else if (northTile === 1 && eastTile === 1 && southTile === 0 && westTile === 1)
            {
                var w14:Wall1 = new Wall1();
                addChild(w14);
                pushTile(w14, cols, rows, 180);
            }

        }
        // debug === // trace('Top Left: ' + northwestTile + ' Top Middle: ' + northTile + ' Top Right: ' + northeastTile + ' Middle Left: ' + westTile + ' This: ' + levelNum[rows][cols] + ' Middle Right: ' + eastTile + ' Bottom Left: ' + southwestTile + ' Bottom Middle: ' + southTile + ' Bottom Right: ' + southeastTile);
    }
}

function pushTile(til:Object, tx:uint, ty:uint, degrees:uint):void
{
    til.x = tx * tileDimension;
    til.y = ty * tileDimension;
    if (degrees != 0) tileRotate(til, degrees);
}

function tileRotate(tile:Object, degrees:uint):void
{
    // http://www.flash-db.com/Board/index.php?topic=18625.0
    var midPoint:int = tileDimension/2;
    var point:Point=new Point(tile.x+midPoint, tile.y+midPoint);
    var m:Matrix=tile.transform.matrix;
    m.tx -= point.x;
    m.ty -= point.y;
    m.rotate (degrees*(Math.PI/180));
    m.tx += point.x;
    m.ty += point.y;
    tile.transform.matrix=m;
}

โดยพื้นฐานแล้วจะตรวจสอบไทล์ทุกอันที่เรียงจากซ้ายไปขวาบนลงล่างและถือว่าไทล์ขอบเป็น 1 เสมอฉันได้อิสระในการส่งออกรูปภาพเป็นไฟล์เพื่อใช้เป็นคีย์:

กระเบื้องบุผนัง

นี่เป็นวิธีที่ไม่สมบูรณ์และอาจเป็นวิธีที่แฮ็กเพื่อให้ได้ แต่ฉันคิดว่ามันอาจเป็นประโยชน์

แก้ไข: สกรีนช็อตของผลลัพธ์ของรหัสนั้น

ผลลัพธ์ที่สร้าง


1

ฉันขอแนะนำบางสิ่ง:

  • ไม่สำคัญว่าไทล์ "กึ่งกลาง" คืออะไรใช่ไหม มันอาจเป็น 2 แต่ถ้าคนอื่นทั้งหมดเป็น 1 มันจะแสดง 1

  • มันเป็นเรื่องสำคัญที่มุมคือเมื่อมีความแตกต่างในเพื่อนบ้านทันทีไปด้านบนหรือด้านข้าง หากเพื่อนบ้านที่อยู่ใกล้เคียงทั้งหมดคือ 1 และมุมคือ 2 มันจะแสดง 1

  • ฉันอาจจะคำนวณล่วงหน้าชุดค่าผสมที่เป็นไปได้ทั้งหมดของเพื่อนบ้านสร้างอาร์เรย์ดัชนี 8 ตัวด้วยสี่รายการแรกที่ระบุค่าของเพื่อนบ้านบน / ล่างและอันดับที่สองแสดงเส้นทแยงมุม:

ขอบ [N] [E] [S] [W] [NE] [SE] [SE] [SW] [NW] = สิ่งใดก็ตามที่ชดเชยเป็นสไปรต์

ดังนั้นในกรณีของคุณ [2] [2] [1] [1] [2] [2] [1] [1] = 4 (สไปรต์ที่ 5)

ในกรณีนี้ [1] [1] [1] [1] จะเป็น 1, [2] [2] [2] [2] จะเป็น 2 และส่วนที่เหลือจะต้องทำงานออกมา แต่การค้นหากระเบื้องเฉพาะจะไม่สำคัญ

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