परिचय
कॉन्फ़्रेंस के रजिस्ट्रेशन शुरू होने से पहले, Google I/O 2013 की वेबसाइट पर डेवलपर की दिलचस्पी बढ़ाने के लिए, हमने मोबाइल के लिए कई एक्सपेरिमेंट और गेम बनाए. इनमें टच इंटरैक्शन, जनरेटिव ऑडियो, और नई चीज़ों को खोजने की खुशी पर फ़ोकस किया गया. कोड की क्षमता और खेलने की शक्ति से प्रेरित होकर, यह इंटरैक्टिव अनुभव नए I/O लोगो पर टैप करने पर, "I" और "O" की आसान आवाज़ों से शुरू होता है.
ऑर्गैनिक मोशन
हमने I और O ऐनिमेशन को एक ऐसा ऑर्गैनिक इफ़ेक्ट दिया है जो अक्सर HTML5 इंटरैक्शन में नहीं दिखता. इसे मज़ेदार और रीऐक्टिव बनाने के लिए, विकल्पों को चुनने में थोड़ा समय लगा.
बाउंसी फ़िज़िक्स कोड का उदाहरण
इस इफ़ेक्ट को हासिल करने के लिए, हमने दो आकारों के किनारों को दिखाने वाले पॉइंट की सीरीज़ पर, फ़िज़िक्स सिम्युलेशन का इस्तेमाल किया. किसी भी आकार पर टैप करने पर, सभी पॉइंट टैप की जगह से बाहर की ओर तेज़ी से बढ़ने लगते हैं. वे वापस खींचे जाने से पहले, खिंच जाते हैं और दूर हो जाते हैं.
इंस्टैंशिएशन के दौरान, हर पॉइंट को रैंडम तौर पर त्वरण और रीबाउंड "बाउंसीनेस" मिलता है, ताकि वे एक जैसा ऐनिमेशन न दिखाएं. इस कोड में देखा जा सकता है:
this.paperO_['vectors'] = [];
// Add an array of vector points and properties to the object.
for (var i = 0; i < this.paperO_['segments'].length; i++) {
var point = this.paperO_['segments'][i]['point']['clone']();
point = point['subtract'](this.oCenter);
point['velocity'] = 0;
point['acceleration'] = Math.random() * 5 + 10;
point['bounce'] = Math.random() * 0.1 + 1.05;
this.paperO_['vectors'].push(point);
}
इसके बाद, टैप करने पर, यहां दिए गए कोड का इस्तेमाल करके, उन्हें टैप की गई जगह से बाहर की ओर तेज़ी से भेजा जाता है:
for (var i = 0; i < path['vectors'].length; i++) {
var point = path['vectors'][i];
var vector;
var distance;
if (path === this.paperO_) {
vector = point['add'](this.oCenter);
vector = vector['subtract'](clickPoint);
distance = Math.max(0, this.oRad - vector['length']);
} else {
vector = point['add'](this.iCenter);
vector = vector['subtract'](clickPoint);
distance = Math.max(0, this.iWidth - vector['length']);
}
point['length'] += Math.max(distance, 20);
point['velocity'] += speed;
}
आखिर में, हर फ़्रेम पर हर कण की गति धीमी हो जाती है और कोड में इस तरीके से धीरे-धीरे संतुलन में वापस आ जाता है:
for (var i = 0; i < path['segments'].length; i++) {
var point = path['vectors'][i];
var tempPoint = new paper['Point'](this.iX, this.iY);
if (path === this.paperO_) {
point['velocity'] = ((this.oRad - point['length']) /
point['acceleration'] + point['velocity']) / point['bounce'];
} else {
point['velocity'] = ((tempPoint['getDistance'](this.iCenter) -
point['length']) / point['acceleration'] + point['velocity']) /
point['bounce'];
}
point['length'] = Math.max(0, point['length'] + point['velocity']);
}
ऑर्गैनिक मोशन का डेमो
यहां I/O होम मोड दिया गया है, जिसे आज़माया जा सकता है. हमने इस सुविधा को लागू करने के लिए, कुछ और विकल्प भी जोड़े हैं. "पॉइंट दिखाएं" को चालू करने पर, आपको वे पॉइंट दिखेंगे जिन पर फ़िज़िक्स सिम्युलेशन और फ़ोर्स काम कर रहे हैं.
रीस्किनिंग
होम मोड के मोशन से संतुष्ट होने के बाद, हमने उसी इफ़ेक्ट का इस्तेमाल दो रेट्रो मोड के लिए करना चाहा: Eightbit और Ascii.
इस रीस्किनिंग को पूरा करने के लिए, हमने होम मोड के उसी कैनवस का इस्तेमाल किया है. साथ ही, दोनों इफ़ेक्ट जनरेट करने के लिए, पिक्सल डेटा का इस्तेमाल किया है. यह तरीका, OpenGL फ़्रैगमेंट शेडर की याद दिलाता है. इसमें सीन के हर पिक्सल की जांच की जाती है और उसमें बदलाव किया जाता है. आइए, इस बारे में ज़्यादा जानें.
कैनवस "शेडर" कोड का उदाहरण
कैनवस पर मौजूद पिक्सल को getImageData
तरीके का इस्तेमाल करके पढ़ा जा सकता है. रिटर्न किए गए ऐरे में हर पिक्सल की चार वैल्यू होती हैं, जो हर पिक्सल की आरजीबीए वैल्यू दिखाती हैं. इन पिक्सल को एक बड़े ऐरे जैसे स्ट्रक्चर में जोड़ा जाता है. उदाहरण के लिए, 2x2 कैनवस के imageData ऐरे में चार पिक्सल और 16 एंट्री होंगी.
हमारा कैनवस फ़ुल स्क्रीन है. इसलिए, अगर हम मान लें कि स्क्रीन 1024x768 (जैसे कि iPad पर) है, तो ऐरे में 3,145,728 एंट्री होंगी. यह एक ऐनिमेशन है, इसलिए यह पूरा ऐरे हर सेकंड में 60 बार अपडेट होता है. आधुनिक JavaScript इंजन, इस डेटा को तेज़ी से लूप कर सकते हैं और उस पर कार्रवाई कर सकते हैं, ताकि फ़्रेम रेट को एक जैसा रखा जा सके. (सलाह: उस डेटा को डेवलपर कंसोल में लॉग करने की कोशिश न करें, क्योंकि इससे आपके ब्राउज़र की क्रॉलिंग धीमी हो जाएगी या वह पूरी तरह से क्रैश हो जाएगा.)
यहां बताया गया है कि हमारा Eightbit मोड, होम मोड कैनवस को कैसे पढ़ता है और ब्लॉक वाला इफ़ेक्ट देने के लिए पिक्सल को कैसे बड़ा करता है:
var pixelData = pctx.getImageData(0, 0, sourceCanvas.width, sourceCanvas.height);
// tctx is the Target Context for the output Canvas element
tctx.clearRect(0, 0, targetCanvas.width + 1, targetCanvas.height + 1);
var size = ~~(this.width_ * 0.0625);
if (this.height_ * 6 < this.width_) {
size /= 8;
}
var increment = Math.min(Math.round(size * 80) / 4, 980);
for (i = 0; i < pixelData.data.length; i += increment) {
if (pixelData.data[i + 3] !== 0) {
var r = pixelData.data[i];
var g = pixelData.data[i + 1];
var b = pixelData.data[i + 2];
var pixel = Math.ceil(i / 4);
var x = pixel % this.width_;
var y = Math.floor(pixel / this.width_);
var color = 'rgba(' + r + ', ' + g + ', ' + b + ', 1)';
tctx.fillStyle = color;
/**
* The ~~ operator is a micro-optimization to round a number down
* without using Math.floor. Math.floor has to look up the prototype
* tree on every invocation, but ~~ is a direct bitwise operation.
*/
tctx.fillRect(x - ~~(size / 2), y - ~~(size / 2), size, size);
}
}
Eightbit शेडर का डेमो
यहां हम Eightbit ओवरले को हटाकर, ओरिजनल ऐनिमेशन देखते हैं. "स्क्रीन बंद करें" विकल्प चुनने पर, आपको एक अजीब इफ़ेक्ट दिखेगा. यह इफ़ेक्ट, सोर्स पिक्सल को गलत तरीके से सैंपल करने की वजह से दिखता है. हमने Eightbit मोड को ऐसे आसपेक्ट रेशियो में बदल दिया है जो आम तौर पर इस्तेमाल नहीं किए जाते. साथ ही, हमने इसे "रिस्पॉन्सिव" ईस्टर अंडे के तौर पर इस्तेमाल किया है. गलती से हुआ अच्छा काम!
कैनवस कॉम्पोज़िटिंग
रेंडर करने के कई चरणों और मास्क को मिलाकर, बहुत ही शानदार चीज़ें बनाई जा सकती हैं. हमने एक 2D मेटाबॉल बनाया है. इसके लिए, ज़रूरी है कि हर बॉल का अपना रेडियल ग्रेडिएंट हो और जहां बॉल ओवरलैप होते हैं वहां उन ग्रेडिएंट को एक साथ ब्लेंड किया जाए. (इस बारे में ज़्यादा जानने के लिए, नीचे दिया गया डेमो देखें.)
ऐसा करने के लिए, हमने दो अलग-अलग कैनवस का इस्तेमाल किया. पहला कैनवस, मेटाबॉल के आकार का हिसाब लगाता है और उसे बनाता है. दूसरा कैनवस, हर बॉल की पोज़िशन पर रेडियल ग्रेडिएंट बनाता है. इसके बाद, आकार ग्रेडिएंट को मास्क कर देता है और हम आखिरी आउटपुट रेंडर कर देते हैं.
कॉम्पोज़ करने के लिए कोड का उदाहरण
यहां वह कोड दिया गया है जिससे यह सब होता है:
// Loop through every ball and draw it and its gradient.
for (var i = 0; i < this.ballCount_; i++) {
var target = this.world_.particles[i];
// Set the size of the ball radial gradients.
this.gradSize_ = target.radius * 4;
this.gctx_.translate(target.pos.x - this.gradSize_,
target.pos.y - this.gradSize_);
var radGrad = this.gctx_.createRadialGradient(this.gradSize_,
this.gradSize_, 0, this.gradSize_, this.gradSize_, this.gradSize_);
radGrad.addColorStop(0, target['color'] + '1)');
radGrad.addColorStop(1, target['color'] + '0)');
this.gctx_.fillStyle = radGrad;
this.gctx_.fillRect(0, 0, this.gradSize_ * 4, this.gradSize_ * 4);
};
इसके बाद, मास्क करने और ड्रॉ करने के लिए कैनवस सेट अप करें:
// Make the ball canvas the source of the mask.
this.pctx_.globalCompositeOperation = 'source-atop';
// Draw the ball canvas onto the gradient canvas to complete the mask.
this.pctx_.drawImage(this.gcanvas_, 0, 0);
this.ctx_.drawImage(this.paperCanvas_, 0, 0);
नतीजा
हमें कई तरह की तकनीकों और टेक्नोलॉजी का इस्तेमाल करने का मौका मिला. जैसे, कैनवस, एसवीजी, सीएसएस ऐनिमेशन, जेएस ऐनिमेशन, वेब ऑडियो वगैरह. इनकी मदद से, प्रोजेक्ट को डेवलप करना बेहद मज़ेदार रहा.
यहां आपको जो जानकारी दिखती है उससे ज़्यादा जानकारी एक्सप्लोर की जा सकती है. I/O लोगो पर टैप करते रहें. सही क्रम में टैप करने पर, आपको ज़्यादा छोटे-मोटे प्रयोग, गेम, ट्रिप्पी विज़ुअल, और शायद नाश्ते के कुछ आइटम भी दिखेंगे. हमारा सुझाव है कि बेहतर अनुभव के लिए, इसे अपने स्मार्टफ़ोन या टैबलेट पर आज़माएं.
शुरुआत करने के लिए, यह कॉम्बिनेशन आज़माएं: O-I-I-I-I-I-I-I. इसे अभी आज़माएं: google.com/io
ओपन सोर्स
हमने अपने कोड को Apache 2.0 लाइसेंस के तहत ओपन सोर्स किया है. इसे हमारे GitHub पर यहां देखा जा सकता है: http://github.com/Instrument/google-io-2013.
क्रेडिट
डेवलपर:
- थॉमस रेनॉल्ड्स
- ब्रायन हेफ़्टर
- स्टेफ़नी हैचर
- पॉल फ़र्निंग
डिज़ाइनर:
- डैन शेचर
- सेज ब्राउन
- काइल बेक
निर्माता:
- ऐमी पास्कल
- एंड्रिया नेल्सन