วิธีการใช้พื้นที่ขอบนุ่มกับอนุภาค


13

เกมของฉันสร้างขึ้นโดยใช้ Phaser แต่คำถามตัวเองนั้นไม่เชื่อเรื่องพระเจ้า

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

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

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

ตัวอย่าง (mockup):

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

ฉันคิดว่า 1 สามารถทำได้โดยการทำให้รูปหลายเหลี่ยมเบลอ แต่ฉันไม่แน่ใจว่าจะทำอย่างไรกับ 2

คุณจะดำเนินการเกี่ยวกับเรื่องนี้อย่างไร?


2
นั่นดูดีมาก ฉันขอลิงค์ไปยังเกมของคุณได้ไหม? :)
ashes999

@GameAlchemist นี่คือภาพย่อย i.imgur.com/y54CeQ9.png
OpherV

@ ashes999 ยังอยู่ในระหว่างดำเนินการ แน่นอนผมจะโพสต์ลิงก์ที่นี่เมื่อฉันมีมันขึ้น :)
OpherV

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

@OpherV ที่จะดี โปรดแก้ไขคำถามของคุณและโพสต์ลิงก์ซึ่งอาจเป็นวิธีที่น่าสนใจมากที่สุดในการทำตลาดในเว็บไซต์นี้ :)
ashes999

คำตอบ:


2

1. หากคุณต้องการบางสิ่งที่ใกล้เคียงกับแบบจำลองของคุณฉันจะใช้อนุภาค (มันไม่จำเป็นต้องเป็นระบบอนุภาคแบบเป่าเต็ม)

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

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

สร้าง mockup อย่างรวดเร็วใน jsfiddle ที่อัปเดตซึ่งมีลักษณะเช่นนี้การสาธิต คุณสามารถค้นหาการสาธิตที่อัปเดตได้ที่นี่

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

สูตรในการคำนวณความเร็วของอนุภาคจะเป็นดังนี้:

//player.velocity and particle.velocity are vectors 
//k is a factor to enhance or weaken the influence of players velocity
var distanceToPlayer = (player.position - particle.position).length();
particle.velocity = particle.velocity + ((k * player.velocity) + particle.velocity) * (1/distanceToPlayer);

ในการคำนวณตำแหน่งของอนุภาคที่คุณใส่ไว้ในวิธีการอัพเดตของคุณ:

var speedY = -(springConstant * (particle.position.y - particle.origin.y)) - (dampingFactor * particle.velocity.y);
var speedX = -(springConstant * (particle.position.x - particle.origin.x)) - (dampingFactor * particle.velocity.x);

particle.position.y = particle.position.y + speedY;
particle.position.x = particle.position.x + speedX;

particle.velocity.x = particle.velocity.x + speedX;
particle.velocity.y = particle.velocity.y + speedY;

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

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


นั่นเป็นความคิดที่น่าสนใจจริงๆที่จะแก้ปัญหา # 1! ฉันชอบมัน. คุณจะแนะนำให้ใช้การเคลื่อนที่แบบสามเหลี่ยม \ ระยะห่างได้อย่างไร
OpherV

1
ฉันแก้ไขโพสต์ดั้งเดิมเพื่อตอบคำถาม # 2
zilluss

เพิ่มตัวอย่างเล็ก ๆ ของเอฟเฟกต์อนุภาค ฉันคิดว่าคุณจะได้รับผลที่คุณต้องการด้วยการปรับแต่งเล็กน้อย
zilluss

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

คุณสามารถเล่นกับสิ่งที่ทำให้ชื้นโรงงานและสปริงคงที่ การทำให้หมาด ๆ จะทำให้อนุภาคเร็วขึ้น สปริงตัวล่างจะลดความเร็วของอนุภาคลง น่าเสียดายที่ค่าทั้งสองนี้ทำให้ซุปอนุภาคมีความหนืดมากขึ้น ดังนั้นเมื่อผู้เล่นของคุณสัมผัสกับอนุภาคคุณสามารถยึดความเร็วสูงสุดที่ผู้เล่นเพิ่มเข้ากับอนุภาคเช่นนี้ ) + particle.velocity.x) * (1 / distanceToPlayer)); สำหรับที่หนีบดู: stackoverflow.com/a/11409944
zilluss

4

ความคิดของฉันเกี่ยวกับสองประเด็นนี้:

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

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

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

  2. ฉันจะเขียนโปรแกรมระบบอนุภาคและทำให้อนุภาคเป็นไปตามรูปหลายเหลี่ยม คุณไม่ต้องกังวลกับสิ่งที่จะเกิดขึ้นที่ขอบ การเปลี่ยนแปลงของระบบอนุภาคของคุณจะทำให้แน่ใจว่าอนุภาคนั้นอยู่ภายในรูปหลายเหลี่ยมและกระจายอย่างสม่ำเสมอ คุณสามารถพยายามทำให้อนุภาคที่อยู่ใกล้ที่สุดผลักกันซึ่งอยู่ห่างออกไป แต่ทำให้มีมวลเป็นจำนวนมากดังนั้นคุณจึงมีความเฉื่อยและดูราบรื่น เพื่อทำให้สิ่งนี้เร็วขึ้นมีความเป็นไปได้บ้าง แต่ปัญหาใหญ่ก็คือความซับซ้อนของเวลาในการผลักดันกลไกซึ่งกันและกัน ถ้าคุณทำให้แต่ละอนุภาคผลักอนุภาคอื่น ๆ คุณจะมี O (n ^ 2) ซึ่งไม่ดีถ้าคุณมีตัวอย่าง 100 อนุภาคในระบบของคุณ อ่านดีเกี่ยวกับวิธีที่คุณสามารถเพิ่มประสิทธิภาพนี้เป็นงานนำเสนอของ PixelJunk:http://fumufumu.q-games.com/gdc2010/shooterGDC.pdf

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


ขอบคุณ! 1. ฉันเห็นภาพสิ่งนี้ยาก คุณช่วยโพส mockup ดูว่ามันทำงานอย่างไร \ ในเกมของคุณ? 2. น่าสนใจ! จะอ่านบนนั้น
OpherV

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

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

3

แนวคิดที่ฉันมีเมื่ออ่านโพสต์ของคุณคือสิ่งนี้:
•สร้างชุดไพ่ที่คุณจะใช้สำหรับพื้นที่ของคุณ
•เรนเดอร์รูปหลายเหลี่ยมพื้นที่บนผืนผ้าใบชั่วคราวขนาดเล็กที่ความละเอียดไทล์ (เช่น: หากไทล์เป็น 16X16, เรนเดอร์ที่ความละเอียดต่ำกว่า (16X, 16X))
•ใช้ผืนผ้าใบชั่วคราวนั้นเพื่อตัดสินใจว่าจะแสดงผลกระเบื้องหรือไม่บนผืนผ้าใบหลัก:
หากจุดใดจุดหนึ่งตั้งอยู่บนผืนผ้าใบความละเอียดต่ำให้วาดไทล์ 'สุ่ม' บนผืนผ้าใบหลัก ถ้าจุดนั้นเป็นเพียงเพื่อนบ้านของจุดที่กำหนดให้วาดไทล์ 'สุ่ม' ที่ความทึบต่ำกว่า (เพื่อทำการเปลี่ยน) บนผืนผ้าใบหลัก

ฉันกลัวว่าความละเอียดที่ลดลงจะสร้างเอฟเฟกต์บล็อก แต่แม้จะใช้ไทล์ 20X20 ก็ตามมันก็ดูค่อนข้างดี:

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

ขั้นตอนนี้คือ: ใช้รูปหลายเหลี่ยมของคุณ:
ป้อนคำอธิบายรูปภาพที่นี่

วาดรูปหลายเหลี่ยมที่ความละเอียดไทล์ของคุณ: ป้อนคำอธิบายรูปภาพที่นี่(!! ใช่มันคือสีแดงของห้างสรรพสินค้า)

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

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

ดังนั้นลองวาดแผ่นกระเบื้อง:

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

สำหรับรูปหลายเหลี่ยมฉันวาดรูปหลายเหลี่ยมหลายครั้งปรับขนาดลงและเพิ่มความทึบของแต่ละรูปวาด (หนึ่งอาจใช้ globalCompositeOperation

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

เมื่อคุณรวมทุกอย่างแล้วมันจะทำให้:

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

ซออยู่ที่นี่:

http://jsfiddle.net/gamealchemist/T7b4Y/

แจ้งให้เราทราบหากสิ่งนี้ช่วยได้


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

ฉันหมายถึงว่าเป็นการทดสอบบูลีนแบบสมบูรณ์: ฉันจำเป็นต้องกรอกข้อมูลแผ่นนี้หรือไม่? , จริงหรือเท็จ, มอบให้โดยการทดสอบการทดสอบความละเอียดต่ำบน imageData [(x + y * ความกว้าง) * 4]! = 0, นั่นคือการพูด == 'ฉันวาดบางอย่างบนผืนผ้าใบความละเอียดต่ำที่ กระเบื้องนั้นวางอยู่หรือไม่ ' จากนั้นถ้าใช่ฉันใช้สูตรเฉพาะจำนวนเต็ม (getRandomNumber) ที่กรอกรายละเอียดเพื่อไปจาก (x, y) ไปยังดัชนีไทล์ 'สุ่ม' ที่จะให้หมายเลขเดียวกันสำหรับพื้นที่ที่กำหนด + (x, y) ฉันไม่เห็นว่าสิ่งต่าง ๆ สามารถทับซ้อนกันได้อย่างไรถ้าคุณกำหนดรูปหลายเหลี่ยมของคุณอย่างถูกต้องดังนั้นฉันจึงไม่ได้รับคำถามที่สอง
GameAlchemist

1

แค่ความคิด:

ในแผ่นกระเบื้องของคุณ "ชิ้นส่วน" มีความกว้างสูงสุดประมาณ 80px ฉันอยากจะแนะนำให้ทำ 2 พื้นที่ คุณวาดรูปหลายเหลี่ยมดั้งเดิมของคุณและคุณทำเลียนแบบของมันประมาณ 80 พิกเซลจากแต่ละขอบ จากนั้นคุณวาดไทล์ลงในรูปหลายเหลี่ยมที่ใหญ่กว่า

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

นี่เป็นระดับที่สูงมาก แต่ฉันคิดว่าฉันจะแบ่งปันกับคุณ มีรายละเอียดมากมายที่ต้องพิจารณาที่นี่

ภาพดิบที่แสดงให้เห็น:

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

หากรูปหลายเหลี่ยมสีดำด้านในเป็นต้นฉบับคุณจะลบรูปหลายเหลี่ยมทั้งหมดด้วยจุดสีแดง


คุณจะตรวจสอบจุดตัดของชิ้นส่วนที่ฝังอยู่ในภาพย่อยด้วยแผ่นเหลี่ยมด้านในได้อย่างไร
OpherV

@OpherV Uhmm คุณสามารถตรวจสอบว่าจุด X อยู่ในรูปหลายเหลี่ยมใช่ไหม คุณสามารถวนซ้ำพิกเซลทั้งหมดในรูปหลายเหลี่ยมด้านนอกและสำหรับแต่ละพิกเซลสีขาวตรวจสอบพิกเซลทั้งหมดและดูว่ามีการโกหกใด ๆ ใน / ภายใน outers สิ่งนี้ไม่ได้มีประสิทธิภาพโดยเฉพาะอย่างยิ่ง แต่เมื่อคุณมีสิ่งที่คุณสามารถคิดวิธีการเพิ่มประสิทธิภาพ?
user46560

นั่นเป็นขั้นตอนหลังการประมวลผลเสร็จสิ้นบน CPU ปรับให้เหมาะสมกับตัวเองแทบจะไม่ ความคิดของคุณอาจทำงานได้ดีหากรูปหลายเหลี่ยมด้านในและด้านนอกเชื่อมต่อกันด้วยแถบสามเหลี่ยม OP สามารถเพิ่มข้อมูลแอ็ตทริบิวต์จุดสุดยอดและติดแท็กแต่ละจุดยอดเป็นภายในหรือภายนอก จากนั้นในจุดสุดยอด shader ความทึบ / อัลฟ่าสามารถสอดแทรกเชิงเส้นจากค่าโปร่งใสน้อยลงไปเป็นทึบแสงสมบูรณ์
Teodron

@teodron นี่คือจุดที่ฉันพยายามทำในคำตอบ มันเป็นแนวคิดระดับสูงและฉันไม่ใช่นักพัฒนาเกมจริงๆ ฉันเพิ่งมีความคิด
user46560

@ user46560 ใช่ แต่ด้วยวิธีนี้คุณไม่จำเป็นต้องคำนวณว่าพิกเซลใดที่อยู่ในแถบรูปหลายเหลี่ยมระหว่างนั้นเลย .. ทั้งบน GPU และ CPU เนื่องจากคุณไม่คุ้นเคยกับวิธีการพัฒนาเกมอย่างที่คุณพูดคุณควรได้รับ +1 สำหรับความคิดของคุณ :)
Teodron
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.