กำลังสร้าง Roll It

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 และใช้การจัดแสงโดยใช้โค้ด ขั้นตอนที่เราดำเนินการมีรายละเอียดดังนี้

สร้างโมเดลของวัตถุใน C4D ตรวจสอบว่าเวกเตอร์ปกติของเมชหันออกไปด้านนอก
โมเดลวัตถุใน C4D ตรวจสอบว่าเวกเตอร์ปกติของเมชหันออกไปด้านนอก
ใช้เครื่องมือการเลือกรูปหลายเหลี่ยมเพื่อสร้างแท็กการเลือกของพื้นที่เฉพาะที่ต้องการใส่พื้นผิว ใช้ชิ้นงานกับแท็กการเลือกแต่ละรายการ
ใช้เครื่องมือการเลือกรูปหลายเหลี่ยมเพื่อสร้างแท็กการเลือกของพื้นที่เฉพาะที่ต้องการใส่พื้นผิว ใช้ชิ้นงานกับแท็กการเลือกแต่ละรายการ
ส่งออกเมชเป็นไฟล์ .dae ของ COLLADA 1.5
ส่งออกเมชเป็นไฟล์ .dae ของ COLLADA 1.5
ตรวจสอบว่าได้เลือก "ส่งออกเรขาคณิต 2 มิติ" แล้ว โดยทั่วไปแล้ว การส่งออกรูปสามเหลี่ยมได้รับการรองรับในวงกว้างมากขึ้นในสภาพแวดล้อม 3 มิติทางด้านโค้ด แต่มีข้อเสียตรงที่จำนวนรูปหลายเหลี่ยมจะเพิ่มขึ้นเป็น 2 เท่า ยิ่งจำนวนรูปหลายเหลี่ยมสูงเท่าใด โมเดลก็จะยิ่งใช้ทรัพยากรโปรเซสเซอร์ของคอมพิวเตอร์มากขึ้นเท่านั้น ดังนั้น ให้เลือกตัวเลือกนี้ไว้หากพบว่าประสิทธิภาพช้า
ตรวจสอบว่าได้เลือก "ส่งออกเรขาคณิต 2 มิติ" แล้ว โดยทั่วไปแล้ว การส่งออกรูปสามเหลี่ยมได้รับการรองรับในวงกว้างมากขึ้นในสภาพแวดล้อม 3 มิติทางด้านโค้ด แต่มีข้อเสียตรงที่จำนวนรูปหลายเหลี่ยมจะเพิ่มขึ้นเป็น 2 เท่า ยิ่งจำนวนรูปหลายเหลี่ยมสูงเท่าใด โมเดลก็จะยิ่งใช้ทรัพยากรโปรเซสเซอร์ของคอมพิวเตอร์มากขึ้นเท่านั้น ดังนั้น ให้เลือกตัวเลือกนี้ไว้หากพบว่าประสิทธิภาพช้า
นําเข้าไฟล์ Collada ไปยัง Blender
นําเข้าไฟล์ Collada ไปยัง Blender
เมื่อนำเข้าไปยัง Blender แล้ว คุณจะเห็นว่าวัสดุและแท็กการเลือกก็โอนไปด้วยเช่นกัน
เมื่อนำเข้าไปยัง Blender แล้ว คุณจะเห็นว่าวัสดุและแท็กการเลือกก็โอนไปด้วยเช่นกัน
เลือกวัตถุและปรับวัสดุของวัตถุตามต้องการ
เลือกวัตถุและปรับวัสดุของวัตถุตามที่ต้องการ
ส่งออกไฟล์เป็นไฟล์ three.js
ส่งออกไฟล์เป็นไฟล์ three.js เพื่อให้ใช้งานร่วมกับ WebGL ได้

การเขียนโค้ด

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 เป็นสัญญาณของยุคสมัย การเชื่อมต่อบนเว็บแบบเปิดเป็นช่วงเวลาที่น่าตื่นเต้นและเปลี่ยนแปลงไปอย่างมาก ทั้งจากโปรเจ็กต์โอเพนซอร์สที่ขับเคลื่อนการพัฒนา พลังการประมวลผลของอุปกรณ์บนโต๊ะทำงานและในกระเป๋าของเรา รวมถึงสถานะของเว็บในฐานะแพลตฟอร์ม เมื่อไม่กี่ปีที่ผ่านมา เทคโนโลยีส่วนใหญ่นี้ยังอยู่ในระบบที่เป็นกรรมสิทธิ์เท่านั้น ไม่สามารถใช้งานและเผยแพร่ได้อย่างอิสระ ปัจจุบันการสร้างประสบการณ์ที่ซับซ้อนสามารถทำได้ด้วยการทำงานน้อยลงและจินตนาการมากขึ้นเมื่อเราสร้างและแชร์ชิ้นส่วนใหม่ของภาพต่อกันทุกวัน อย่ามัวรอช้า สร้างสิ่งดีๆ แล้วแชร์ให้โลกรู้

โลโก้ Roll it