เราจะหลีกเลี่ยง“ เอฟเฟกต์บันได” ในการเคลื่อนไหวของภาพพิกเซลได้อย่างไร


21

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

ที่ความเร็วหน้าจอขนาดใหญ่พอ (vΔtมากกว่า 2 หรือ 3 พิกเซล) นี้ทำงานได้ดีมาก อย่างไรก็ตามเมื่อความเร็วมีขนาดเล็กเอฟเฟกต์บันไดที่เห็นได้ชัดเจนสามารถปรากฏขึ้นได้โดยเฉพาะอย่างยิ่งในแนวเส้นทแยงมุม นี่ไม่ใช่ปัญหาที่ความเร็วหน้าจอช้ามาก (v << 1 พิกเซลต่อวินาที) ดังนั้นฉันจึงมองหาวิธีแก้ปัญหาสำหรับค่าความเร็วกลางเท่านั้น

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

พิกัดพิกเซลสำหรับวิถีวัตถุ

ฉันสนใจแนวคิดของอัลกอริทึมในการกรองวิถีเพื่อลดนามแฝงในขณะที่ยังคงพฤติกรรมเดิมที่ความเร็วสูงและขนาดเล็ก ฉันสามารถเข้าถึงΔtตำแหน่งทันทีและความเร็วเช่นเดียวกับจำนวนโดยพลการของค่าก่อนหน้า แต่เนื่องจากเป็นการจำลองแบบเรียลไทม์ฉันจึงไม่ทราบเกี่ยวกับค่าในอนาคต . โปรดทราบว่าเนื่องจากการจำลองทางฟิสิกส์การเปลี่ยนแปลงทิศทางอย่างฉับพลันอาจเกิดขึ้นได้เช่นกัน

คำตอบ:


18

นี่คือโครงร่างอย่างย่อซึ่งอยู่ด้านบนของหัวของอัลกอริทึมที่ควรจะทำงานได้ดีพอสมควร

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

ใน pseudocode:

if ( abs(velocity.x) > abs(velocity.y) ) {
    x = round(position.x);
    y = round(position.y + (x - position.x) * velocity.y / velocity.x);
} else {
    y = round(position.y);
    x = round(position.x + (y - position.y) * velocity.x / velocity.y);
}

แก้ไข: ใช่ผ่านการทดสอบทำงานได้ค่อนข้างดี


+1 มันใช้งานได้ดีอย่างน่าประหลาดใจ! ฉันสังเกตเห็นการกระโดดย้อนกลับที่แปลก ๆ ด้วยการเคลื่อนที่แบบวงกลมที่ความเร็วช้าเนื่องจากการปรับสามารถทำได้ในทิศทางที่ตรงข้ามกับเวกเตอร์ความเร็ว (ซึ่งโดยปกติแล้วจะเป็นแบบโอเค แต่ไม่ใช่ด้วยความโค้งวิถีเล็ก ๆ ) ที่สามารถแก้ไขได้โดยการคูณvelocity.y / velocity.xด้วยปัจจัยการแก้ไขตามสัดส่วนกับความเร็ว
sam hocevar

@ Sam: คุณหมายถึงรัศมีวงเลี้ยวเล็ก ๆ (= ความโค้งสูง) ใช่ไหม? นั่นอาจทำให้เกิดปัญหากับการอนุมานเชิงเส้นที่ความเร็วต่ำ (โดยทั่วไปจะทำงานตราบเท่าที่ความเร็วยกกำลังสองต่อการเร่งความเร็วมีขนาดใหญ่กว่า 1 พิกเซล) วิธีแก้ปัญหาหนึ่งที่เป็นไปได้ (klugey) อาจจะจำตำแหน่งโค้งมนสุดท้ายและนำมาใช้ใหม่หากใกล้กับตำแหน่งจริงมากกว่าที่คำนวณใหม่ (หนึ่งอาจลองอนุมานตามลำดับที่สูงขึ้น แต่สูตรได้น่าเกลียดมาก)
Ilmari Karonen

อันที่จริงฉันหมายถึงรัศมีขนาดเล็ก ความผิดฉันเอง. และขอบคุณสำหรับคำแนะนำเพิ่มเติม; ประสิทธิภาพไม่สำคัญดังนั้นฉันจึงสามารถปรับปรุงคุณภาพได้
sam hocevar

3

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

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


แม้ที่ความละเอียดสูงการเรนเดอร์จะถูกลดขนาด (เพื่อนบ้านที่ใกล้ที่สุด) เพื่อปรับปรุงลักษณะที่ปรากฏของโรงเรียนเก่า นี่คือการตัดสินใจทางศิลปะ
sam hocevar

@ SamHocevar: ถ้าคุณต้องการ "การปรากฏตัวในวัยชรา" ทำไมคุณไม่ต้องการที่จะ"ปรากฏตัวที่โรงเรียนเก่า" แบบเต็ม ? ทำไมบันไดแบบก้าวเท้าซึ่งเกม "oldschool" ใดที่จะมีไม่ได้เป็นส่วนหนึ่งของเอฟเฟกต์โดยรวมที่คุณต้องการบรรลุ
Nicol Bolas

ฉันไม่คิดว่าเกมโอลด์สคูลที่ดีจะมีการเคลื่อนไหวในแนวทแยงที่มีเอฟเฟกต์ของบันไดนั้นเพราะมันจะดูเหมือนอึ ไม่เหมือนอึเป็นส่วนสำคัญของเอฟเฟ็กต์ oldschool ฉันต้องการบรรลุ :-)
sam hocevar

@ SamHocevar: เกมโรงเรียนส่วนใหญ่เป็นเกมแอคชั่นและดังนั้นจึงไม่ช้าพอที่จะสังเกตเห็น พวกเขายังมีแนวโน้มที่จะไม่เคลื่อนที่ไปตามโค้ง โดยเฉพาะอย่างยิ่งเกมที่ฉันคิดว่าเป็น Solar Jetman ซึ่งมีผลมากเมื่อเคลื่อนที่ช้า จริงอยู่ที่กล้องมีศูนย์กลางอยู่ที่คุณเสมอดังนั้นคุณจึงสังเกตเห็นมันในการเคลื่อนไหวของโลก แต่มันมีอยู่มาก
Nicol Bolas

3

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

ฉันคิดว่าปัญหาอยู่ใน v <sqrt (2) v> sqrt (2) ควรเคลื่อนที่อย่างน้อยแนวทแยงมุมเสมอหลีกเลี่ยงเอฟเฟกต์บันได อาจมีประโยชน์สำหรับการตัดซึ่งจำเป็นต้องมีการเปรียบเทียบการเคลื่อนไหวก่อน


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