केस स्टडी - Google I/O 2013 प्रयोग

परिचय

कॉन्फ़्रेंस के रजिस्ट्रेशन शुरू होने से पहले, 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 पर), तो कलेक्शन में 31,45,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);

नतीजा

हमें कई तरह की तकनीकों और टेक्नोलॉजी का इस्तेमाल करने का मौका मिला. जैसे, कैनवस, SVG, सीएसएस ऐनिमेशन, JS ऐनिमेशन, वेब ऑडियो वगैरह. इनकी मदद से, इस प्रोजेक्ट को डेवलप करना बेहद मज़ेदार रहा.

यहां आपको जो जानकारी दिखती है उससे ज़्यादा जानकारी एक्सप्लोर की जा सकती है. I/O लोगो पर टैप करते रहें. सही क्रम में टैप करने पर, आपको ज़्यादा छोटे प्रयोग, गेम, ट्रिप्पी विज़ुअल, और शायद नाश्ते के कुछ आइटम भी दिखेंगे. हमारा सुझाव है कि बेहतर अनुभव के लिए, इसे अपने स्मार्टफ़ोन या टैबलेट पर आज़माएं.

शुरुआत करने के लिए, यह कॉम्बिनेशन आज़माएं: O-I-I-I-I-I-I-I. इसे अभी आज़माएं: google.com/io

ओपन सोर्स

हमने अपने कोड को Apache 2.0 लाइसेंस के तहत ओपन सोर्स किया है. इसे हमारे GitHub पर यहां देखा जा सकता है: http://github.com/Instrument/google-io-2013.

क्रेडिट

डेवलपर:

  • थॉमस रेनॉल्ड्स
  • ब्रायन हेफ़्टर
  • स्टेफ़नी हैचर
  • पॉल फ़ार्निंग

डिज़ाइनर:

  • डैन शेचर
  • सेज ब्राउन
  • कायल बेक

निर्माता:

  • एमी पास्कल
  • एंड्रिया नेल्सन