Roll It เป็นเกมทดลองของ Chrome ที่พลิกโฉมเกมกระดานชายหาดสุดคลาสสิกโดยใช้เพียงเบราว์เซอร์ในโทรศัพท์และคอมพิวเตอร์ เบราว์เซอร์ในโทรศัพท์ช่วยให้คุณเล็งและกลิ้งลูกบอลด้วยการขยับข้อมือ ขณะที่เบราว์เซอร์ในคอมพิวเตอร์จะแสดงผลกราฟิกแบบเรียลไทม์ของสนามโบว์ลิ่งด้วย WebGL และ Canvas อุปกรณ์ทั้ง 2 เครื่องจะสื่อสารกันผ่าน Websockets ไม่มีแอป ไม่มีดาวน์โหลด ไม่มีโทเค็น คุณใช้เบราว์เซอร์สมัยใหม่ได้
Legwork ได้พัฒนาประสบการณ์ของผู้ใช้ อินเทอร์เฟซ และสภาพแวดล้อมเกมตามแนวทางของ Google Creative Lab จากนั้นได้ร่วมมือกับพาร์ทเนอร์ด้านการพัฒนาอย่าง Mode Set เพื่อสร้างเกม Roll It ตลอดระยะเวลาของโปรเจ็กต์นี้ เราพบปัญหาที่ไม่เหมือนใครหลายประการ บทความนี้จะอธิบายเทคนิคบางส่วนที่เราใช้ เคล็ดลับที่เราค้นพบ และบทเรียนที่เราได้เรียนรู้ขณะทำให้ฟีเจอร์ Roll It กลายเป็นจริง
เวิร์กโฟลว์ 3 มิติ
ปัญหาอย่างหนึ่งในช่วงแรกคือการหาวิธีที่ดีที่สุดในการนําโมเดล 3 มิติจากซอฟต์แวร์ของเราไปไว้ในรูปแบบไฟล์ที่พร้อมใช้งานบนเว็บ หลังจากสร้างชิ้นงานใน Cinema 4D แล้ว ระบบจะลดความซับซ้อนของโมเดลและแปลงเป็นเมชแบบรูปหลายเหลี่ยมต่ำ แต่ละเมชได้รับการติดแท็กการเลือกรูปหลายเหลี่ยมบางอย่างเพื่อแยกความแตกต่างระหว่างส่วนต่างๆ ของวัตถุสำหรับการระบายสีและการสร้างพื้นผิว จากนั้นเราส่งออกเป็นไฟล์ Collada 1.5 (.dae) และนําเข้าไปยัง Blender ซึ่งเป็นโปรแกรม 3 มิติแบบโอเพนซอร์สเพื่อสร้างไฟล์ที่เข้ากันได้กับ three.js เมื่อตรวจสอบว่านําเข้าโมเดลอย่างถูกต้องแล้ว เราจะส่งออกเมชเป็นไฟล์ JSON และใช้การจัดแสงโดยใช้โค้ด ขั้นตอนที่เราดำเนินการมีรายละเอียดดังนี้
การเขียนโค้ด
Roll It พัฒนาขึ้นโดยใช้ไลบรารีโอเพนซอร์สและทำงานในเบราว์เซอร์สมัยใหม่ได้โดยตรง เทคโนโลยีอย่าง WebGL และ WebSockets ช่วยให้เว็บสามารถมอบประสบการณ์การเล่นเกมและมัลติมีเดียที่มีคุณภาพระดับคอนโซลได้ ความสะดวกและสบายใจของนักพัฒนาแอปในการสร้างประสบการณ์เหล่านี้ได้พัฒนาไปอย่างมากเมื่อมีเครื่องมือที่ทันสมัยมากขึ้นสําหรับการพัฒนา HTML
สภาพแวดล้อมในการพัฒนาซอฟต์แวร์
โค้ดเดิมส่วนใหญ่ของ Roll It เขียนด้วย CoffeeScript ซึ่งเป็นภาษาที่เขียนได้กระชับและชัดเจน ซึ่งจะเปลี่ยนรูปแบบเป็น JavaScript ที่ถูกต้องตามรูปแบบและผ่านการตรวจสอบ CoffeeScript เหมาะสําหรับการพัฒนา OOP ด้วยรูปแบบการสืบทอดที่ยอดเยี่ยมและการจัดการขอบเขตที่สะอาดตา CSS เขียนด้วยเฟรมเวิร์ก SASS ซึ่งช่วยให้นักพัฒนาซอฟต์แวร์มีเครื่องมือที่ยอดเยี่ยมมากมายในการปรับปรุงและจัดการสไตล์ชีตของโปรเจ็กต์ การเพิ่มระบบเหล่านี้ลงในกระบวนการสร้างจะใช้เวลาสักครู่ในการตั้งค่า แต่ผลลัพธ์ที่ได้คุ้มค่าแน่นอน โดยเฉพาะสำหรับโปรเจ็กต์ขนาดใหญ่อย่าง Roll It เราได้ตั้งค่าเซิร์ฟเวอร์ Ruby on Rails เพื่อคอมไพล์ชิ้นงานโดยอัตโนมัติระหว่างการพัฒนา เพื่อให้ขั้นตอนเหล่านี้ทั้งหมดมีความโปร่งใส
นอกจากการสร้างสภาพแวดล้อมการเขียนโค้ดที่มีประสิทธิภาพและสะดวกสบายแล้ว เรายังเพิ่มประสิทธิภาพชิ้นงานด้วยตนเองเพื่อลดคำขอให้เหลือน้อยที่สุดเพื่อโหลดเว็บไซต์ได้เร็วขึ้น เราได้เรียกใช้รูปภาพทุกรูปผ่านโปรแกรมบีบอัด 2 โปรแกรม ได้แก่ ImageOptim และ ImageAlpha โปรแกรมแต่ละโปรแกรมจะเพิ่มประสิทธิภาพรูปภาพด้วยวิธีของตัวเอง ซึ่งก็คือแบบไม่สูญเสียคุณภาพและแบบสูญเสียคุณภาพตามลำดับ การตั้งค่าที่ถูกต้องจะช่วยลดน้ำหนักไฟล์รูปภาพได้อย่างมาก ซึ่งไม่เพียงช่วยประหยัดแบนด์วิดท์เมื่อโหลดรูปภาพภายนอกเท่านั้น แต่เมื่อเพิ่มประสิทธิภาพแล้ว รูปภาพจะเปลี่ยนเป็นสตริงที่เข้ารหัส Base64 ที่มีขนาดเล็กลงมากสำหรับการฝังในหน้าใน HTML, CSS และ JavaScript ในเรื่องของการเข้ารหัส Base64 เรายังได้ฝังไฟล์แบบอักษร WOFF และ SVG ของ Open Sans ลงใน CSS โดยตรงโดยใช้เทคนิคนี้ด้วย ซึ่งส่งผลให้มีคำขอทั้งหมดน้อยลง
ฉาก 3 มิติที่เปิดใช้ฟิสิกส์
THREE.js เป็นไลบรารี JavaScript 3 มิติที่พบได้ทั่วไปในเว็บ เครื่องมือนี้รวมคณิตศาสตร์ 3 มิติระดับล่างและการเพิ่มประสิทธิภาพ WebGL ตามฮาร์ดแวร์เข้าด้วยกัน ซึ่งช่วยให้ผู้ใช้ทั่วไปสร้างฉาก 3 มิติแบบอินเทอร์แอกทีฟที่มีแสงสว่างเพียงพอและสวยงามได้อย่างง่ายดายโดยไม่ต้องเขียนโปรแกรม Shader ที่กำหนดเองหรือทำการเปลี่ยนรูปแบบเมทริกซ์ด้วยตนเอง Physijs เป็น Wrapper สำหรับ THREE.js โดยเฉพาะสำหรับไลบรารีฟิสิกส์ C++ ยอดนิยมที่ได้รับการแปลเป็น JavaScript เราใช้ประโยชน์จากไลบรารีนี้เพื่อจำลองลูกบอลกลิ้ง กระโดด และเด้งไปยังจุดหมายในแบบ 3 มิติ
ตั้งแต่เริ่มต้น เราตั้งใจที่จะไม่เพียงทำให้ประสบการณ์การกลิ้งลูกบอลสมจริงเท่านั้น แต่ยังต้องทำให้วัตถุในเกมดูสมจริงด้วย ซึ่งต้องใช้การปรับแรงโน้มถ่วงโดยรวมของฉากฟิสิกส์ ความเร็วของลูกบอลขณะกลิ้งจากการโยนของผู้เล่น ความลาดชันของเนินในเลน และคุณสมบัติของแรงเสียดทานและการกลับคืนสู่สภาพเดิม (ความยืดหยุ่น) ของวัสดุของลูกบอลและเลน การรวมแรงโน้มถ่วงและความเร็วที่มากขึ้นเข้าด้วยกันทำให้ประสบการณ์การเล่นเกมสมจริงยิ่งขึ้น
ปรับให้ราบรื่น
เบราว์เซอร์และวิดีโอการ์ดสมัยใหม่ส่วนใหญ่ควรใช้ประโยชน์จากการลดรอยหยักแบบฮาร์ดแวร์ในสภาพแวดล้อม WebGL แต่บางรายการอาจใช้งานร่วมกันไม่ได้ ในกรณีที่การลดรอยหยักไม่ทำงานโดยค่าเริ่มต้น ขอบที่แข็งและตัดกันมากในฉาก THREE.js จะดูไม่สม่ำเสมอและไม่น่าดู (อย่างน้อยก็สำหรับสายตาที่สังเกตเห็นรายละเอียดของเรา)
แต่โชคดีที่ปัญหานี้แก้ไขได้ เราสามารถตรวจจับได้ว่าแพลตฟอร์มจะรองรับการลดรอยหยักในตัวหรือไม่ผ่านข้อมูลโค้ด หากใช่ ก็ลุยต่อได้เลย หากไม่ใช่ เรามีชุดเชดเดอร์สำหรับขั้นตอนหลังการประมวลผลที่มาพร้อมกับ THREE.js ซึ่งจะช่วยเราได้ กล่าวคือ ตัวกรองการลบรอยหยัก FXAA การวาดฉากที่ผ่านการจัดการแสดงผลใหม่ทุกเฟรมด้วยโปรแกรมเปลี่ยนสีนี้ช่วยให้เส้นและขอบดูเรียบเนียนขึ้นมาก ดูการสาธิตด้านล่าง
// Check for native platform antialias support via the THREE renderer
// from: http://codeflow.org/entries/2013/feb/22/how-to-write-portable-webgl/#antialiasing
var nativeAntialiasSupport = (renderer.context.getParameter(renderer.context.SAMPLES) == 0) ? false : true;
การควบคุมเกมที่อิงตามเซ็นเซอร์ตรวจจับความเร่ง
ความน่าสนใจส่วนใหญ่ของ Roll It มาจากท่าทางสัมผัสลูกบอลที่ผู้เล่นทำกับโทรศัพท์ อุปกรณ์เคลื่อนที่มีสิทธิ์เข้าถึงตัวตรวจวัดความเร่งภายในเบราว์เซอร์มาระยะหนึ่งแล้ว แต่ในฐานะอุตสาหกรรม เราเพิ่งเริ่มสำรวจการจดจำท่าทางสัมผัสตามการเคลื่อนไหวบนเว็บ เรามีข้อจำกัดบางอย่างจากข้อมูลที่ได้จากเครื่องวัดความเร่งของโทรศัพท์ แต่เราก็ใช้ความคิดสร้างสรรค์เล็กๆ น้อยๆ เพื่อสร้างประสบการณ์การใช้งานใหม่ๆ ที่ยอดเยี่ยมได้
การจับการเคลื่อนไหว "เลื่อน" หลักของ Roll It เริ่มต้นด้วยการติดตามการอัปเดตจากเครื่องวัดความเร่งล่าสุด 10 รายการที่มาจากเหตุการณ์ deviceorientation
ของหน้าต่าง เราจะเก็บค่าการเปลี่ยนแปลงของมุมระหว่างเหตุการณ์ต่างๆ โดยการลบค่าการเอียงก่อนหน้าออกจากค่าการเอียงปัจจุบัน จากนั้นเราจะรวมค่าเดลต้าของมุม 10 รายการล่าสุดอย่างต่อเนื่องเพื่อตรวจจับการหมุนอย่างต่อเนื่องขณะที่โทรศัพท์เคลื่อนที่ผ่านพื้นที่ เมื่อโทรศัพท์ผ่านเกณฑ์การเปลี่ยนแปลงมุมการสแกน เราจะทริกเกอร์การกลิ้ง จากนั้นเราจะประมาณความเร็วของบอลได้โดยหาค่า Delta ของการเอียงครั้งเดียวที่ใหญ่ที่สุดในการกวาดนั้น ในฟีเจอร์ Roll It ความเร็วนี้จะได้รับการทำให้เป็นมาตรฐานโดยใช้การประทับเวลาที่แนบมากับการอัปเดตของเซ็นเซอร์ตรวจจับความเร่งแต่ละครั้ง ซึ่งจะช่วยปรับความเร็วที่ผันผวนของการสตรีมข้อมูลอัปเดตจากเครื่องวัดความเร่งไปยังเบราว์เซอร์ในอุปกรณ์ต่างๆ ให้ราบรื่น
การสื่อสารผ่าน WebSocket
เมื่อผู้เล่นกลิ้งลูกบอลด้วยโทรศัพท์ ระบบจะส่งข้อความจากโทรศัพท์ไปยังแล็ปท็อปเพื่อบอกให้ยิงลูกบอล ระบบจะส่งข้อความ "roll" นี้ผ่านออบเจ็กต์ข้อมูล JSON ผ่านการเชื่อมต่อ WebSocket ระหว่างเครื่อง 2 เครื่อง ข้อมูล JSON มีขนาดเล็ก โดยประกอบด้วยประเภทข้อความ ความเร็วในการโยน และทิศทางการเล็งเป็นหลัก
{
"type": "device:ball-thrown",
"speed": 0.5,
"aim": 0.1
}
การสื่อสารทั้งหมดระหว่างแล็ปท็อปและโทรศัพท์จะเกิดขึ้นผ่านข้อความ JSON ขนาดเล็กเช่นนี้ ทุกครั้งที่เกมอัปเดตสถานะบนเดสก์ท็อป หรือผู้ใช้เอียงหรือแตะปุ่มบนโทรศัพท์ ระบบจะส่งข้อความ WebSocket ระหว่างเครื่อง ระบบจะออกอากาศข้อความ WebSockets โดยใช้จุดออกเดียวจากเบราว์เซอร์ใดเบราว์เซอร์หนึ่งเพื่อให้การสื่อสารนี้ง่ายและจัดการได้ ในทางกลับกัน จะมีจุดแรกเข้าเพียงจุดเดียวในเบราว์เซอร์ฝั่งที่รับ โดยมีออบเจ็กต์ WebSocket 1 รายการที่จัดการข้อความขาเข้าและขาออกทั้งหมดของทั้ง 2 ฝั่ง เมื่อได้รับข้อความ WebSocket ระบบจะออกอากาศข้อมูล JSON อีกครั้งภายในแอป JavaScript โดยใช้เมธอด trigger()
ของ jQuery เมื่อถึงจุดนี้ ข้อมูลที่เข้ามาจะทํางานเหมือนกับเหตุการณ์ DOM ที่กําหนดเองอื่นๆ และวัตถุอื่นๆ ในแอปพลิเคชันจะรับและประมวลผลข้อมูลดังกล่าวได้
var websocket = new WebSocket(serverIPAddress);
// rebroadcast incoming WebSocket messages with a global event via jQuery
websocket.onmessage = function(e) {
if (e.data) {
var obj = JSON.parse(e.data);
$(document).trigger(data.type, obj);
}
};
// broadcast outgoing WebSocket messages by passing in a native .js object
var broadcast = function(obj) {
websocket.send(JSON.stringify(obj));
};
ระบบจะสร้างเซิร์ฟเวอร์ WebSocket ของ Roll It ขณะดำเนินการเมื่ออุปกรณ์ 2 เครื่องซิงค์กับรหัสเกม แบ็กเอนด์ของ Roll It สร้างขึ้นบนแพลตฟอร์ม Google Compute Engine และ App Engine โดยใช้ Go
การเอียงหน้าจอเมนู
นอกจากข้อความ WebSocket ที่ทำงานตามเหตุการณ์ซึ่งใช้ระหว่างเล่นเกมแล้ว เมนูใน Roll It ยังควบคุมด้วยการเอียงโทรศัพท์และแตะปุ่มเพื่อยืนยันการเลือก ซึ่งต้องใช้สตรีมข้อมูลที่แสดงการเอียงที่สม่ำเสมอมากขึ้นซึ่งส่งจากโทรศัพท์ไปยังแล็ปท็อป ระบบจะส่งข้อความเหล่านี้เฉพาะในกรณีที่อุปกรณ์เอียงมากกว่า 2-3 องศาเท่านั้น เพื่อลดแบนด์วิดท์และหลีกเลี่ยงการส่งการอัปเดตที่ไม่จำเป็น การส่งสตรีมข้อมูลการเอียงจะไร้ประโยชน์หากโทรศัพท์วางราบอยู่บนโต๊ะ ระบบจะควบคุมอัตราการส่งด้วย โดยจะส่งข้อความ WebSockets ไม่เกิน 15 ข้อความต่อวินาทีในฟีเจอร์ Roll It แม้ว่าอุปกรณ์จะเอียงอยู่ก็ตาม
เมื่อระบบรับค่าการเอียงในคอมพิวเตอร์แล้ว ระบบจะประมาณค่าเมื่อเวลาผ่านไปโดยใช้ requestAnimationFrame
เพื่อให้รู้สึกราบรื่น ผลลัพธ์ที่ได้คือเมนูแบบหมุนและลูกบอลที่กลิ้งไปมาเพื่อช่วยระบุการเลือกของผู้ใช้ เมื่อโทรศัพท์ส่งข้อมูลการเอียง องค์ประกอบ DOM เหล่านี้จะอัปเดตแบบเรียลไทม์โดยคำนวณการเปลี่ยนรูปแบบ CSS ใหม่ภายในลูป requestAnimationFrame
คอนเทนเนอร์ของเมนูหมุนไปมา แต่ลูกบอลดูเหมือนจะกลิ้งไปตามพื้น เราใช้ตรีโกณมิติพื้นฐานเพื่อเชื่อมโยงพิกัด x ของลูกบอลกับการหมุนเพื่อให้ได้เอฟเฟกต์นี้ สมการง่ายๆ คือ การหมุน = x / (เส้นผ่านศูนย์กลาง * π)
สรุป
Roll It เป็นสัญญาณของยุคสมัย การเชื่อมต่อบนเว็บแบบเปิดเป็นช่วงเวลาที่น่าตื่นเต้นและเปลี่ยนแปลงไปอย่างมาก ทั้งจากโปรเจ็กต์โอเพนซอร์สที่ขับเคลื่อนการพัฒนา พลังการประมวลผลของอุปกรณ์บนโต๊ะทำงานและในกระเป๋าของเรา รวมถึงสถานะของเว็บในฐานะแพลตฟอร์ม เมื่อไม่กี่ปีที่ผ่านมา เทคโนโลยีส่วนใหญ่นี้ยังอยู่ในระบบที่เป็นกรรมสิทธิ์เท่านั้น ไม่สามารถใช้งานและเผยแพร่ได้อย่างอิสระ ปัจจุบันการสร้างประสบการณ์ที่ซับซ้อนสามารถทำได้ด้วยการทำงานน้อยลงและจินตนาการมากขึ้นเมื่อเราสร้างและแชร์ชิ้นส่วนใหม่ของภาพต่อกันทุกวัน อย่ามัวรอช้า สร้างสิ่งดีๆ แล้วแชร์ให้โลกรู้