1 คะแนน โดย GN⁺ 4 시간 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Catlantean 3D เป็นโปรเจกต์เสริมที่ตั้งใจสร้างเกมยิงมุมมองบุคคลที่หนึ่งแบบเต็มรูปแบบภายใต้ข้อจำกัดสไตล์เกมพีซีต้นยุค 1990 โดยตั้งเป้าเรนเดอร์ที่ความละเอียด 320x240 และใช้พาเลต 256 สี
  • เรนเดอร์ทำงานกับเพียงดัชนีของพาเลต จึงมีการคำนวณ colormap ล่วงหน้า 32 ระดับเพื่อทำเอฟเฟกต์มืดลงตามระยะ และระหว่างรันไทม์ก็เลือกสีที่มืดลงได้ด้วยการ lookup แบบ O(1)
  • การสร้างแอสเซ็ตแบ่งเป็น สไปรต์พรีเรนเดอร์ จาก Blender, สไปรต์และเท็กซ์เจอร์วาดมือ, และเท็กซ์เจอร์เชิงกระบวนการที่สร้างด้วยสคริปต์ Python
  • HUD ที่วาดมือและกฎเรื่องสเกลระดับพิกเซลเป็นข้อจำกัดสำคัญเพื่อคงความคมชัดและการอ่านได้ในความละเอียดต่ำ โดยกำหนดให้ 1 ยูนิตในโลกเท่ากับ 64 พิกเซล
  • แทนที่จะใช้ Tiled ผู้พัฒนาสร้างแมปเอดิเตอร์ของตัวเอง และมีแผนจะปล่อยเอดิเตอร์เดียวกันให้ผู้เล่นหลังวางจำหน่าย พร้อมเปิดซอร์สโค้ดของเกมเป็นโอเพนซอร์สบน GitHub

เป้าหมายและข้อจำกัดของโปรเจกต์

  • Catlantean 3D เป็นโปรเจกต์เสริมที่พัฒนาช้า ๆ ในเวลาว่างมานานกว่าหนึ่งปี และตั้งเป้าวางจำหน่ายบน Steam ในปีถัดไป
  • เป้าหมายคือสร้างเกมยิงมุมมองบุคคลที่หนึ่งที่สมบูรณ์และพร้อมวางจำหน่าย โดยใช้เทคนิคที่พบได้ทั่วไปในช่วงต้นยุค 1990
  • อนุญาตให้ใช้คอมไพเลอร์สมัยใหม่และชั้น abstraction ของแพลตฟอร์มได้ แต่ชั้น abstraction จะจำกัดไว้ประมาณเฟรมบัฟเฟอร์สำหรับเขียนพิกเซล, อินพุตคีย์บอร์ดและเมาส์, ออดิโอบัฟเฟอร์สำหรับเขียนแซมเปิล, และไฟล์ซิสเต็ม I/O
  • ตัวเกมต้องสร้างใหม่ทั้งหมดตั้งแต่ต้นรวมถึงแอสเซ็ต และทั้งเรนเดอร์รวมถึงซาวด์มิกซ์ก็ต้องทำเองทั้งหมด
  • ความละเอียดเป้าหมายคือ 320x240 และทุกพิกเซลบนหน้าจอใช้ได้เพียงหนึ่งใน 256 สีเท่านั้น
  • ลอจิกของเกมใช้ fixed-point เพื่อรับประกันพฤติกรรมแบบกำหนดแน่นอน ส่วนการเรนเดอร์ใช้ floating-point เพราะความเป็น deterministic สำคัญน้อยกว่า
  • ผลลัพธ์ต้องไม่ใช่แค่เดโมเทคนิค แต่ต้องเป็นเกมที่เล่นสนุกและสมบูรณ์ และจะไม่ใช้ผลลัพธ์จาก AI
  • งานทั้งหมดที่แสดงอยู่ยังอยู่ระหว่างพัฒนาและอาจเปลี่ยนแปลงอย่างมากได้

การเรนเดอร์แบบพาเลต

  • กราฟิก VGA

    • Mode 13h ของฮาร์ดแวร์ VGA คือโหมดกราฟิก 320x200 256 สี และเป็นโหมดชื่อดังที่นิยามเกมพีซีอยู่ช่วงหนึ่ง
    • จากมุมมองของโปรแกรมเมอร์ Mode 13h ให้เฟรมบัฟเฟอร์เชิงเส้นที่แต่ละพิกเซลแทนด้วย 1 ไบต์ ซึ่งเป็นดัชนีในพาเลต 256 สี
    • หากต้องการวาดพิกเซล ก็เพียงเขียน 1 ไบต์ไปยังแอดเดรสที่กำหนด โดยไม่ต้องยุ่งกับแนวคิดอย่าง shader หรือ VRAM
    • แอสเซ็ตเกมสมัยใหม่อาจใช้สีได้หลายล้านสีในภาพเดียว แต่เมื่อถูกจำกัดไว้ที่ 256 สี ทุกการเลือกสีต้องระมัดระวังและมีเจตนา
    • เกมอย่าง Doom และ Duke Nukem ถูกยกเป็นตัวอย่างว่าความคมและความชัดเจนของกราฟิกเกิดขึ้นจากข้อจำกัดทางเทคนิค
    • Catlantean 3D พยายามถ่ายทอดความรู้สึกนั้นอีกครั้ง แต่เลือกใช้ 320x240 ที่ใกล้เคียง VGA Mode-X มากกว่า 320x200
    • หากแสดง 320x200 บนจอ 4:3 พิกเซลจะไม่เป็นสี่เหลี่ยมจัตุรัส ซึ่งแม้จะดั้งเดิมกว่า แต่ผู้พัฒนาเลือกหลีกเลี่ยงตามความชอบ
  • พาเลต

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

colormap และการจัดการแสง

  • โครงสร้าง raycaster

    • Catlantean 3D เป็น raycaster แบบดั้งเดิม โดยแมปประกอบด้วยไทล์ขนาดเท่ากันทั้งหมด
    • ไทล์บางส่วนเป็นกำแพง และบางส่วนเป็นพื้นที่ว่างที่มีเพียงพื้นกับเพดาน
    • สำหรับแต่ละคอลัมน์ของจอ เรนเดอร์จะใช้ขั้นตอนวิธี DDA เดินผ่านไทล์แมปเพื่อหาตำแหน่งที่ชนกับเรขาคณิตของแมป
    • จากจุดชน จะนำคอลัมน์ของกำแพงที่สุ่มตัวอย่างจากพิกัดเท็กซ์เจอร์ที่เหมาะสมมาวาดบนจอ
    • จากนั้นพื้นและเพดานจะถูกเรนเดอร์ภายหลังด้วย horizontal scanline เพื่อเติมส่วนที่เหลือของจอ
    • หากเรนเดอร์โลกของเกมด้วยพาเลตล้วน ๆ หน้าจอจะดูแบนและไม่น่าประทับใจ
    • เมื่อวัตถุอยู่ไกลจากผู้เล่นมากขึ้น แสงควรลดลง และถ้าด้านหนึ่งของไทล์แมปมืดกว่าอีกด้านเล็กน้อย ก็จะช่วยให้เกิดมิติความลึก
  • การทำให้มืดลงด้วยพาเลต

    • ในเรนเดอร์แบบเร่งด้วยฮาร์ดแวร์สมัยใหม่ การทำให้มืดลงทำได้ง่ายใน shader โดยคูณเวกเตอร์สีด้วยค่าสัมประสิทธิ์แบบ floating-point ตามระยะจากจุดยอด
    • แต่เรนเดอร์แบบพาเลตไม่ได้จัดการกับ “สี” โดยตรง มีเพียงดัชนีของพาเลตเท่านั้น ดังนั้นหากต้องการหาสีที่มืดกว่าของสีหนึ่ง ก็ต้องค้นทั่วทั้งพาเลต
    • การค้นพาเลต 256 สีสำหรับทุกพิกเซลระหว่างเรนเดอร์จะช้าเกินไป จึงเตรียมการ lookup สีแบบเร็วด้วยการคำนวณล่วงหน้าก่อนรัน
    • หากนำพาเลตมาวางเป็นหนึ่งแถวและเลือกขั้นความสว่าง 32 ระดับ ก็จะต้องมีเวอร์ชันที่มืดลง 31 แบบสำหรับแต่ละสี ไม่นับต้นฉบับ
    • จะคำนวณสีเป้าหมายที่มืดลงจากค่า RGB ของแต่ละสีและดัชนีระดับความสว่าง แต่สีนั้นอาจไม่มีอยู่จริงในพาเลต
    • จึงต้องค้นหาสีพาเลตที่ใกล้กับสีเป้าหมายมากที่สุดเพื่อสร้าง colormap
    • ในช่วงแรกใช้ระยะ Euclidean แต่พบว่าสีจำนวนมากถูกดึงไปทางสีเทา และโทนมืดดูเย็นและไร้ชีวิตเกินไป
    • หลังจากนั้นจึงแปลงสีไปยัง color space แบบ Oklab และใช้สูตรระยะเชิงการรับรู้ที่ใกล้เคียงกับการมองเห็นความต่างของสีของมนุษย์มากกว่า
    • ยังมีการใช้แนวคิด hue shifting ของ pixel art โดยเลื่อนสีไปทางโทนอุ่นเล็กน้อยเมื่อมืดลง
    • colormap เป็นเมทริกซ์สองมิติของดัชนีพาเลตที่แทนระดับความสว่างของแต่ละสี และเพราะยังใช้ได้แค่สีในพาเลตเดิม การไล่ระดับจึงไม่สมบูรณ์แบบ
  • ลดต้นทุนขณะรัน

    • เมื่อกำหนดดัชนีแถวของ colormap ตามระยะได้แล้ว ก็เลือกสมาชิกตัวที่ N ในแถวนั้นเพื่อรับดัชนีพาเลตของสี N ที่มืดลง
    • วิธีนี้ทำให้การเลือกสีที่มืดลงระหว่างรันไทม์เป็นการ lookup แบบ O(1)
    • ในการเรนเดอร์กำแพง คอลัมน์ของกำแพงเป็นแนวตั้งล้วนและทุกพิกเซลในคอลัมน์มีระยะจากกล้องเท่ากัน จึงคำนวณดัชนีแถวของ colormap เพียงครั้งเดียวต่อคอลัมน์บนจอ
    • ในการเรนเดอร์พื้น พิกเซลทั้งหมดในแถวแนวนอนเดียวกันมีระยะเท่ากัน จึงคำนวณเพียงครั้งเดียวต่อแถวบนจอ
    • สไปรต์เป็น billboard แบบแบนที่ทุกพิกเซลมีระยะจากกล้องเท่ากัน จึงคำนวณเพียงครั้งเดียวต่อสไปรต์ที่มองเห็น
    • ดังนั้นกำแพงคำนวณ 320 ครั้ง พื้นสูงสุด 240 ครั้ง และสไปรต์ที่มองเห็นแต่ละตัวเพียงครั้งเดียว โดย raycasting ยังช่วยคัดวัตถุที่ถูกบังออกได้ฟรี
    • Doom และเกมอื่นอีกหลายเกมก็ใช้แนวทางคล้ายกัน

วิธีสร้างแอสเซ็ต

  • แอสเซ็ตสามหมวด

    • เท็กซ์เจอร์และสไปรต์ของ Catlantean 3D แบ่งเป็นสามหมวด
    • หมวดแรกคือสไปรต์พรีเรนเดอร์ที่เรนเดอร์มาจากโมเดล 3D ที่สร้างใน Blender
    • หมวดที่สองคือสไปรต์และเท็กซ์เจอร์ที่วาดด้วยมือ
    • หมวดที่สามคือเท็กซ์เจอร์เชิงกระบวนการที่สร้างด้วยสคริปต์ Python พิเศษซึ่งนำงานวาดมือมาประกอบกัน
  • สไปรต์พรีเรนเดอร์

    • สไปรต์แอนิเมชันที่ซับซ้อนต้องแก้ไขหลายเฟรม ทำให้การทำซ้ำยุ่งยากและใช้เวลามาก
    • วิธีที่มีประสิทธิภาพกว่าคือสร้างโมเดล 3D ใน Blender ทำ rigging และ animation จากนั้นใช้สคริปต์ที่เรียก Blender Python API เพื่อเรนเดอร์เท็กซ์เจอร์จำนวนมาก
    • การแก้ไขจะทำที่ตัวโมเดล แล้วปล่อยให้สคริปต์เรนเดอร์จัดการส่วนที่เหลือ จึงลดเวลาในการทำซ้ำได้มาก
    • ปัญหาหลักคือสไปรต์ที่เรนเดอร์ออกมามักเบลอมากและดูเหมือนสีซีด
    • การเรนเดอร์ที่ความละเอียดสูงแล้วค่อยย่อด้วยฟิลเตอร์ให้ผลปะปนกัน เพราะรายละเอียดมักถูกฟิลเตอร์กลบและขอบสูญเสียความคม
    • วิธีที่มีประสิทธิภาพและนำกลับมาใช้ซ้ำได้มากที่สุดคือใช้ระบบ compositing ของ Blender เพื่อให้ได้คอนทราสต์และความคมที่เหมาะสม
    • เมื่อภาพพร้อมแล้ว สคริปต์ Python พิเศษจะทำ palette quantization เพื่อสร้างภาพพิกเซลแบบ 1 ไบต์ที่เอนจินใช้
    • สำหรับทุกพิกเซลในภาพต้นฉบับ สคริปต์จะหาสีพาเลตที่ใกล้ที่สุดในเชิงการรับรู้ตาม Oklab แล้วใช้ดัชนีของสีนั้นเป็นค่าพิกเซล
    • อาร์เรย์ของดัชนีและข้อมูลขนาดจะถูกแพ็กลงในฟอร์แมต TEX แบบง่ายที่เกมใช้
    • สไปรต์ศัตรูอาจมีหลายแอนิเมชัน และแต่ละแอนิเมชันต้องมีเฟรมสำหรับทั้ง 8 ทิศทางที่สไปรต์สามารถหันได้
    • สคริปต์ Python จะหมุนสไปรต์สำหรับแต่ละแอนิเมชัน เรนเดอร์ทุกเฟรม แล้วหมุนใหม่ซ้ำไปเรื่อย ๆ
    • ชื่อไฟล์สไปรต์จะถูกบันทึกตามกฎที่ระบุชื่อสไปรต์ ชื่อท่า ทิศทาง และดัชนีเฟรม
    • สไปรต์ที่เรนเดอร์แล้วจะไม่ถูกเก็บไว้ในรีโพและถูกใส่ใน .gitignore ส่วนบนเครื่องอื่น สคริปต์คอมไพล์จะเรนเดอร์ทุกโมเดลเพื่อสร้างสไปรต์ขึ้นมาใหม่
    • บน RTX 3070 ใช้เวลาราว 10 วินาทีในการประมวลผลโมเดลประมาณ 15 ตัว
  • สไปรต์และเท็กซ์เจอร์วาดมือ

    • ในช่วงต้นของการพัฒนา มีการสร้างหัวทรงแมวพร้อมเท็กซ์เจอร์จากแมวชื่อ Vilko ใน Blender เพื่อใช้เป็นใบหน้าบนแถบสถานะ
    • ผลลัพธ์นั้นดูขี้เกียจและใช้ความพยายามต่ำ สื่ออารมณ์ได้ไม่ดี และเป็นสิ่งแรกที่คนชี้ให้เห็นจากการให้ความเห็นด้านบรรยากาศของเกม
    • องค์ประกอบบางอย่างจำเป็นต้องวาดด้วยมือ และผู้พัฒนาตัดสินใจว่าเวอร์ชันวาดมือที่มีแอนิเมชันดีกว่ามาก
    • ด้วยขนาดของสไปรต์ ทุกพิกเซลต้องมีเจตนา จึงไม่มีพื้นที่ให้ปล่อยให้เรนเดอร์ของ Blender ตัดสินแทน
    • ตรรกะเดียวกันนี้ใช้กับไอเท็มเก็บส่วนใหญ่ด้วย โดยผลลัพธ์พรีเรนเดอร์ก่อนหน้านี้ไม่สามารถให้คุณภาพที่ดีอย่างสม่ำเสมอในสเกลเล็กด้วย compositor ของ Blender
    • หลังผ่านการปรับด้วยมือ ความคมชัดและการอ่านของไอเท็มเก็บดีขึ้นอย่างมาก
    • การเพิ่มความละเอียดของสไปรต์อย่างเดียวแม้ให้เกม rasterizer ย่อหรือขยายได้ แต่ผลลัพธ์ไม่ดีเพราะสเกลพิกเซลไม่สม่ำเสมอ
    • ผู้เล่นมักคาดหวังโดยไม่รู้ตัวว่าเมื่อวัตถุเคลื่อนหน้า-หลังในแถวหรือคอลัมน์เดียวกัน ขนาดพิกเซลจะยังคงเท่ากัน ดังนั้นถ้าสไปรต์แต่ละตัวมีสเกลพิกเซลต่างกันจะดูแปลก
    • ใน Catlantean 3D หนึ่งยูนิตของโลกเท่ากับ 64 พิกเซล และสไปรต์ทั้งหมดถูกสร้างให้สอดคล้องกับสเกลนี้
    • สไปรต์ที่สูงหนึ่งในสี่ของยูนิตโลกจึงต้องสูง 64/4=16 พิกเซล

HUD และไปป์ไลน์การสร้างเชิงกระบวนการ

  • HUD

    • HUD และองค์ประกอบของมันแทบทั้งหมดถูกจัดวางและวาดด้วยมือ
    • แถบสถานะด้านล่างจอ แผงและหน้าจอเปลี่ยนผ่านต่าง ๆ รวมถึงฟอนต์ อยู่ในหมวด HUD วาดมือ
    • แทนที่จะลงสีทุกองค์ประกอบด้วยตัวเองทั้งหมด มีการใช้เอฟเฟกต์เลเยอร์และการ compositing ของ Affinity Photo อย่างมาก
    • เอฟเฟกต์ที่ใช้มีทั้ง emboss เพื่อให้พื้นผิวแบนดูเป็น 3D, การสร้าง noise และ overlay เพื่อให้ดูหยาบ, color overlay, blending mode, และเอฟเฟกต์ glow
    • เพราะองค์ประกอบ HUD ต้องถูกแก้ไขซ้ำบ่อย ความสะดวกในการจัดวางใหม่แบบอิงเลเยอร์จึงสำคัญด้วย
    • โดยทั่วไปจะเริ่มทำงานในโหมด truecolor ใน Affinity Photo ก่อน และองค์ประกอบจำนวนมากเป็นเพียงสี่เหลี่ยมสีล้วนที่ใส่เอฟเฟกต์พิเศษและ blending ลงไป
    • ภาพที่ส่งออกจาก Affinity Photo มีอาร์ติแฟกต์แปลก ๆ ที่ดูเหมือนเกี่ยวกับ anti-aliasing และไม่สามารถปิดได้อย่างเสถียร
    • จึงไม่เหมาะกับงานที่ต้องการความแม่นยำระดับพิกเซล ทำให้ต้องไปทำงานเพิ่มใน Aseprite เช่น ข้อความแบบ pixel-perfect, การตัดแยกชิ้นงาน, และการเก็บขอบให้คมชัดขึ้น
  • เท็กซ์เจอร์ที่สร้างเชิงกระบวนการ

    • เท็กซ์เจอร์บางแบบเรียบง่ายหรือเฉพาะเจาะจงพอที่จะวาดตรง ๆ ได้ แต่เท็กซ์เจอร์จำนวนมากใช้วัสดุพื้นฐานร่วมกันแล้วต่างกันที่ร่องรอยสึกหรอ ฝุ่น และรายละเอียดพื้นผิว
    • หากต้องวาดทุกเวอร์ชันด้วยมือจะน่าเบื่อและความสม่ำเสมอก็ลดลง จึงสร้างด้วยสคริปต์ Python
    • ไปป์ไลน์การสร้างรับอินพุตเป็น heightmap ที่กำหนด relief ของพื้นผิว, noise map สำหรับความแปรผัน, grime map สำหรับฝุ่นและคราบสึกหรอ, สีฐานสองสี, และ brightmap
    • heightmap ถูกใช้จริงเพื่อสร้าง normal map และ normal map จะถูกใช้เพื่ออบแสงและเงาแบบง่าย
    • brightmap ระบุส่วนที่ต้องคงสีไว้ไม่ว่าพารามิเตอร์อื่นจะเป็นอย่างไร
    • สคริปต์จะสร้างเท็กซ์เจอร์สุดท้ายและทำ palette quantization ให้พร้อมใช้ในเอนจินได้ทันที
    • การแก้ไขเท็กซ์เจอร์จึงกลายเป็นการปรับพารามิเตอร์แทนการวาดพิกเซลใหม่ทั้งหมด ซึ่งช่วยประหยัดเวลาได้มากสำหรับการพัฒนาแบบทำคนเดียว

gibs และเอฟเฟกต์พรีเรนเดอร์

  • Gibs

    • เมื่อศัตรูได้รับความเสียหายหนักเกินไป เช่น shotgun blast ระยะประชิดหรือการระเบิด มักจะเกิด gibbing
    • เพื่อถ่ายทอดแรงกระแทกของความเสียหายรุนแรง จะใช้แอนิเมชันที่ศัตรูแตกกระจายเป็นชิ้นส่วนเปื้อนเลือด
    • ไปป์ไลน์นี้ขับเคลื่อนโดยสคริปต์ Python ซึ่งรับสไปรต์ พาเลต และชุดพารามิเตอร์ แล้วสร้างเฟรมแอนิเมชันสำหรับข้อมูลเกม
    • ขั้นแรกที่เรียกว่า Voronoi decomposition จะสุ่มเลือกพิกเซล seed จำนวน K จุดจากร่างทึบของสไปรต์ แล้วกำหนดให้ทุกพิกเซลสังกัด seed ที่ใกล้ที่สุด
    • แต่ละ cell ที่ได้จะกลายเป็นชิ้นส่วนที่ปลิวออกไปหนึ่งชิ้น
    • ขั้นที่สอง wound bleeding จะทำเครื่องหมายพิกเซลตามขอบที่ติดกับชิ้นส่วนอื่นเป็นบาดแผลที่มีความลึก 0 แล้วใช้ BFS กระจายเข้าด้านในพร้อมกำหนดค่าความลึก
    • ระหว่างเรนเดอร์ พิกเซลใกล้ขอบจะถูกผสมไปทางสีเลือดจาก ramp ที่อนุมานจากพาเลตของเกม และยิ่งเข้าไปด้านในของชิ้นส่วนก็จะรักษาสีเดิมของสไปรต์ไว้มากขึ้น
    • การเลือก palette ramp ถูกทำให้ปรับพารามิเตอร์ได้ ดังนั้น “เลือด” สีเขียวหรือน้ำเงินสำหรับศัตรูบางประเภทก็ทำได้
    • ขั้นที่สาม physics จะกำหนดให้แต่ละชิ้นมีจุดศูนย์กลาง ความเร็วกระจายแบบสุ่มที่พุ่งออกจากศูนย์กลางของสไปรต์ ความเร็วการหมุน แรงโน้มถ่วง และ drag
    • แม้จะไม่มีการตรวจจับการชน แต่ชิ้นส่วนจะหยุดเมื่อกระทบพื้น ซึ่งแม้จะหยาบแต่ก็ให้ผลที่ดีพอ
    • จำนวนชิ้น แรงระเบิด แรงโน้มถ่วง drag การกระจาย และความลึกของบาดแผล สามารถปรับได้ด้วยพารามิเตอร์
    • ต้องลองผิดลองถูกเล็กน้อยเพื่อหา seed ที่ดูดี แต่ก็ยังเร็วกว่าการวาดแอนิเมชันด้วยมือ
    • เทคนิคเดียวกันนี้ยังใช้กับวัตถุฉากที่ทำลายได้ เช่น กระถาง ถัง และลัง
    • เช่นเดียวกับแอนิเมชันพรีเรนเดอร์ ผลลัพธ์ของ gibs ก็ไม่ถูกเก็บในรีโพ แต่จะถูกสร้างใหม่หลัง checkout และเวลาในการรันนั้นน้อยมากจนมองข้ามได้
  • ระบบพาร์ติเคิลแบบพรีเรนเดอร์

    • เอฟเฟกต์พาร์ติเคิลส่วนใหญ่ถูกวาดมือใน Aseprite แต่บางส่วนถูกสร้างและอบด้วยแนวทางเดียวกับ gibs
    • สคริปต์ Python จะรันการจำลองเพื่อสร้างลำดับเฟรม PNG แล้วจึง quantize เป็น TEX
    • ไม่มีระบบพาร์ติเคิลขณะรันจริง โดยทุกเอฟเฟกต์จะถูกอบล่วงหน้าเพื่อให้ซอฟต์แวร์ rasterizer เรนเดอร์ได้เร็วที่สุด
    • คำว่า “particle” ในที่นี้อาจทำให้เข้าใจผิดเล็กน้อย เพราะในความเป็นจริงไม่ได้จำลองอนุภาคเป็นเม็ด ๆ
    • แต่ละเฟรมจะคำนวณ radial energy field ต่อพิกเซล แล้วรวมหลายเลเยอร์อิสระเข้าด้วยกัน
    • core คือแผ่นวงกลมเนียน ๆ ที่ขยายออกด้านนอกตลอดช่วงแอนิเมชัน
    • rays คือแฉกแสงแหลม ๆ รอบ core ซึ่งสามารถตั้งค่า sharpness และ length ได้ และแต่ละ ray ยังมีการแกว่งของความยาวจาก RNG เพื่อให้ดูไม่สม่ำเสมอ
    • ring คือ shockwave แบบขยายที่เลือกเปิดใช้ได้ ส่วน noise จะคูณพลังงานรวมด้วย value noise เพื่อให้รูปร่างที่สะอาดเกินไปดูหยาบและไม่สม่ำเสมอมากขึ้น
    • พลังงานสะสมต่อพิกเซลจะถูก quantize ให้เข้ากับ palette ramp ที่กำหนดผ่านพารามิเตอร์ของสคริปต์
    • จากการออกแบบพาเลต แต่ละแถวถูกมองเป็นกราเดียนต์จากสว่างไปมืด ดังนั้นจึงทำให้พิกเซลมืดลงได้ด้วยเพียงเลขคณิตบนดัชนีพาเลต โดยไม่ต้องคำนวณ blending หรือ alpha
    • ที่ระดับเกิน threshold บางค่า พิกเซลจะถูกดันไปทางขาวมากขึ้นเพื่อให้ความรู้สึกเหมือนแกนกลางร้อนขาว
    • สามารถโปรย sparkle ขนาดเล็กเพิ่มทับด้านบนได้ โดยรูปกากบาทเหล่านี้จะเคลื่อนออกด้านนอกและค่อย ๆ จางหายภายในช่วงอายุของมัน
    • แอนิเมชันรองรับทั้งโหมด one-shot ที่ขยายแล้วหายไป เช่น explosion หรือ teleport flash และโหมด loop ที่เฟรมแรกกับเฟรมสุดท้ายต่อกันได้อย่างไร้รอยต่อ
    • โหมด loop มีประโยชน์กับเอฟเฟกต์ที่เล่นซ้ำต่อเนื่อง เช่น plasma bolts และ energy projectiles

แมปเอดิเตอร์และระบบนิเวศของเครื่องมือ

  • เดิมการแก้ไขแมปเริ่มจาก Tiled ซึ่งโดยทั่วไปก็เป็นเครื่องมือที่สมเหตุสมผล แต่ขาดความสามารถเฉพาะที่เกมนี้ต้องการ
  • Tiled ไม่มีแนวคิดอย่างการระบาย light level รายเซลล์, cell flags, หรือคุณสมบัติเฉพาะของเกม ทำให้ช่วงแรกต้องอาศัย object properties แบบฝืน ๆ เพื่อแก้ปัญหา
  • ยังต้องมีสคริปต์ Python เพื่อแปลง JSON output ของ Tiled ให้เป็นฟอร์แมตไบนารีที่เอนจินใช้ ซึ่งเป็นองค์ประกอบเพิ่มเติมเพื่ออุดช่องว่างระหว่างเครื่องมือกับความต้องการของเกม
  • ถ้าผู้เล่นต้องติดตั้ง Tiled เรียนรู้อินเทอร์เฟซ และตั้งค่าสคริปต์แปลงเพื่อสร้างแมป ภาระนี้ก็หนักพอที่จะทำให้เอดิเตอร์แทบไม่มีโอกาสถูกใช้งานจริง
  • เอดิเตอร์ที่สร้างเองรองรับ light level painting, cell flags และ entity กับชนิด property ทุกอย่างที่เกมรู้จักได้โดยตรง
  • เมื่อเกมวางจำหน่าย ผู้เล่นก็จะได้รับเอดิเตอร์ตัวเดียวกับที่ใช้ในการพัฒนา
  • เอดิเตอร์เป็นแบบ plug and play และสามารถรันเลเวลได้จากในเอดิเตอร์โดยตรง
  • ผู้พัฒนาทราบดีว่าไอคอนบน toolbar ดูแย่มาก และนั่นก็เป็นเหตุผลที่คงมันไว้แบบนั้น
  • เอดิเตอร์สร้างด้วย wxPython ซึ่งเหมาะกว่าทั้งในด้าน widget, event handling และ layout เมื่อเทียบกับ tkinter
  • ผลลัพธ์จาก wxPython ดูเป็น native มากกว่า และช่วยให้การทำซ้ำทำได้รวดเร็ว
  • โครงสร้างที่ยึดตามแพตเทิร์น MVP ช่วยแยกตรรกะ UI ออกจากข้อมูลแมปได้อย่างสะอาด ซึ่งสำคัญมากเพราะฟอร์แมตแมปยังไม่เสถียรและทั้งสองฝั่งเปลี่ยนบ่อย
  • ไม่ใช่ทุกส่วนของเอดิเตอร์จะเขียนด้วย Python โดยหลายส่วนของ model พึ่งพาไลบรารี pybast
  • pybast คือ Python binding ของภายในเอนจินผ่าน pybind ซึ่งให้ความสามารถด้านการอ่าน game data archive, การอ่าน game textures, fixed point class สำหรับพิกัด entity และ serialization
  • นี่เป็นการเลือกเพื่อหลีกเลี่ยงการเขียนสิ่งที่มีอยู่แล้วใน C++ ซ้ำใน Python และทำให้เอนจินกับเครื่องมือกลายเป็นระบบนิเวศขนาดเล็กที่เชื่อมกันแน่น

แผนวางจำหน่ายและวิธีเผยแพร่

  • คาดว่า Catlantean 3D จะเปิดตัวภายในไตรมาส 1 ปี 2027
  • ปัจจุบันโฟกัสอยู่ที่การออกแบบเลเวล การเพิ่มศัตรูและอาวุธ และงาน polish ที่ยังดำเนินอยู่
  • ตั้งเป้าราคาไว้ราว 5–8 ดอลลาร์
  • มีแผนจะเปิดซอร์สโค้ดของเกมเป็นโอเพนซอร์สบน GitHub
  • ส่วน data archive จริงที่มีกราฟิก เลเวล เสียง และดนตรี จะได้รับเมื่อซื้อเกมเท่านั้น
  • ความโปร่งใสของกระบวนการถูกมองว่าเป็นหนึ่งในไม่กี่ปัจจัยที่ช่วยสร้างความเชื่อมั่นอย่างต่อเนื่อง
  • เกมอินดี้ต่างจากเกม AAA ตรงที่พึ่งพาผู้ชมกลุ่มเล็กกว่า แต่ผู้ชมกลุ่มนั้นก็มักเต็มใจจะติดตาม สนับสนุน และบอกต่อมากกว่า
  • การแสดงให้เห็นกระบวนการทำงานถูกเสนอว่าเป็นวิธีที่ซื่อสัตย์ที่สุดในการบอกว่าผู้สร้างใส่ใจกับสิ่งที่กำลังทำอยู่จริง ๆ

1 ความคิดเห็น

 
GN⁺ 4 시간 전
ความคิดเห็นจาก Hacker News
  • ถ้าอยากลองเล่นกับ software rendering มีตัวอย่างโค้ดที่ใกล้เคียงกับโค้ดสั้นที่สุดสำหรับการแสดงอาร์เรย์ ARGB8888 แบบ 2D ในหน่วยความจำหลักขึ้นหน้าจออย่างมีประสิทธิภาพบนทุกแพลตฟอร์มด้วย SDL2 และ C: https://gist.github.com/CoryBloyd/6725bb78323bb1157ff8d4175d...
    ส่วนการแปลงเฟรมบัฟเฟอร์พาเลต 320x200x8 บิตให้เป็น ARGB ต้องทำเอง ;)
    ถ้าอยากหาแรงบันดาลใจว่าทำอะไรกับเฟรมบัฟเฟอร์พาเลตได้บ้าง ลองกด Show Options ที่ http://www.effectgames.com/demos/canvascycle/ หรือดูบรรยาย GDC ของศิลปินคนนั้นที่ https://youtu.be/aMcJ1Jvtef0
    จากนั้นถ้าอยากได้อารมณ์แบบ Deluxe Paint IIe คลาสสิกก็เปิด https://github.com/mriale/PyDPainter ได้เลย หรือถ้าอยากได้เครื่องมือที่ทันสมัยขึ้นหน่อยก็ใช้ https://www.aseprite.org/

    • อย่างน้อยใน SDL3 ก็ไม่ต้องใช้ renderer หรือ texture อีกต่อไปแล้ว แค่เอา surface มาด้วย SDL_GetWindowSurface แล้วแสดงด้วย SDL_UpdateWindowSurface ก็พอ
      เท่าที่ผมเข้าใจไลบรารีนี้ นี่เป็นวิธีที่ใกล้เคียงกับซอฟต์แวร์กราฟิกที่สุด และ SDL ก็ยังจัดการ double buffering ให้เหมือนเดิม

    • แน่นอนว่านี่เป็นวิธีพื้นฐานที่สุด ถ้าอยากทำ optimization เล็ก ๆ ในลูปด้านใน ก็แค่คำนวณ offset ของ scanline ไว้ล่วงหน้าก่อนเข้าลูปพิกเซล:
      int s = y*screenRect.w;

      for (int x = 0; x < screenRect.w; x++) {
      pixels[s + x] = argb(255, frame>>3, y+frame, x+frame);
      }

    • ขอบคุณที่แชร์ ถึงจะมี Quake fork ยอดนิยมอยู่หลายตัวแล้ว แต่ Planimeter ก็กำลังแจกจ่าย fork ของ Quake-VS2026 ที่ไม่ใส่การเปลี่ยนแปลงเพิ่มเติม
      ทีมกำลังทำบิลด์ x64 ซึ่งต้องแทนที่ SciTech Multi-platform Graphics Library แบบเก่า (รองรับเฉพาะ x86) ด้วย SDL3 ไม่อย่างนั้นก็ต้องพอร์ต scitech-mgl ไป x64 ซึ่งดูแล้วคงเป็นไปได้ยาก และเท่าที่ทราบล่าสุด software renderer อาจจะถูกตัดออกไปด้วย
      แต่บางทีก็อาจเก็บไว้ได้ด้วย software renderer และ SDL_Texture

  • บทความนี้ได้รับแรงบันดาลใจจาก Doom มากก็จริง แต่จริง ๆ แล้ว ray casting engine ใกล้เคียงกับเกมก่อนหน้า Doom มากกว่า โดยเฉพาะ Wolfenstein 3D ที่ดังที่สุด
    มันใช้กำแพงแนวตั้ง และพื้นกับเพดานที่มีความสูงคงที่ Wolf3D ไม่มีพื้นและเพดานแบบมี texture เพราะข้อจำกัดด้านประสิทธิภาพ แต่เกมอื่นที่คล้ายกันบางเกมก็มี
    ถ้าจำไม่ผิด Doom และ Duke Nukem ก็ใช้ BSP engine ที่ยืดหยุ่นกว่ามาก ซึ่งให้กำแพงตัดกันได้ในมุมใดก็ได้ และเปลี่ยนความสูงของพื้น/เพดานได้ แต่ด่านก็ยังคงเป็นแบบ “แบน” อยู่ จึงทำหลายชั้นในด่านเดียวกันไม่ได้ เช่น ออกแบบสะพานที่เดินได้ทั้งด้านบนและด้านล่างพร้อมกันไม่ได้

    • Build engine ไม่ได้ใช้ BSP แต่มองการเชื่อมต่อระหว่าง sector เป็น portal แล้ว clip ตาม portal นั้น พร้อม rasterize กำแพงเป็นรูปสี่เหลี่ยมคางหมูที่หมุน 90 องศา
      เพราะแบบนี้จึงรองรับเรขาคณิตกำแพงแบบไดนามิกได้ เช่น รถไฟที่เคลื่อนที่หรือแสงที่หมุน และยังทำโครงสร้างแบบ “ห้องเหนือห้อง” ได้ตราบใดที่มองเห็นสองห้องพร้อมกันไม่ได้
      ใน Blood และ Shadow Warrior ยังมีการใช้วิธีอ้อมเพื่อทำให้พื้นที่ดู “3D” มากขึ้น โดยสร้าง sector รูปร่างเดียวกันแล้วใช้พื้นของ sector หนึ่งเป็นเหมือน portal ที่เชื่อมไปยังเพดานของอีก sector หนึ่ง
      มันไม่ใช่ฟีเจอร์ที่เอนจินรองรับโดยตรงแต่แรก แต่ก็ยืดหยุ่นพอที่สตูดิโอซึ่งไม่มีสิทธิ์เข้าถึงซอร์สยังทำเองได้
      ด่านแรกของ Duke Nukem 3D ก็ใช้ Build trick หลายอย่าง เช่น sprite สามารถตั้งให้ไม่หมุนตามกล้องและมี collision ได้ ดังนั้นถ้ามองแต่ละ sprite เป็นสี่เหลี่ยมที่จัดแนวตามแกน ก็สามารถสร้างเรขาคณิต 3D แบบพื้นฐานได้ ในด่านแรกมันถูกใช้ทำสะพานระหว่างตึกสองหลังตรงก่อนถึงปุ่มทางออก

    • Blake Stone และ Rise of the Triad ใช้ Wolf3D engine เวอร์ชันช่วงท้าย และมี พื้นกับเพดานแบบมี texture
      ส่วน Build engine ของ Duke Nukem ไม่ได้ใช้ BSP

      https://www.jonof.id.au/forum/topic-137.html#msg1548

    • ดูเหมือนว่าใน Shadow Warrior ภายหลังก็ทำแบบนั้นได้เหมือนกัน น่าจะจำได้ว่าใช้ portal ทำ และตั้งค่าใน editor ค่อนข้างทรมาน

    • เรื่องพื้นนั้น เท่าที่รู้ แม้แต่ DOOM เองก็ไม่ได้จัดการแบบแม่นตรงนัก ในกรณีกำแพงแนวตั้ง คุณต้องทำ perspective divide แค่ครั้งเดียวต่อคอลัมน์พิกเซลสำหรับชิ้นกำแพงนั้น
      แต่กับพื้นมันไม่มีความหรูแบบนั้น น่าเสียดายที่ถ้าจำไม่ผิด DOOM จะแบ่งพื้นออกเป็น patch แล้วคำนวณ perspective ที่ถูกต้องเฉพาะตรงมุม จากนั้นค่อย interpolate ตรงกลาง

    • ตอนแรกผมนึกว่ามันก็แค่ Wolfenstein 3D ที่เปลี่ยนสกินเท่านั้น ซึ่งเป็นการตัดสินที่ไม่ยุติธรรมเอามาก ๆ เพราะงานที่ใส่ลงไปในนี้มีเยอะจริง ๆ

  • เป็นบทความที่ยอดเยี่ยมมาก โดยเฉพาะแนวทางในการทำ gib animation ที่น่าสนใจมาก
    แม้จะเป็นเดโมทางเทคนิค แต่ราวกลางยุค 90 ผมก็เคยทำอะไรคล้าย ๆ กันอยู่เหมือนกัน จุดหนึ่งที่ไม่เห็นในบทความนี้คือ เราใช้ lightmap ขนาด 8x8 หรือ 16x16 กับ texture เพื่อทำเอฟเฟ็กต์อย่างคบเพลิงที่กะพริบ หรือจรวดที่บินไปตามทางเดินพร้อมส่องแสงได้อย่างง่ายดาย ถ้าต้องการ ก็ใช้ lightmap เพื่อ “อบ” แสงเข้าไปได้ด้วย
    เพราะ lightmap มีขนาดแค่ 8x8 “เท่านั้น” จึงยังพอรับมือกับคณิตศาสตร์ระดับคำนวณระยะถึงแหล่งกำเนิดแสงและเส้นการมองเห็นของแต่ละ luxel หรือแต่ละหน่วยใน lightmap เพื่อหาค่าความสว่างได้ ตอนเรนเดอร์ texture ก็ใช้ luxel ร่วมกับตาราง lookup เพื่อตัดสินค่าสีของพิกเซลที่จะวาดจริง
    เพื่อประสิทธิภาพ เท่าที่จำได้เราจะอัปเดต lightmap 15 ครั้งต่อวินาที สำหรับการเรนเดอร์นั้นใช้ inline assembly ด้วยอานิสงส์ของ DJGPP และเพราะการคำนวณ floating point ในยุคนั้นช้า เราจึงใช้ fixed-point arithmetic ที่ปรับแต่งประสิทธิภาพได้ดีมาก ประสิทธิภาพการเรนเดอร์ตามมาตรฐานคอมพิวเตอร์ในสมัยนั้นน่าทึ่งจริง ๆ

    • แนวคิดเรื่อง fixed-point นี่เหมือนถูกใช้น้อยเกินไปและประเมินค่าต่ำเกินไปมาก ๆ มีหลายด้านที่มันเป็นตัวเลือกที่ดีกว่า และบางครั้งยังเร็วกว่าอีกด้วย
  • การเขียนโปรแกรมกราฟิก ในช่วงต้นถึงกลางยุค 1990 สนุกมากทีเดียว แค่เขียนข้อมูลพิกเซลลงไปใน video RAM ที่แมปไว้กับหน่วยความจำ มันก็แสดงขึ้นจอบนหน้าจอทันที
    มีแค่ pointer ที่ชี้ไปยัง 0xA0000 ก็พอแล้ว ไม่ต้องมี API อะไรเลย เหตุผลของโหมด VGA 320×200 ที่พิกเซลไม่เป็นสี่เหลี่ยมจัตุรัสตามที่กล่าวถึง ก็เพราะ video buffer มีขนาด 64000 ไบต์ ซึ่งพอดีอยู่ในเซกเมนต์ 16 บิต ทำให้โค้ด 16 บิตและ CPU ระบุที่อยู่ได้ง่าย

    • ผมชอบเสมอที่ว่า เมื่อเทียบกับคอนโซลแล้ว PC ในสมัยนั้นมี CPU ระดับสัตว์ประหลาดแท้ ๆ แต่กลับต้องลำบากในการทำ smooth scrolling แบบ Mario บน NES ปี 1985 เพราะโครงสร้างกราฟิกของมัน
      แต่เพราะจุดอ่อนนั้นเอง มันจึงทำงานต่อหนึ่งพิกเซลบนหน้าจอได้มากกว่ามาก และนั่นทำให้ระบบ ray casting หรือ BSP tree แบบนี้เป็นไปได้
      มันไม่มีโปรเซสเซอร์เฉพาะสำหรับ sprite และ background layer แต่ในทางกลับกัน ความสามารถของ PC ก็ไม่ถูกขังอยู่กับสถาปัตยกรรม fixed-function ที่แข็งทื่อ
      พอมีโปรเซสเซอร์ 3D เฉพาะทางออกมาในช่วงกลางถึงปลายยุค 90 มันก็ไม่ใช่ปัญหาอีกต่อไป แต่ในช่วงสั้น ๆ ต้นยุค 90 มันเคยเป็นสนามเล่นของการเรนเดอร์ภาพที่มีเอกลักษณ์มาก
    • แม้ pointer ไปที่ 0xA0000 ตัวเดียวจะพอ แต่ extender ที่ใช้ก็อาจทำให้เรื่องนั้นยุ่งยากขึ้นอีกนิดได้ :-P
      ทั้ง DJGPP และ Free Pascal ใช้ go32 extender ตัวเดียวกันของ DJ Delorie ซึ่งไม่ได้ทำ linear mapping แบบสมบูรณ์ จึงต้องจัดการเพิ่มอีกหน่อยถ้าจะให้มีอะไรขึ้นบนจอ
    • ก่อนที่ VGA จะออกมา เรื่องพวกนี้ซับซ้อนกว่านี้มาก
  • สิ่งที่น่าสนใจที่สุดคือเครื่องมือภายในพวกนี้เอง อย่าง Python script สำหรับทำ gib animation หรือ Python script อีกตัวที่สร้าง 2D spritesheet จาก Blender
    ผู้เขียนต้นฉบับดูเป็น 10x engineer ที่วาดภาพเก่งได้ด้วยอย่างชัดเจน และผมว่าคนแบบนี้หาได้ยากจริง ๆ การมี art direction ที่สอดคล้องกันก็ถือว่าน่าทึ่งมากเหมือนกัน

    • มองจากมุมของแฟนแนวนี้ในยุค 90 ดูเหมือนว่าเบื้องหลังผลงานฮิตสำคัญ ๆ จะมี วิศวกรสายเรอเนซองส์ แบบนี้อยู่เสมอ ผมยังจำบางชื่อได้อยู่ และพวกเขาเป็นศิลปินตัวจริง
      แต่ในช่วง 15 ปีที่ผ่านมาในอุตสาหกรรมเกม นอกจาก CEO หรือ lead director แล้ว ผมแทบไม่รู้ชื่อใครเลย
  • เพิ่งนึกได้ว่าเกมนี้อาจเป็นหนึ่งในเกมยิงไม่กี่เกมที่มีตัวเอกเป็นผู้หญิง เพราะแมวตัวนี้มีลาย calico ซึ่งแมวลายแบบนั้นแทบจะเป็นตัวเมียเกือบทั้งหมด (https://en.wikipedia.org/wiki/Calico_cat)

    • เกมยิงที่มีตัวเอกเป็นผู้หญิงมันหายากขนาดนั้นเลยเหรอ? แค่นึกแบบเร็ว ๆ ก็มีงานกระแสหลักพอสมควรแล้ว เช่น Perfect Dark, Mirror's Edge, Dishonored ภาค 1 หรือ 2, Metroid ซึ่งทั้งหมดก็เป็นเกมยิงในแบบใดแบบหนึ่งและมีตัวเอกเป็นผู้หญิง
      แน่นอนว่า Mirror's Edge ถ้าจะพูดให้เป๊ะ 100% ก็ใกล้กับ “มุมมองบุคคลที่หนึ่ง” มากกว่า “เกมยิง”
      แล้วในกลุ่ม “RPG + FPS” ก็ยังมีหลายเกมที่ให้เล่นเป็นผู้ชายหรือผู้หญิงได้
      ดูเหมือนผู้เขียนก็รู้เรื่องลายกับความเป็นไปได้ของเพศแมวอยู่แล้ว:

      After all, I do need to give the protagonist his fair share. [image] (Yes, I know it's a female, but call it convention rooted in dialect.)

    • นี่ไม่ใช่เกม Perfect Dark

    • ทุกวันนี้ในแนว boomer shooter มีตัวเอกหญิงค่อนข้างเยอะ เช่น Selaco[0], Supplice[1], The Citadel[2] และภาคต่อ[3], Zortch[4] และภาคต่อที่กำลังจะมา[5], Nightmare Reaper[6], COVEN[7], Viscerafest[8], Hedon[9]
      จริง ๆ แล้วเดี๋ยวนี้เหมือนเกม boomer shooter ที่มีตัวเอกหญิงจะมีมากกว่าที่ไม่มีเสียอีก :-P ถ้าค้นหาใน Steam โดยรวมแท็ก “boomer shooter” กับ “female protagonist” เข้าด้วยกัน จะได้ 143 รายการ แม้ว่าจะรวมเกมที่เลือกเพศตัวละครได้ หรือเกมที่ส่วนใหญ่เล่นเป็นผู้ชายแต่มีบางช่วงให้เล่นเป็นผู้หญิงด้วยก็ตาม

      [0] https://store.steampowered.com/app/1592280/Selaco/

      [1] https://store.steampowered.com/app/1693280/Supplice/

      [2] https://store.steampowered.com/app/1378290/The_Citadel/

      [3] https://store.steampowered.com/app/3371240/Beyond_Citadel/

      [4] https://store.steampowered.com/app/2443360/Zortch/

      [5] https://store.steampowered.com/app/3807500/Zortch_2/

[6] https://store.steampowered.com/app/1051690/Nightmare_Reaper/

[7] [https://store.steampowered.com/app/1785940/COVEN/](<https://store.steampowered.com/app/1785940/COVEN/>;)

[8] [https://store.steampowered.com/app/1406780/Viscerafest/](<https://store.steampowered.com/app/1406780/Viscerafest/>;)

[9] [https://store.steampowered.com/app/1072150/Hedon_Bloodrite/](<https://store.steampowered.com/app/1072150/Hedon_Bloodrite/>;)
  • ถึงคงไม่ได้ตั้งใจ แต่โดยรวมแล้วผมไม่ค่อยประทับใจกับอะไรแบบนั้นและก็ไม่เห็นคุณค่าด้วย เหมือนกับการพรรณนาใน Hollywood ที่ผู้หญิงล้มผู้ชายที่ตัวใหญ่กว่าตัวเองสองเท่าได้
    ผมว่ามันทั้งไม่สมจริง น่าขัน และเป็นโทษ

  • เจ๋งมาก อีกหนึ่งลูกเล่นสนุก ๆ ที่ใช้กันในยุค 90s คือ palette animation แค่เปลี่ยนพาเลตก็สร้างเอฟเฟกต์ที่โคตรเท่ได้โดยใช้ต้นทุนการประมวลผลต่ำมาก

    • ใช่เลย ถ้าอยากดูตัวอย่างเจ๋ง ๆ ของเทคนิคนี้ ขอแนะนำเว็บไซต์นี้อย่างมาก

      http://www.effectgames.com/demos/canvascycle/

    • การเปลี่ยน palette กลางเฟรมก็สนุกเหมือนกัน บน PC ไม่มีอะไรอย่าง copper ของ Amiga เลยต้องใส่ใจกับจังหวะมากกว่าเยอะ แต่ก็ยังทำได้

    • ถ้าจำไม่ผิด ศัตรูหลายตัวใน Diablo 1 และ 2 จริง ๆ แล้วคือสไปรต์ชุดเดียวกันที่แค่ลงพาเลตคนละแบบ นี่คือทริกเดียวกันไหม?

    • สีน้ำเงินคือน้ำ สีม่วงคือพลาสมา สีแดง/ส้มคือเลือดหรือลาวา

  • ผมแปลกใจมากที่ สไปรต์ที่ผ่านการ quantize หลังเรนเดอร์ออกมาดูดีขนาดนี้ การแปลงแบบเร็ว ๆ นั้นทำให้มันดูคมชัดมาก

  • ในฐานะนักพัฒนาร่วมคนหนึ่งที่กำลังสร้าง 3D engine ภายใต้ข้อจำกัดที่โหดเกินเหตุ ผมชอบมากที่ได้เห็นรายละเอียดของคำอธิบายและขั้นตอนที่ผ่านมาทั้งหมดตรงนี้

  • ผมกำลังลองทำเทคเดโมของเทคนิค voxel space rendering สำหรับ PlayStation homebrew อยู่ หลังจากทำเล่น ๆ แค่วันสองวันช่วงสุดสัปดาห์ก็ได้ผลลัพธ์ราว 10~15 FPS ซึ่งถือว่าโอเค และยังไม่ได้ใช้ทั้ง DMA หรือ GTE รวมถึง primitive แบบ polyline เลย
    การได้หยิบตรีโกณมิติและเคล็ดลับการ optimize ระดับล่างแบบสมัยก่อนกลับมาใช้อีกครั้งเป็นอะไรที่สดใหม่ดี ตอนที่ scratch buffer มีแค่ 1KiB และ stack ก็ใช้ได้แค่บางส่วนของมัน คุณจะตระหนักเลยว่าไมโครคอนโทรลเลอร์ที่ใช้ในที่ทำงานนั้นหรูหราแค่ไหน เพราะที่นั่นมี stack ให้ thread ละ 8KiB และยังมี backtrace ที่ซ้อนฟังก์ชันเทมเพลต C++ เกิน 50 ชั้นได้อีก