1 คะแนน โดย GN⁺ 2024-05-09 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • Machine ของ xkcd คือเกมเครื่องลูกแก้วแบบ Rube Goldberg ขนาดยักษ์ที่ประกอบจากไทล์อุปกรณ์ที่ผู้อ่านสร้างขึ้น โดยนำไอเดียมาทำเป็นการ์ตูนอินเทอร์แอ็กทีฟจริงภายใน 3 สัปดาห์
  • ประสบการณ์จากโปรเจกต์แบบมีส่วนร่วมของผู้ใช้ก่อนหน้านี้นำไปสู่หลักเกณฑ์การออกแบบว่า หากแคนวาสร่วมกันจะทำงานได้ดี ต้องมี บริบทร่วมและเป้าหมายร่วม
  • เพื่อรักษาความสามารถในการแสดงออกของผู้เล่น แต่ยังคงความเข้ากันได้ของไทล์ จึงกำหนดข้อจำกัดด้านอินพุตและเอาต์พุตอย่างเข้มงวด และจำกัดให้อุปกรณ์แต่ละชิ้นต้องเข้าสู่ สภาวะเสถียรภายใน 30 วินาที
  • แทนที่จะจำลองทั้งเครื่องทั้งหมดแบบเรียลไทม์ จะใช้ Rapier เฉพาะบริเวณที่มองเห็น และทำให้ดูเหมือนอุปกรณ์กำลังทำงานอยู่แล้วด้วย สแนปช็อต ณ เวลาที่อนุมัติ
  • ใช้ React และการเรนเดอร์ด้วย DOM, แบ็กเอนด์ Haskell, Redis, OpenAPI, TanStack Query และ UI สำหรับม็อดเดอเรชัน มาร่วมกันจัดการขั้นตอนการอนุมัติและเผยแพร่ผลงานส่งเข้าระบบ

จุดเริ่มต้นของ Machine

  • xkcd เปิดตัว Machine เมื่อวันที่ 5 เมษายน
  • Machine คือเครื่องมือสร้าง Rube Goldberg machine ขนาดใหญ่ในสไตล์เกมคลาสสิก The Incredible Machine
  • เครื่องทั้งหมดประกอบขึ้นจากการต่อกันของไทล์อุปกรณ์ขนาดเล็กที่ผู้อ่าน xkcd แต่ละคนสร้างไว้
  • ทีมสร้าง Machine ขึ้นภายใน 3 สัปดาห์ และไอเดียเริ่มต้นมาจาก GIF แบบร่วมมือกันในปี 2005 ชื่อ Blue Ball Machine
  • คำถามหลักในการระดมไอเดียช่วงแรกคือ ลูกแก้วมาจากไหน เครื่องที่ทุกคนเห็นเป็นเครื่องเดียวกันอย่างไร เป้าหมายของเครื่องคืออะไร ผู้เล่นจะโต้ตอบกันอย่างไร และอะไรคือแรงจูงใจในการเข้าร่วม

บทเรียนจาก xkcd แบบมีส่วนร่วมของผู้ใช้

  • ในการ์ตูนอินเทอร์แอ็กทีฟ xkcd ก่อนหน้านี้ที่เน้นคอนเทนต์จากผู้ใช้ Lorenz ให้ผู้อ่านเขียนข้อความในแต่ละพาเนลเพื่อพัฒนามุกและเรื่องราว ซึ่งเป็นประสบการณ์ที่ดี
  • ส่วน Collector’s Edition ในปี 2020 ให้ผู้เล่นค้นหาสติกเกอร์จากคลัง xkcd แล้วนำไปติดบนแคนวาสร่วมกันทั่วโลกได้คนละครั้ง แต่ผลลัพธ์ไม่เป็นไปอย่างที่หวัง
    • ผู้เล่นทุกคนเริ่มจากจุดกึ่งกลางของแผนที่ว่างเปล่า และไม่นานหน้าจอก็กลายเป็นภาพที่ชวนสับสนตั้งแต่แรกเห็น
    • แรงจูงใจในการเลือกตำแหน่งติดสติกเกอร์อย่างรอบคอบมีน้อย และยากที่จะทำให้เนื้อเรื่องคืบหน้าด้วยการกระทำของแต่ละคนเพียงลำพัง
    • เพราะไม่มีเรื่องเล่าหรือเป้าหมายร่วมกัน จึงไม่ชัดเจนว่าสติกเกอร์แต่ละชิ้นเชื่อมโยงกับองค์ประกอบอื่นของหน้าอย่างไร
  • ถ้าจะแคนวาสร่วมกันให้ทำงานได้ดี ผู้ใช้ต้องสามารถ เรียนรู้จากตัวอย่าง ว่าควรสร้างอะไรถึงจะออกมาดูน่าสนใจ
  • หากต้องการให้ผลลัพธ์เชิงสร้างสรรค์ไปในทิศทางเดียวกัน จำเป็นต้องมี บริบทร่วมและเป้าหมายร่วม ที่ช่วยซิงก์ว่าควรสร้างอะไร

การออกแบบข้อจำกัด: การแสดงออก ความเข้ากันได้ และสภาวะเสถียรใน 30 วินาที

  • แม้จะตัดสินใจทำอุปกรณ์ลูกแก้วแบบร่วมมือกันขนาดใหญ่แล้ว ก็ยังเหลือปัญหาเรื่องขนาดเครื่องทั้งหมด วิธีจำลอง และวิธีรวมไทล์เข้าด้วยกัน
  • หากสมมติว่าเครื่องมีขนาด 100x100 เป้าหมายที่จะให้ไคลเอนต์จำลอง 10,000 ไทล์ แบบเรียลไทม์และรองรับลูกแก้วหลายสิบลูกในแต่ละไทล์ถือว่าเสี่ยงเกินไป
  • ให้ความสำคัญกับการแสดงออกมากกว่าความแม่นยำ

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

    • ในช่วงแรกมีการคิดถึงวิธีให้ผู้เล่นคนถัดไปต่อขยายได้อย่างอิสระตามตำแหน่งเอาต์พุตของไทล์ก่อนหน้า
    • แต่ถ้าจำเป็นต้องเปลี่ยนไทล์ที่วางไว้ก่อนหน้านั้นในภายหลัง พื้นที่ขนาดใหญ่ที่พึ่งพาไทล์นั้นอาจพังตามไปด้วย
    • จึงกำหนดข้อจำกัดอินพุตและเอาต์พุตอย่างเข้มงวด เพื่อให้ผู้เล่นหลายคนสามารถออกแบบสิ่งที่เข้ากันได้ภายในพื้นที่ไทล์เดียวกัน
    • แนวทางนี้สอดคล้องกับหลักการ Robustness principle ที่ว่า “สิ่งที่ส่งออกควรเข้มงวด สิ่งที่รับเข้าควรยืดหยุ่น”
    • map generator ของ Kevin เริ่มจากปริศนาแบบ 1 อินพุต 1 เอาต์พุตที่เรียบง่าย จากนั้นซับซ้อนขึ้นเป็นการรวมกันตรงกลางแบบ 4 อินพุต 4 เอาต์พุต แล้วค่อยกลับมาที่ 2 เอาต์พุตต่อไทล์ในช่วงท้าย
    • ตัวแก้ไขให้ฟีดแบ็กแบบเรียลไทม์ขณะที่ผู้เล่นสร้างไทล์
      • โดยเฉลี่ยแล้ว ไทล์ควรปล่อยลูกแก้วออกไปในอัตราใกล้เคียงกับที่รับเข้ามา
      • พยายามลดอุปกรณ์ที่กลืนลูกแก้วหายไปหรือทำให้เกิดการหน่วงอย่างมาก
      • เพื่อสะท้อนความผันผวนของอินพุตจากต้นน้ำ จึงใช้ chaos testing โดยสุ่มอัตราความเร็วของลูกแก้วที่ไหลเข้ามาในตัวแก้ไข
  • ต้องเข้าสู่สภาวะเสถียรภายใน 30 วินาที

    • เพื่อลดเวลาที่ม็อดเดอเรเตอร์ต้องเฝ้าดู จึงตั้งเกณฑ์ตามอำเภอใจว่าอุปกรณ์ต้องเข้าสู่ สภาวะเสถียรภายใน 30 วินาที
    • เกณฑ์นี้อ้างอิงจากการคำนวณว่า หากต้องดู 10,000 ไทล์ ไทล์ละ 30 วินาที เวลาม็อดเดอเรตรวมจะอยู่ที่ประมาณ 83.3 ชั่วโมง
    • ลูกแก้วก็ถูกตั้งให้หมดอายุหลัง 30 วินาทีด้วย
      • หากไม่มีการหมดอายุ ประสบการณ์แรกของผู้เล่นมือใหม่จะกลายเป็นการเห็นลูกแก้วกองสะสมเต็มหน้าจอ
      • จำนวน active rigid body ก็จะเพิ่มขึ้นจนทำให้การจำลองฟิสิกส์ช้าลงด้วย
    • การหมดอายุของลูกแก้วช่วยไม่ให้ข้อผิดพลาดสะสมตามเวลา และทำให้การเฝ้าดูเพียง 30 วินาทีก็เพียงพอที่จะเห็นตำแหน่งปลายทางของลูกแก้วส่วนใหญ่ จึงทำให้การม็อดเดอเรตง่ายขึ้น

วิธีที่ไม่รันทั้งเครื่องแบบเรียลไทม์

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

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

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

โครงสร้างการเรนเดอร์ด้วย React, DOM และ Rapier

  • Machine สร้างขึ้นบนเอนจินฟิสิกส์ Rapier
  • จุดเด่นของ Rapier คือเอกสารประกอบ, API, องค์ประกอบพื้นฐานที่มีประโยชน์ และประสิทธิภาพบนเบราว์เซอร์ผ่าน WASM จากการเขียนด้วย Rust
  • ตอนแรกก็สนใจเรื่องการรับประกันความกำหนดแน่ชัดของ Rapier เช่นกัน แต่ท้ายที่สุดไม่ได้ทำการจำลองฝั่งเซิร์ฟเวอร์
  • บน Rapier มีการเขียน React context แบบกำหนดเองชื่อ <PhysicsContext>
    • ใช้สร้างและจัดการอ็อบเจ็กต์ฟิสิกส์ของ Rapier ภายในวงจรชีวิตของคอมโพเนนต์ React
    • ทำให้พัฒนาแต่ละวัตถุที่วางได้และพื้นผิวชนต่าง ๆ ได้ง่ายในรูปแบบคอมโพเนนต์ “widget”
    • React ทำหน้าที่เหมือน scene graph แบบหยาบ ๆ ที่รวดเร็ว
    • เมื่อไทล์ถูก unmount อ็อบเจ็กต์ฟิสิกส์และ DOM ที่เกี่ยวข้องก็จะถูกเก็บกวาดไปด้วย
    • การ hot reload ผ่านการรีเฟรชอย่างรวดเร็วช่วยให้ปรับรูปทรงการชนได้ง่าย
  • มีการทำให้ฟิสิกส์ฮุกใช้งานไม่ได้หากอยู่นอก <PhysicsContext> ซึ่งนำไปใช้กับภาพพรีวิวแบบสแตติกใน UI ม็อดเดอเรชัน
  • ภายหลังมองว่าการสร้างอ็อบเจ็กต์ Rapier ในรูปคอมโพเนนต์แทนฮุกน่าจะดีกว่า
    • react-three-rapier ใช้วิธีนี้ และเข้ากับการ diff ของ React ได้ดีกว่า
    • แนวทางที่อิง useEffect จะทำให้เมื่อ dependency เปลี่ยน อินสแตนซ์เดิมถูกลบทิ้งแล้วสร้างใหม่
  • การเรนเดอร์ด้วย DOM ล้วน

    • Machine เรนเดอร์ทั้งหมดด้วย DOM
    • ช่วงแรกคิดว่าหากเจอข้อจำกัดด้านประสิทธิภาพ อาจย้ายไปใช้ PixiJS หรือ canvas ได้ แต่สุดท้ายก็ผลักแนวทาง DOM ให้สุดเพราะมีสิ่งที่ต้องสร้างน้อยกว่า
    • เพื่อประสิทธิภาพการเรนเดอร์ ลูปเฟรมจะนำสไตล์ไปใช้กับวิดเจ็ตที่อยู่ในการจำลองฟิสิกส์โดยตรง
    • React diff จะทำงานเฉพาะตอนที่โครงสร้างของ scene graph เปลี่ยนเท่านั้น
    • ตอนแรกเรนเดอร์ลูกแก้วด้วย React เช่นกัน แต่การสร้างและลบบ่อย ๆ ทำให้ต้นทุน diff สูง จึงสร้าง optimized renderer แยกต่างหาก
    • ใช้ draw culling กับลูกแก้วและวิดเจ็ตที่อยู่นอกหน้าจอ
    • วิธีนี้ทำงานได้ดีทั้งกับลูกแก้วที่กำลังถูกจำลอง 4,000 ลูก และลูกแก้วหลายร้อยลูกบนหน้าจอ จึงสรุปให้ใช้การเรนเดอร์ด้วย DOM ล้วน

API, ม็อดเดอเรชัน และการจัดการผลงานส่งเข้า

  • แบ็กเอนด์เขียนด้วย Haskell โดย davean และ Kevin และใช้ Redis เป็นสตอเรจ
  • การแชร์ type ระหว่างโค้ดเบสใช้ OpenAPI และ OpenAPI fetch
    • ช่วงแรกมีความไม่สะดวกอยู่บ้างในการทำให้ตรงกับ Haskell type
    • แต่ก็ช่วยมากในการประสานการเปลี่ยนแปลง API ช่วงท้ายโครงการ
  • TanStack Query มีประโยชน์ในการจัดการแคชและการรีเฟรชอัตโนมัติโดยไม่ต้องมี server push
  • UI ม็อดเดอเรชันและลำดับความสำคัญ

    • UI ม็อดเดอเรชันที่ Ed White ออกแบบคือคอขวดที่ผลงานส่งเข้าทั้งหมดต้องผ่านก่อนจะเผยแพร่สู่สาธารณะ
    • ม็อดเดอเรเตอร์อาจต้องเลือกจากดีไซน์ผู้สมัครหลายร้อยแบบสำหรับไทล์หนึ่ง ๆ
    • ลำดับความสำคัญของคิวกำหนดด้วย interestingness score แยกตามชนิดวิดเจ็ต แล้วนับจำนวนแต่ละอินสแตนซ์เพื่อนำมาจัดเรียงไทล์ผู้สมัคร
    • วิธีนี้มีแนวโน้มเอนเอียงไปทางคำตอบที่ใส่องค์ประกอบจำนวนมาก แต่ม็อดเดอเรเตอร์ก็ช่วยถ่วงดุลด้วยการตรวจดูช่วงกลางของรายการเพื่อหาแบบที่มินิมัลกว่านั้น
    • ความไม่สมดุลอย่างมากระหว่างจำนวนดีไซน์ที่ถูกส่งเข้ามา กับจำนวนดีไซน์ที่ถูกเผยแพร่ในเครื่องจริง ยังคงเป็นจุดที่น่าเสียดาย
    • ก่อนเปิดตัวมีการพยายามหาวิธีเปิดเผย backlog ให้มากขึ้น แต่ไม่พบจุดลงตัวที่ดีภายใต้ข้อจำกัดด้านเวลาม็อดเดอเรชัน
    • หลังจากการส่งผลงานสดสิ้นสุดลง ก็อยากหาวิธีแบ่งปันชุดข้อมูลผลงานส่งเข้ามากขึ้น
  • คูลดาวน์การอนุมัติและการเร่งความเร็ว

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

ปฏิสัมพันธ์ระหว่างไทล์ที่ไม่ได้ตั้งใจ

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

โค้ดและการทดลองที่ยังเหลืออยู่

  • ดูซอร์สโค้ดของ Machine ได้ที่ GitHub repository
  • การทำ implementation ที่จำลองทั้งเครื่องแบบสมบูรณ์ในระดับ global ยังคงเป็นโจทย์แฮ็กที่น่าสนใจ
  • ลิงก์สำหรับเพิ่มดีไซน์เข้าไปใน Machine โดยตรงอยู่ที่ xkcd 2916

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

 
GN⁺ 2024-05-09
ความคิดเห็นบน Hacker News
  • สิ่งที่ตลกสำหรับผมตอนอ่านบทความนี้คือ ตอนนั้นผมไม่รู้เลยว่ากำลังเกิดเรื่องแบบนี้อยู่
    ดูเหมือนไม่มีคำอธิบายว่ามันคือสถานการณ์อะไร ไม่รู้ด้วยว่านี่เป็นประสบการณ์ที่ทุกคนทำร่วมกัน และรู้สึกแค่ว่ามีเรื่องสุ่ม ๆ หลายอย่างเกิดขึ้นอย่างสับสน
    ผมทำไทล์เสร็จไปสองสามอันแล้วส่งไป คิดว่านั่นคือวิธีไป “ด่านถัดไป” เลยตั้งชื่อโง่ ๆ อย่าง “test 1b” เพราะคิดว่าเป็น โหมดเล่นคนเดียว และชื่อมีแค่ผมที่เห็น
    ทำไปไม่กี่อันก็เบื่อ แล้วเดินดูไปเรื่อย ๆ เห็นของซับซ้อนหลายอย่าง แต่ไม่รู้ว่านั่นเป็นงานที่ส่งเข้ามา คิดว่าเป็นแค่จุดเริ่มต้นสำหรับแก้เลเวล สุดท้ายก็เท่ากับว่าผมโดน มุกวัน April Fools’ หลอกเข้าให้

    • ผมยังไม่รู้ด้วยซ้ำว่ามันโต้ตอบได้ แค่ดูแล้วคิดว่า “เจ๋งดี”
    • ควรมี การชี้นำให้ลงมือทำ เช่น แสดงตัวอย่างที่แก้ไขได้ตั้งแต่แรก หรือไม่ก็แสดงผลลัพธ์สุดท้ายก่อน แล้วโฟกัสไปที่ช่องว่าง
    • เผื่อใครสนใจ ตอนนี้ยังรับผลงานส่งอยู่นะ
    • ผมหนักกว่านั้นอีก ลองเล่นประมาณ 2 นาทีแล้วไม่เข้าใจเลยว่าเกิดอะไรขึ้น เลยเลิก
      อาจเป็นเพราะไม่เคยเล่นเกมเครื่องจักรต้นฉบับที่เป็นแรงบันดาลใจมาก่อนก็ได้ :-)
    • คราวหน้าคงดีถ้าลง บทความอธิบาย ก่อนเปิดให้เล่น
  • ผมเพิ่มองค์ประกอบ “bonk” เข้าไปเยอะ ๆ แล้วเหมือนจะทำให้ rapier ตายไปเลย
    Uncaught Error: recursive use of an object detected which would lead to unsafe aliasing in rust
    at jt (rapier_wasm2d_bg.js:4836:11)
    at 4ea5626ea4b1e4145572.module.wasm:0xf061c
    at 4ea5626ea4b1e4145572.module.wasm:0xf0638
    at 4ea5626ea4b1e4145572.module.wasm:0xb5e7b
    at H.remove (rapier_wasm2d_bg.js:1051:14)
    at l.remove (collider_set.js:87:18)
    at y.removeCollider (world.js:343:28)
    at PhysicsContext.tsx:258:15
    แต่ก็สนุกมากจริง ๆ เสียดายที่ไม่รู้ตอนมันเปิดให้เล่นแบบเรียลไทม์ ถ้าสร้าง ลิงก์ถาวร ไปยังเครื่องแต่ละชิ้นที่คนทำได้ก็คงดีมาก
    เข้าใจว่าอาจมีปัญหาเรื่องพื้นที่จัดเก็บ แต่ทำแบบเข้ารหัส JSON เป็น base64 แล้วใส่ในพารามิเตอร์ URL ไม่ได้เหรอ? อยากทำแมปแปลก ๆ แล้วแชร์กับคนอื่น

    • ตอนนี้ยังเปิดอยู่ https://xkcd.com/2916/
      เครื่องที่เข้าไปอยู่ในเวอร์ชันสาธารณะทั้งหมดสามารถทำลิงก์ถาวรได้ แต่ผลงานรายชิ้นที่ไม่ได้ถูกเลือกจากคิวรอตรวจไม่มีลิงก์ถาวร
      ตั้งใจตัดสินใจแบบนั้นเพื่อหลีกเลี่ยงความเสี่ยงจากการโฮสต์ เนื้อหาที่ผู้ใช้สร้างขึ้นซึ่งยังไม่ได้ตรวจสอบ บนโดเมนของการ์ตูน
  • เผื่อไว้ HN เคยมีหัวข้อนี้เมื่อวันที่ 6 เมษายนด้วย และมีคอมเมนต์ 14 รายการ
    https://news.ycombinator.com/item?id=39953514

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

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

    • เพิ่งส่งไปสองอัน และไม่รู้เลยว่ารายการนั้นเลื่อนได้
      ตอนนี้ไม่มีแรงกลับไปตรวจแล้ว :(
  • ว้าว ผมกับเพื่อนก็เคยนึกไอเดียเดียวกันได้ในปี 2014 แล้วทำเป็นเกมสำหรับ Ludum Dare ด้วย https://nickfa.ro/wiki/CoinSlot
    ดีจังที่ได้เห็นไอเดียนั้นถูกขัดเกลาและออกมาในรูปแบบที่ใช้งานได้ดี

  • ทำให้นึกถึงสิ่งนี้สมัยยังเด็ก ผมเคยเสียเวลาไปมากมายอย่างสนุกสุด ๆ
    https://www.myabandonware.com/game/the-incredible-machine-1m...

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

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