กรณีศึกษา - การสร้าง doodle Stanisław Lem ของ Google

สวัสดีทุกคน

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

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

doodle แบบอินเทอร์แอกทีฟทุกตัวที่ฉันเขียนโค้ด (Pac-Man, Jules Verne, World’s Fair) และหลายๆ คนที่ฉันช่วยด้วยนั้นมีส่วนในรูปแบบล้ำยุคและล้าสมัยเท่าๆ กัน เป็นโอกาสที่ดีในการใช้ฟีเจอร์บนเว็บอันล้ำสมัย... และการปฏิบัติอย่างเคร่งครัดในความเข้ากันได้ข้ามเบราว์เซอร์

เราได้เรียนรู้สิ่งต่างๆ มากมายจาก doodle แบบอินเทอร์แอกทีฟแต่ละเกม และมินิเกม Stanisław Lem ล่าสุดก็ไม่มีข้อยกเว้น ด้วยโค้ด JavaScript 17,000 บรรทัด โดยทดลองสิ่งต่างๆ มากมายเป็นครั้งแรกในประวัติศาสตร์ Doodle วันนี้ผมจะมาแชร์โค้ดนี้กับคุณ บางทีคุณอาจพบสิ่งที่น่าสนใจ หรือชี้แนะข้อผิดพลาดของผม และพูดคุยกันสักเล็กน้อย

ดูโค้ด Doodle ของ Stanisław Lem »

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

ต่อไปเรามาดูเทคโนโลยีเว็บสมัยใหม่บางส่วนที่ค้นพบ และบางอย่างที่ยังไม่มีใน doodle ของ Stanisław Lem

กราฟิกผ่าน DOM และ Canvas

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

ผมได้รวบรวมเครื่องมือกราฟิกที่แยกองค์ประกอบพื้นฐานแบบกราฟิกที่เรียกว่า "สี่เหลี่ยมผืนผ้า" ออกไป แล้วแสดงผลโดยใช้ Canvas หรือ DOM หากผืนผ้าใบไม่พร้อมใช้งาน

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

น่าเสียดายที่การเปลี่ยนไปใช้ Canvas ไม่ง่ายอย่างการมิเรอร์พื้นหลัง CSS ด้วย drawImage(): คุณจะสูญเสียสิ่งต่างๆ มากมายที่ไม่มีค่าใช้จ่ายเมื่อรวมสิ่งต่างๆ เข้าด้วยกันผ่าน DOM ซึ่งที่สำคัญที่สุดคือการซ้อนทับด้วยดัชนี z และเหตุการณ์เกี่ยวกับเมาส์

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

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

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

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

อัตราเฟรม

การรู้อัตราเฟรมปัจจุบันและการตอบสนองต่อเมื่ออัตราที่ช้าเกินไป (และเร็วเกินไป) เป็นส่วนสำคัญของเครื่องมือของเรา เนื่องจากเบราว์เซอร์ไม่รายงานอัตราเฟรมกลับคืน เราจึงต้องคำนวณเอง

ผมเริ่มใช้ requestAnimationFrame แล้วกลับไปใช้ setTimeout แบบเก่าหากเวอร์ชันเดิมไม่พร้อมใช้งาน requestAnimationFrame ช่วยประหยัด CPU ได้อย่างชาญฉลาดในบางสถานการณ์ แม้ว่าเราจะกำลังดำเนินการบางอย่างเองตามที่อธิบายไว้ด้านล่าง แต่ก็ยังช่วยให้ได้อัตราเฟรมที่สูงกว่า setTimeout ด้วย

การคำนวณอัตราเฟรมในปัจจุบันนั้นทำได้ง่ายๆ แต่อาจมีการเปลี่ยนแปลงอย่างมาก เช่น อาจจะลดลงอย่างรวดเร็วเมื่อแอปพลิเคชันอื่นรบกวนคอมพิวเตอร์เป็นระยะเวลาหนึ่ง เราจึงคำนวณอัตราเฟรม "แบบกลิ้ง" (เฉลี่ย) เฉพาะจากจุด 100 จุดเท่านั้น และทำการตัดสินใจตามจุดนั้น

การตัดสินใจประเภทใด

  • หากอัตราเฟรมสูงกว่า 60 FPS เราจะเร่งความเร็ว ปัจจุบัน requestAnimationFrame ใน Firefox บางเวอร์ชันไม่มีขีดจำกัดสูงสุดของอัตราเฟรม และไม่มีส่วนที่จะทำให้ CPU ทำงานอย่างสิ้นเปลือง โปรดทราบว่าจริงๆ แล้วเรากำหนดขีดจำกัดไว้ที่ 65 FPS เนื่องจากข้อผิดพลาดในการปัดเศษที่ทำให้อัตราเฟรมสูงกว่า 60 FPS ในเบราว์เซอร์อื่นเพียงเล็กน้อย เราจึงไม่ต้องการเริ่มควบคุมโดยไม่ได้ตั้งใจ

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

  • สุดท้ายนี้ เราอาจลองลดความซับซ้อนของกราฟิกเมื่ออัตราเฟรมต่ำจนเข้าข่ายอันตราย เราไม่ได้ทำเช่นนี้สำหรับ Lem doodle ยกเว้นเคอร์เซอร์เมาส์ (ดูรายละเอียดเพิ่มเติมด้านล่าง) แต่สันนิษฐาน เราอาจสูญเสียภาพเคลื่อนไหวส่วนเกินบางอย่างไป แค่ทำให้ Doodle นี้ดูลื่นไหลได้แม้จะใช้คอมพิวเตอร์ที่ทำงานช้า

และเรายังมีแนวคิดเกี่ยวกับจุดอยู่กับตัวและขีดเชิงตรรกะอีกด้วย ส่วนแรกมาจาก requestAnimationFrame/setTimeout อัตราส่วนในเกมเพลย์ปกติคือ 1:1 แต่สำหรับการกรอไปข้างหน้า เราเพียงแค่เพิ่มเครื่องหมายถูก 1 จุดต่อจุด 1 จุด (ไม่เกิน 1:5) วิธีนี้ช่วยให้เราทำการคำนวณที่จำเป็นทั้งหมดสำหรับการติดตามเชิงตรรกะได้ทั้งหมด โดยกำหนดให้เพียงรายการเดียวเป็นอักขระอัปเดตสิ่งต่างๆ บนหน้าจอ

การเปรียบเทียบ

มีสมมติฐานว่า Canvas จะเร็วกว่า DOM เมื่อใดก็ตามที่พร้อมใช้งาน นั่นไม่จริงเสมอไป ขณะทดสอบ เราพบว่า Opera 10.0–10.1 บน Mac และ Firefox ใน Linux นั้นทำงานเร็วกว่าเมื่อย้ายองค์ประกอบ DOM

ในโลกที่สมบูรณ์แบบ Doodle จะทำการเปรียบเทียบเทคนิคกราฟิกต่างๆ แบบเงียบๆ ไม่ว่าจะเป็นองค์ประกอบ DOM ที่เคลื่อนไหวโดยใช้ style.left และ style.top การวาดบนผืนผ้าใบ หรือแม้แต่องค์ประกอบ DOM ที่ย้ายโดยใช้การแปลง CSS3

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

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

การประหยัด CPU

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

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

หากมี มีเมื่อไร

  • หลังจากผ่านไป 18 วินาทีในหน้าแรก (เกมอาร์เคดเรียกว่าโหมดดึงดูด)
  • หลังจากผ่านไป 180 วินาทีหากแท็บโฟกัสอยู่
  • หลังจากผ่านไป 30 วินาที หากแท็บไม่มีโฟกัส (เช่น ผู้ใช้เปลี่ยนไปดูหน้าต่างอื่น แต่อาจกำลังดู doodle อยู่ในแท็บที่ไม่ได้ใช้งาน)
  • ทันทีในกรณีที่แท็บนั้นไม่แสดง (เช่น ผู้ใช้เปลี่ยนไปยังแท็บอื่นในหน้าต่างเดียวกัน) ถ้าเรามองไม่เห็นแท็บนั้น ก็จะไม่สูญเปล่า

เราจะรู้ได้อย่างไรว่าแท็บปัจจุบันมีโฟกัสอยู่ เราแนบ window.focus และ window.blur แล้วคุณจะรู้ได้อย่างไรว่าแท็บเปิดอยู่ โดยเรากำลังใช้ Page Understanding API แบบใหม่และตอบสนองต่อเหตุการณ์ที่เหมาะสม

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

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

การเปลี่ยนฉาก การเปลี่ยนรูปแบบ เหตุการณ์

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

ปัญหาเหล่านี้และอีกมากมายคือสาเหตุที่ Lem doodle มีการเปลี่ยนผ่านและเครื่องมือการแปลงของตัวเอง ใช่ เรียกยุค 2000 เป็นต้นว่า ความสามารถที่ผมมีในตัว ไม่ได้มีประสิทธิภาพเท่า CSS3 แต่ไม่ว่าเครื่องมือใด ก็ทำได้อย่างสอดคล้องกันและควบคุมได้มากกว่า

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

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

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

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

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

การจัดการกับรูปภาพและสไปรท์

เครื่องมือไม่ได้มีไว้สำหรับดูเดิลเท่านั้น แต่ยังรวมถึงการทำงานด้วย เราได้แชร์พารามิเตอร์การแก้ไขข้อบกพร่องบางส่วนข้างต้นแล้ว ที่เหลือใน engine.readDebugParams ดูได้

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

Doodle แพ็ก-แมน
สไปรท์ที่ Doodle ของ Pac-Man ใช้สำหรับ

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

ภาพหน้าจอของกราฟิกการโหลดที่มีแถบความคืบหน้าที่ขึ้นด้านบน
ภาพหน้าจอของการโหลดกราฟิกด้วยแถบความคืบหน้าที่แสดงขึ้น

ในบางฉาก เราใช้สไปรท์มากกว่า 1 แบบเพื่อเร่งการโหลดโดยใช้การเชื่อมต่อแบบขนานกัน แต่เพียงเพราะข้อจำกัดด้านพิกเซล 3/5 ล้านพิกเซลสำหรับรูปภาพใน iOS

HTML5 เหมาะกับทั้งหมดนี้ในส่วนไหน ด้านบนยังใหม่ไม่มากนัก แต่เครื่องมือที่ฉันเขียนไว้สำหรับการสไปดี้/ครอบตัดคือเทคโนโลยีเว็บแบบใหม่ทั้งหมด เช่น Canvas, blobs, a[download] สิ่งหนึ่งที่น่าตื่นเต้นเกี่ยวกับ HTML คือมีการค่อยๆ แยกย่อยสิ่งที่เคยทำนอกเบราว์เซอร์ไปช้าๆ ส่วนเดียวที่เราต้องการ คือ การเพิ่มประสิทธิภาพไฟล์ PNG

กำลังบันทึกสถานะในระหว่างเกม

โลกของ Lem นั้นยิ่งใหญ่ มีชีวิตชีวา และสมจริงเสมอ เรื่องราวของเขามักเริ่มต้นโดยไม่มีคำอธิบายอะไรมากนัก หน้าแรกจะเริ่มด้วยความละเอียดของสื่อ โดยที่ผู้อ่านจะต้องค้นหาตัวเองให้เจอ

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

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

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

เรานำข้อมูลนี้ไปใช้อย่างไร

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

มีพารามิเตอร์การแก้ไขข้อบกพร่องหลายรายการที่ควบคุมฟีเจอร์นี้ ดังนี้

  • ?doodle-debug&doodle-first-run – สมมติว่าเป็นการเรียกใช้ครั้งแรก
  • ?doodle-debug&doodle-second-run – สมมติว่าเป็นการเรียกใช้ครั้งที่ 2
  • ?doodle-debug&doodle-old-run – ลองสมมติให้เป็นเวอร์ชันเก่าๆ

อุปกรณ์ระบบสัมผัส

เราอยากให้ doodle รู้สึกเหมือนอยู่บ้านเมื่อใช้อุปกรณ์แบบสัมผัส ตัวดูเดิลก็ทรงพลังและทรงพลังพอที่จะเล่น Doodle ได้ และการได้สัมผัสประสบการณ์เล่นเกมผ่านการแตะก็สนุกกว่าการคลิกมาก

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

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

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

การมีองค์ประกอบ DOM แบบโปร่งใสที่คลิกได้แยกต่างหากช่วยได้มากตรงนี้ เพราะผมสามารถปรับขนาดองค์ประกอบเหล่านี้แยกจากภาพได้ ผมเริ่มใช้ระยะห่างจากขอบ 15 พิกเซลสำหรับอุปกรณ์แบบสัมผัสและใช้ทุกครั้งที่มีการสร้างองค์ประกอบที่คลิกได้ (ผมเพิ่มระยะห่างจากขอบ 5 พิกเซลสำหรับสภาพแวดล้อมของเมาส์ด้วย เพื่อให้ Mr. Fitts มีความสุข)

สำหรับปัญหาอื่น เราแนะนำให้แนบและทดสอบตัวแฮนเดิลเริ่มต้นและสิ้นสุดที่เหมาะสมแทนที่จะอาศัยการคลิกเมาส์

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

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

การกำหนดค่าตัวชี้เมาส์

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

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

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

  • คุณต้องสามารถลบเคอร์เซอร์เมาส์ดั้งเดิมได้
  • คุณจะต้องทำให้ตัวชี้ของเมาส์ ซิงค์กับไอคอน "จริง" ได้ดี

วิธีแรกค่อนข้างซับซ้อน CSS3 อนุญาตให้ทำ cursor: none แต่บางเบราว์เซอร์ ไม่รองรับด้วยเช่นกัน เราต้องหันไปพึ่งนักยิมนาสติกบางคนโดยใช้ไฟล์ .cur ที่ว่างเปล่าเป็นการสำรอง ระบุลักษณะการทำงานที่ชัดเจนสำหรับบางเบราว์เซอร์ และแม้แต่ฮาร์ดโค้ดโปรแกรมอื่นๆ ที่ไม่มีประสบการณ์ไม่ว่าในกรณีใดก็ตาม

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

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

ช่วงอัตราเฟรม ลักษณะการทำงาน
>10 FPS ลดความเร็วเกมเพื่อให้เฟรมไม่ตกหล่นไปมาก
10-20 FPS ใช้ตัวชี้เมาส์แบบเนทีฟแทนตัวชี้ที่กำหนดเอง
20-60 FPS การทำงานปกติ
>60 FPS ควบคุมความเร็วเพื่อให้อัตราเฟรมไม่เกินค่านี้
สรุปลักษณะการทำงานที่อิงตามอัตราเฟรม

ชี้เมาส์บน Mac เป็นสีมืด แต่ชี้เมาส์บนพีซีเป็นสีขาว ทำไมจึงเป็นเช่นนั้น เพราะสงครามแพลตฟอร์มต้องอาศัยพลัง แม้แต่ในจักรวาลที่แต่งขึ้น

บทสรุป

แม้ว่ากลไกนี้ไม่สมบูรณ์แบบ แต่ก็ไม่สมบูรณ์แบบ ซึ่งได้รับการพัฒนามาคู่กับ doodle ของ Lem และมีความเฉพาะเจาะจงกับมันมาก ไม่เป็นไร "การเพิ่มประสิทธิภาพก่อนวัยอันควรคือรากของความชั่วร้ายทั้งหมด" ดังที่ Don Knuth กล่าวไว้ว่าผมไม่เชื่อว่าการเขียนเครื่องมือไว้โดดเดี่ยวก่อน และนำมาใช้ในภายหลังจะเหมาะสมเท่านั้น แนวทางปฏิบัตินี้บอกทฤษฎีได้พอๆ กับที่ทฤษฎีบอกในการฝึก ในกรณีของฉัน โค้ดถูกทิ้งไป หลายส่วนเขียนใหม่ซ้ำแล้วซ้ำอีก และชิ้นส่วนทั่วไปจำนวนมากก็สังเกตเห็นโพสต์ ไม่ใช่ข้อเท็จจริง แต่ในท้ายที่สุด สิ่งที่เรามีทำให้เราได้ทำในสิ่งที่อยากได้ คือการเฉลิมฉลองอาชีพของ Stanisław Lem และภาพวาดของ Daniel Mróz ในรูปแบบที่ดีที่สุดที่เราคิดว่า

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

ฉันเองก็ทำแบบนั้นเอง ด้านล่างนี้เป็นการจัดพิมพ์ในช่วงหลายวันที่ผ่านมา โดยนับถอยหลังไปจนถึงช่วงเริ่มต้นวันที่ 23 พฤศจิกายน 2011 ในรัสเซีย ซึ่งเป็นเขตเวลาแรกที่เห็น doodle ของ Lem เรื่องบ้าๆ บอๆ บางทีก็เหมือนกับดูเดิลนะครับ สิ่งที่ดูเหมือนไม่มีนัยสำคัญบางครั้งก็มีความหมายที่ลึกซึ้งยิ่งขึ้น เครื่องนับคะแนนนี้เป็น "การทดสอบความเครียด" ที่ดีสำหรับเครื่องยนต์

ภาพหน้าจอของนาฬิกานับถอยหลังของ Lem doodle ในจักรวาล
ภาพหน้าจอของนาฬิกานับถอยหลังของ Lem doodle ในจักรวาล

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