परिचय
क्या आपको कैनवस और HTML5 का इस्तेमाल करके गेम बनाना है? इस ट्यूटोरियल को फ़ॉलो करें और कुछ ही समय में, आपको अपने लक्ष्य तक पहुंचने में मदद मिलेगी.
इस ट्यूटोरियल में, यह माना गया है कि आपके पास JavaScript की कम से कम इंटरमीडिएट लेवल की जानकारी है.
पहले गेम खेलें या सीधे लेख पर जाएं और गेम का सोर्स कोड देखें.
कैनवस बनाना
कुछ भी बनाने के लिए, हमें एक कैनवस बनाना होगा. यह आसान गाइड है, इसलिए हम jQuery का इस्तेमाल करेंगे.
var CANVAS_WIDTH = 480;
var CANVAS_HEIGHT = 320;
var canvasElement = $("<canvas width='" + CANVAS_WIDTH +
"' height='" + CANVAS_HEIGHT + "'></canvas>");
var canvas = canvasElement.get(0).getContext("2d");
canvasElement.appendTo('body');
गेम लूप
गेमप्ले को बिना किसी रुकावट के और स्मूद तरीके से चलाने के लिए, हम गेम को अपडेट करना चाहते हैं. साथ ही, स्क्रीन को फिर से खींचने की प्रोसेस को इतना तेज़ करना चाहते हैं कि मानव मस्तिष्क और आंखों को यह महसूस न हो.
var FPS = 30;
setInterval(function() {
update();
draw();
}, 1000/FPS);
फ़िलहाल, अपडेट और ड्रॉ करने के तरीकों को खाली छोड़ा जा सकता है. यह जानना ज़रूरी है कि setInterval()
समय-समय पर उन्हें कॉल करता है.
function update() { ... }
function draw() { ... }
नमस्ते दुनिया
अब हमारे पास गेम लूप है, तो स्क्रीन पर कुछ टेक्स्ट खींचने के लिए, अपने ड्रॉ करने के तरीके को अपडेट करते हैं.
function draw() {
canvas.fillStyle = "#000"; // Set color to black
canvas.fillText("Sup Bro!", 50, 50);
}
यह स्टेशनरी टेक्स्ट के लिए काफ़ी अच्छा है. हालांकि, हमारे पास पहले से ही गेम लूप सेट अप है, इसलिए हम इसे आसानी से मूव कर सकते हैं.
var textX = 50;
var textY = 50;
function update() {
textX += 1;
textY += 1;
}
function draw() {
canvas.fillStyle = "#000";
canvas.fillText("Sup Bro!", textX, textY);
}
अब इसे आज़माएं. अगर आपने निर्देशों का पालन किया है, तो यह पैनल स्क्रीन पर दिखेगा. साथ ही, स्क्रीन पर पहले जितनी बार यह पैनल दिखेगा उतनी ही बार यह पैनल स्क्रीन पर दिखेगा. थोड़ा समय निकालकर, यह अनुमान लगाएं कि ऐसा क्यों हो सकता है. ऐसा इसलिए होता है, क्योंकि हम स्क्रीन को साफ़ नहीं कर रहे हैं. इसलिए, आइए ड्रॉ करने के तरीके में स्क्रीन को साफ़ करने का कोड जोड़ते हैं.
function draw() {
canvas.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
canvas.fillStyle = "#000";
canvas.fillText("Sup Bro!", textX, textY);
}
अब आपने स्क्रीन पर कुछ टेक्स्ट घुमाया है, तो इसका मतलब है कि आपने रीयल गेम बनाने की प्रोसेस का आधा हिस्सा पूरा कर लिया है. बस कंट्रोल को बेहतर बनाएं, गेमप्ले को बेहतर बनाएं, और ग्राफ़िक को बेहतर बनाएं. हो सकता है कि यह गेम बनाने का सातवां हिस्सा हो, लेकिन अच्छी बात यह है कि ट्यूटोरियल में इससे ज़्यादा जानकारी दी गई है.
प्लेयर बनाना
खिलाड़ी का डेटा सेव करने और ड्रॉइंग जैसी चीज़ों के लिए ज़िम्मेदार ऑब्जेक्ट बनाएं. यहां हम सारी जानकारी को सेव करने के लिए, एक साधारण ऑब्जेक्ट लिटरल का इस्तेमाल करके प्लेयर ऑब्जेक्ट बनाते हैं.
var player = {
color: "#00A",
x: 220,
y: 270,
width: 32,
height: 32,
draw: function() {
canvas.fillStyle = this.color;
canvas.fillRect(this.x, this.y, this.width, this.height);
}
};
फ़िलहाल, हम प्लेयर को दिखाने के लिए, रंगीन रेक्टैंगल का इस्तेमाल कर रहे हैं. गेम को ड्रॉ करते समय, हम कैनवस को मिटा देंगे और खिलाड़ी को ड्रॉ करेंगे.
function draw() {
canvas.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
player.draw();
}
कीबोर्ड से कंट्रोल करने की सुविधा
jQuery हॉटकी का इस्तेमाल करना
jQuery Hotkeys प्लग इन की मदद से, सभी ब्राउज़र में की को आसानी से मैनेज किया जा सकता है.
क्रॉस-ब्राउज़र keyCode
और
charCode
से जुड़ी समस्याओं को हल करने के बजाय, इवेंट को इस तरह से बांधें:
$(document).bind("keydown", "left", function() { ... });
यह जानना कि किन कुंजियों में कौनसे कोड हैं, इस बारे में चिंता न करना एक बड़ी जीत है. हम बस इतना ही चाहते हैं कि "जब प्लेयर ऊपर वाला बटन दबाए, तो कुछ करें" जैसी बातें कही जा सकें. jQuery Hotkeys की मदद से, ऐसा आसानी से किया जा सकता है.
प्लेयर की गति
JavaScript, कीबोर्ड इवेंट को पूरी तरह से इवेंट के हिसाब से मैनेज करता है. इसका मतलब है कि किसी कुंजी के काम न करने की जांच करने के लिए, कोई पहले से मौजूद क्वेरी नहीं है. इसलिए, हमें अपनी क्वेरी का इस्तेमाल करना होगा.
आपके मन में यह सवाल आ सकता है कि "बटन को मैनेज करने के लिए, इवेंट-ड्रिवन तरीके का इस्तेमाल क्यों नहीं किया जा सकता?" ऐसा इसलिए होता है, क्योंकि कीबोर्ड के बटन दबाने की दर हर सिस्टम में अलग-अलग होती है. यह गेम लूप के समय पर निर्भर नहीं करती. इसलिए, गेमप्ले हर सिस्टम में काफ़ी अलग-अलग हो सकता है. गेम का बेहतर अनुभव देने के लिए, यह ज़रूरी है कि कीबोर्ड इवेंट का पता लगाने की सुविधा को गेम लूप के साथ पूरी तरह से इंटिग्रेट किया गया हो.
अच्छी बात यह है कि मैंने 16 लाइन का एक JS रैपर शामिल किया है, जिससे इवेंट के लिए क्वेरी करने की सुविधा उपलब्ध होगी. इसे key_status.js कहा जाता है. keydown.left
वगैरह की जांच करके, किसी भी समय किसी कुंजी की स्थिति के बारे में क्वेरी की जा सकती है.
अब हमारे पास यह पता करने की सुविधा है कि बटन दबाए गए हैं या नहीं. इसलिए, प्लेयर को एक जगह से दूसरी जगह ले जाने के लिए, अपडेट करने के इस आसान तरीके का इस्तेमाल किया जा सकता है.
function update() {
if (keydown.left) {
player.x -= 2;
}
if (keydown.right) {
player.x += 2;
}
}
इसे आज़माकर देखें.
आपको पता चल सकता है कि प्लेयर को स्क्रीन से हटाया जा सकता है. खिलाड़ी को सीमाओं के अंदर रखने के लिए, उसकी पोज़िशन को क्लैंप करते हैं. इसके अलावा, प्लेयर धीमा है. इसलिए, इसकी स्पीड भी बढ़ा दें.
function update() {
if (keydown.left) {
player.x -= 5;
}
if (keydown.right) {
player.x += 5;
}
player.x = player.x.clamp(0, CANVAS_WIDTH - player.width);
}
ज़्यादा इनपुट जोड़ना भी उतना ही आसान होगा. इसलिए, चलिए कुछ प्रोजेक्टाइल जोड़ते हैं.
function update() {
if (keydown.space) {
player.shoot();
}
if (keydown.left) {
player.x -= 5;
}
if (keydown.right) {
player.x += 5;
}
player.x = player.x.clamp(0, CANVAS_WIDTH - player.width);
}
player.shoot = function() {
console.log("Pew pew");
// :) Well at least adding the key binding was easy...
};
गेम में ज़्यादा ऑब्जेक्ट जोड़ना
प्रोजेक्टाइल
आइए, अब असली प्रोजेक्टाइल जोड़ते हैं. सबसे पहले, हमें एक कलेक्शन बनाना होगा, ताकि हम इन सभी को उसमें सेव कर सकें:
var playerBullets = [];
इसके बाद, हमें बुलेट इंस्टेंस बनाने के लिए एक कन्स्ट्रक्टर की ज़रूरत होगी.
function Bullet(I) {
I.active = true;
I.xVelocity = 0;
I.yVelocity = -I.speed;
I.width = 3;
I.height = 3;
I.color = "#000";
I.inBounds = function() {
return I.x >= 0 && I.x <= CANVAS_WIDTH &&
I.y >= 0 && I.y <= CANVAS_HEIGHT;
};
I.draw = function() {
canvas.fillStyle = this.color;
canvas.fillRect(this.x, this.y, this.width, this.height);
};
I.update = function() {
I.x += I.xVelocity;
I.y += I.yVelocity;
I.active = I.active && I.inBounds();
};
return I;
}
जब खिलाड़ी गोली चलाता है, तो हमें एक बुलेट इंस्टेंस बनाना चाहिए और उसे बुलेट के कलेक्शन में जोड़ना चाहिए.
player.shoot = function() {
var bulletPosition = this.midpoint();
playerBullets.push(Bullet({
speed: 5,
x: bulletPosition.x,
y: bulletPosition.y
}));
};
player.midpoint = function() {
return {
x: this.x + this.width/2,
y: this.y + this.height/2
};
};
अब हमें अपडेट करने के चरण वाले फ़ंक्शन में, बुलेट को अपडेट करने की सुविधा जोड़नी होगी. बुलेट पॉइंट की सूची में अनलिमिटेड बुलेट पॉइंट शामिल होने से रोकने के लिए, हम बुलेट पॉइंट की सूची को फ़िल्टर करते हैं, ताकि सिर्फ़ ऐक्टिव बुलेट पॉइंट शामिल किए जा सकें. इससे, हम उन गोलियों को भी हटा सकते हैं जो किसी दुश्मन से टकराई हैं.
function update() {
...
playerBullets.forEach(function(bullet) {
bullet.update();
});
playerBullets = playerBullets.filter(function(bullet) {
return bullet.active;
});
}
आखिरी चरण में, बुलेट पॉइंट बनाएं:
function draw() {
...
playerBullets.forEach(function(bullet) {
bullet.draw();
});
}
शत्रु
अब हमें बुलेट की तरह ही दुश्मनों को भी जोड़ना है.
enemies = [];
function Enemy(I) {
I = I || {};
I.active = true;
I.age = Math.floor(Math.random() * 128);
I.color = "#A2B";
I.x = CANVAS_WIDTH / 4 + Math.random() * CANVAS_WIDTH / 2;
I.y = 0;
I.xVelocity = 0
I.yVelocity = 2;
I.width = 32;
I.height = 32;
I.inBounds = function() {
return I.x >= 0 && I.x <= CANVAS_WIDTH &&
I.y >= 0 && I.y <= CANVAS_HEIGHT;
};
I.draw = function() {
canvas.fillStyle = this.color;
canvas.fillRect(this.x, this.y, this.width, this.height);
};
I.update = function() {
I.x += I.xVelocity;
I.y += I.yVelocity;
I.xVelocity = 3 * Math.sin(I.age * Math.PI / 64);
I.age++;
I.active = I.active && I.inBounds();
};
return I;
};
function update() {
...
enemies.forEach(function(enemy) {
enemy.update();
});
enemies = enemies.filter(function(enemy) {
return enemy.active;
});
if(Math.random() < 0.1) {
enemies.push(Enemy());
}
};
function draw() {
...
enemies.forEach(function(enemy) {
enemy.draw();
});
}
इमेज लोड करना और उन्हें ड्रॉ करना
इन बॉक्स को उड़ते हुए देखना मज़ेदार है, लेकिन इनके लिए इमेज होना और भी मज़ेदार होगा. कैनवस पर इमेज लोड करना और ड्रॉ करना आम तौर पर मुश्किल होता है. इस परेशानी से बचने के लिए, हम किसी आसान यूटिलिटी क्लास का इस्तेमाल कर सकते हैं.
player.sprite = Sprite("player");
player.draw = function() {
this.sprite.draw(canvas, this.x, this.y);
};
function Enemy(I) {
...
I.sprite = Sprite("enemy");
I.draw = function() {
this.sprite.draw(canvas, this.x, this.y);
};
...
}
टक्कर का पता लगाने की सुविधा
स्क्रीन पर ये सभी आइटम एक-दूसरे के साथ इंटरैक्ट नहीं कर रहे हैं. यह तय करने के लिए कि कब क्या फटेगा, हमें किसी तरह का टक्कर का पता लगाने वाला सिस्टम जोड़ना होगा.
आइए, एक आसान रेक्टैंगल्यूलर कोलिज़न डिटेक्शन एल्गोरिदम का इस्तेमाल करें:
function collides(a, b) {
return a.x < b.x + b.width &&
a.x + a.width > b.x &&
a.y < b.y + b.height &&
a.y + a.height > b.y;
}
हम कुछ ऐसे कॉलिज़न की जांच करना चाहते हैं:
- खिलाड़ी की गोलियां => दुश्मन की जहाज़
- Player => Enemy Ships
आइए, अपडेट करने के तरीके से कॉल किए जा सकने वाले कॉलिज़न को हैंडल करने के लिए एक तरीका बनाते हैं.
function handleCollisions() {
playerBullets.forEach(function(bullet) {
enemies.forEach(function(enemy) {
if (collides(bullet, enemy)) {
enemy.explode();
bullet.active = false;
}
});
});
enemies.forEach(function(enemy) {
if (collides(enemy, player)) {
enemy.explode();
player.explode();
}
});
}
function update() {
...
handleCollisions();
}
अब हमें प्लेयर और दुश्मनों के लिए, विस्फोट करने के तरीके जोड़ने होंगे. इससे उन्हें हटाने के लिए फ़्लैग किया जाएगा और विस्फोट की आवाज़ जोड़ी जाएगी.
function Enemy(I) {
...
I.explode = function() {
this.active = false;
// Extra Credit: Add an explosion graphic
};
return I;
};
player.explode = function() {
this.active = false;
// Extra Credit: Add an explosion graphic and then end the game
};
आवाज़
इस अनुभव को बेहतर बनाने के लिए, हम कुछ बेहतरीन साउंड इफ़ेक्ट जोड़ने जा रहे हैं. इमेज की तरह, साउंड को भी HTML5 में इस्तेमाल करना मुश्किल हो सकता है. हालांकि, हमारे बेहतरीन साउंड.js फ़ॉर्मूला की मदद से, साउंड को आसानी से इस्तेमाल किया जा सकता है.
player.shoot = function() {
Sound.play("shoot");
...
}
function Enemy(I) {
...
I.explode = function() {
Sound.play("explode");
...
}
}
हालांकि, एपीआई अब बिना रुकावट के काम करता है, लेकिन साउंड जोड़ने से आपका ऐप्लिकेशन फटाक से बंद हो सकता है. आम तौर पर, ऐसा होता है कि आवाज़ें बंद हो जाती हैं या ब्राउज़र का पूरा टैब बंद हो जाता है. इसलिए, अपने टिश्यू तैयार रखें.
Farewell
फिर से, यहां गेम का पूरा डेमो दिया गया है. सोर्स कोड को ज़िप के तौर पर भी डाउनलोड किया जा सकता है.
हमें उम्मीद है कि आपको JavaScript और HTML5 में आसान गेम बनाने की बुनियादी बातें सीखने में मज़ा आया होगा. एब्स्ट्रैक्शन के सही लेवल पर प्रोग्रामिंग करके, हम एपीआई के मुश्किल हिस्सों से खुद को बचा सकते हैं. साथ ही, आने वाले समय में होने वाले बदलावों के हिसाब से भी खुद को तैयार रख सकते हैं.