23 KiB
स्पेस गेम तयार करा भाग ३: गती जोडणे
पूर्व-व्याख्यान प्रश्नमंजुषा
गेम्स मजेदार होण्यासाठी स्क्रीनवर एलियन्स फिरणे आवश्यक आहे! या गेममध्ये आपण दोन प्रकारच्या हालचालींचा वापर करू:
- कीबोर्ड/माऊस हालचाल: जेव्हा वापरकर्ता कीबोर्ड किंवा माऊस वापरून स्क्रीनवरील वस्तू हलवतो.
- गेम-प्रेरित हालचाल: जेव्हा गेम विशिष्ट वेळेच्या अंतराने वस्तू हलवतो.
तर स्क्रीनवर वस्तू कशा हलवायच्या? हे सर्व कार्टेशियन कोऑर्डिनेट्सवर आधारित आहे: आपण वस्तूचे स्थान (x, y) बदलतो आणि नंतर स्क्रीन पुन्हा रेखाटतो.
सामान्यतः स्क्रीनवर हालचाल साध्य करण्यासाठी तुम्हाला खालील चरणांची आवश्यकता असते:
- नवीन स्थान सेट करा: वस्तू हलवलेली असल्याचे जाणवण्यासाठी हे आवश्यक आहे.
- स्क्रीन साफ करा: स्क्रीन पुन्हा रेखाटण्याच्या दरम्यान साफ करणे आवश्यक आहे. आपण पार्श्वभूमी रंगाने भरलेला आयत रेखाटून स्क्रीन साफ करू शकतो.
- नवीन स्थानावर वस्तू पुन्हा रेखाटणे: असे केल्याने आपण वस्तू एका स्थानावरून दुसऱ्या स्थानावर हलवणे साध्य करतो.
कोडमध्ये हे असे दिसू शकते:
//set the hero's location
hero.x += 5;
// clear the rectangle that hosts the hero
ctx.clearRect(0, 0, canvas.width, canvas.height);
// redraw the game background and hero
ctx.fillRect(0, 0, canvas.width, canvas.height)
ctx.fillStyle = "black";
ctx.drawImage(heroImg, hero.x, hero.y);
✅ तुम्ही विचार करू शकता का की तुमच्या हिरोला अनेक फ्रेम्स प्रति सेकंद पुन्हा रेखाटल्यामुळे कार्यक्षमतेवर काही परिणाम होऊ शकतो? या पद्धतीचे पर्याय वाचा.
कीबोर्ड इव्हेंट्स हाताळा
तुम्ही विशिष्ट इव्हेंट्सना कोडशी जोडून इव्हेंट्स हाताळता. कीबोर्ड इव्हेंट्स संपूर्ण विंडोवर ट्रिगर होतात, तर माऊस इव्हेंट्स जसे की click
विशिष्ट घटकावर क्लिक करण्याशी जोडले जाऊ शकतात. आपण या प्रकल्पात कीबोर्ड इव्हेंट्स वापरणार आहोत.
इव्हेंट हाताळण्यासाठी तुम्हाला विंडोच्या addEventListener()
पद्धतीचा वापर करावा लागतो आणि त्याला दोन इनपुट पॅरामीटर्स द्यावे लागतात. पहिला पॅरामीटर इव्हेंटचे नाव आहे, उदाहरणार्थ keyup
. दुसरा पॅरामीटर म्हणजे इव्हेंट घडल्यामुळे कॉल होणारी फंक्शन.
उदाहरण येथे आहे:
window.addEventListener('keyup', (evt) => {
// `evt.key` = string representation of the key
if (evt.key === 'ArrowUp') {
// do something
}
})
की इव्हेंट्ससाठी इव्हेंटवर दोन गुणधर्म असतात ज्याचा वापर तुम्ही कोणती की दाबली आहे हे पाहण्यासाठी करू शकता:
key
: ही दाबलेल्या कीची स्ट्रिंग प्रतिनिधित्व आहे, उदाहरणार्थArrowUp
keyCode
: ही संख्या प्रतिनिधित्व आहे, उदाहरणार्थ37
, ज्याचा संबंधArrowLeft
शी आहे.
✅ की इव्हेंट्सचे हेरफेर गेम डेव्हलपमेंटच्या बाहेर उपयुक्त आहे. या तंत्राचा आणखी कोणत्या उपयोगासाठी विचार करू शकता?
विशेष की: एक सावधगिरी
काही विशेष की आहेत ज्या विंडोवर परिणाम करतात. याचा अर्थ असा की जर तुम्ही keyup
इव्हेंट ऐकत असाल आणि तुम्ही तुमच्या हिरोला हलवण्यासाठी या विशेष की वापरत असाल तर ते क्षैतिज स्क्रोलिंग देखील करेल. त्यामुळे तुम्हाला तुमचा गेम तयार करताना हे अंगभूत ब्राउझर वर्तन बंद करायचे असेल. तुम्हाला अशा प्रकारचा कोड आवश्यक आहे:
let onKeyDown = function (e) {
console.log(e.keyCode);
switch (e.keyCode) {
case 37:
case 39:
case 38:
case 40: // Arrow keys
case 32:
e.preventDefault();
break; // Space
default:
break; // do not block other keys
}
};
window.addEventListener('keydown', onKeyDown);
वरील कोड सुनिश्चित करेल की अॅरो-की आणि स्पेस कीचे डिफॉल्ट वर्तन बंद केले आहे. बंद यंत्रणा e.preventDefault()
कॉल केल्यावर होते.
गेम-प्रेरित हालचाल
आपण setTimeout()
किंवा setInterval()
सारख्या टाइमर्सचा वापर करून वस्तू स्वतःच हलवू शकतो, जे प्रत्येक टिक किंवा वेळेच्या अंतराने वस्तूचे स्थान अपडेट करतात. हे असे दिसू शकते:
let id = setInterval(() => {
//move the enemy on the y axis
enemy.y += 10;
})
गेम लूप
गेम लूप ही एक संकल्पना आहे जी मूलतः एका नियमित अंतराने कॉल होणारी फंक्शन आहे. याला गेम लूप म्हणतात कारण वापरकर्त्याला दिसणारे सर्व काही लूपमध्ये रेखाटले जाते. गेम लूप गेमचा भाग असलेल्या सर्व गेम ऑब्जेक्ट्सचा वापर करते, त्यापैकी सर्व रेखाटते, जोपर्यंत काही कारणास्तव गेमचा भाग राहू नये. उदाहरणार्थ, जर एखादी वस्तू शत्रू असेल जी लेसरने हिट झाली आणि फुटली, तर ती सध्याच्या गेम लूपचा भाग राहणार नाही (तुम्ही याबद्दल पुढील धड्यांमध्ये अधिक शिकाल).
गेम लूप सामान्यतः कोडमध्ये कसे दिसते ते येथे आहे:
let gameLoopId = setInterval(() =>
function gameLoop() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawHero();
drawEnemies();
drawStaticObjects();
}, 200);
वरील लूप प्रत्येक 200
मिलिसेकंदांनी कॅनव्हास पुन्हा रेखाटण्यासाठी कॉल केला जातो. तुमच्या गेमसाठी योग्य वाटणारे सर्वोत्तम अंतर निवडण्याची क्षमता तुमच्याकडे आहे.
स्पेस गेम सुरू ठेवणे
तुम्ही विद्यमान कोड घेऊन त्याचा विस्तार कराल. भाग I मध्ये पूर्ण केलेल्या कोडसह सुरू करा किंवा भाग II- स्टार्टर मधील कोड वापरा.
- हिरो हलवणे: तुम्ही अॅरो की वापरून हिरो हलवता येईल याची खात्री करण्यासाठी कोड जोडाल.
- शत्रू हलवणे: तुम्हाला शत्रू वरून खाली दिलेल्या दराने हलवता येतील याची खात्री करण्यासाठी कोड जोडणे आवश्यक आहे.
शिफारस केलेले चरण
your-work
उपफोल्डरमध्ये तयार केलेल्या फाइल्स शोधा. त्यात खालील गोष्टी असाव्यात:
-| assets
-| enemyShip.png
-| player.png
-| index.html
-| app.js
-| package.json
तुमचा प्रकल्प your_work
फोल्डरमध्ये सुरू करण्यासाठी टाइप करा:
cd your-work
npm start
वरील HTTP सर्व्हर http://localhost:5000
पत्त्यावर सुरू करेल. ब्राउझर उघडा आणि तो पत्ता इनपुट करा, सध्या ते हिरो आणि सर्व शत्रूंना रेंडर करेल; काहीही हलत नाही - अजून!
कोड जोडा
-
hero
,enemy
आणिgame object
साठी समर्पित ऑब्जेक्ट्स जोडा, त्यांच्याकडेx
आणिy
गुणधर्म असावेत. (Inheritance किंवा composition याबद्दलच्या भागाची आठवण ठेवा).सूचना:
game object
हाx
आणिy
असलेला आणि स्वतःला कॅनव्हासवर रेखाटण्याची क्षमता असलेला असावा.सूचना: खाली दिलेल्या प्रकारे त्याचा कन्स्ट्रक्टर परिभाषित करून नवीन GameObject क्लास जोडा आणि नंतर कॅनव्हासवर रेखाट:
class GameObject { constructor(x, y) { this.x = x; this.y = y; this.dead = false; this.type = ""; this.width = 0; this.height = 0; this.img = undefined; } draw(ctx) { ctx.drawImage(this.img, this.x, this.y, this.width, this.height); } }
आता, या GameObject चा विस्तार करून हिरो आणि शत्रू तयार करा.
class Hero extends GameObject { constructor(x, y) { ...it needs an x, y, type, and speed } }
class Enemy extends GameObject { constructor(x, y) { super(x, y); (this.width = 98), (this.height = 50); this.type = "Enemy"; let id = setInterval(() => { if (this.y < canvas.height - this.height) { this.y += 5; } else { console.log('Stopped at', this.y) clearInterval(id); } }, 300) } }
-
की-इव्हेंट हँडलर्स जोडा की नेव्हिगेशन हाताळण्यासाठी (हिरो वर/खाली डाव्या/उजव्या बाजूला हलवा)
लक्षात ठेवा: हे कार्टेशियन सिस्टम आहे, टॉप-लेफ्ट
0,0
आहे. तसेच डिफॉल्ट वर्तन थांबवण्यासाठी कोड जोडण्याची आठवण ठेवा.सूचना: तुमची onKeyDown फंक्शन तयार करा आणि ती विंडोशी जोडा:
let onKeyDown = function (e) { console.log(e.keyCode); ...add the code from the lesson above to stop default behavior } }; window.addEventListener("keydown", onKeyDown);
या टप्प्यावर तुमच्या ब्राउझर कन्सोलमध्ये तपासा आणि की दाबल्यावर लॉगिंग पहा.
-
Pub sub pattern लागू करा, यामुळे तुमचा कोड स्वच्छ राहील कारण तुम्ही उर्वरित भागांचे अनुसरण कराल.
हे शेवटचे भाग करण्यासाठी, तुम्ही:
-
विंडोवर इव्हेंट लिसनर जोडा:
window.addEventListener("keyup", (evt) => { if (evt.key === "ArrowUp") { eventEmitter.emit(Messages.KEY_EVENT_UP); } else if (evt.key === "ArrowDown") { eventEmitter.emit(Messages.KEY_EVENT_DOWN); } else if (evt.key === "ArrowLeft") { eventEmitter.emit(Messages.KEY_EVENT_LEFT); } else if (evt.key === "ArrowRight") { eventEmitter.emit(Messages.KEY_EVENT_RIGHT); } });
-
EventEmitter क्लास तयार करा संदेश प्रकाशित आणि सबस्क्राइब करण्यासाठी:
class EventEmitter { constructor() { this.listeners = {}; } on(message, listener) { if (!this.listeners[message]) { this.listeners[message] = []; } this.listeners[message].push(listener); } emit(message, payload = null) { if (this.listeners[message]) { this.listeners[message].forEach((l) => l(message, payload)); } } }
-
Constants जोडा आणि EventEmitter सेट करा:
const Messages = { KEY_EVENT_UP: "KEY_EVENT_UP", KEY_EVENT_DOWN: "KEY_EVENT_DOWN", KEY_EVENT_LEFT: "KEY_EVENT_LEFT", KEY_EVENT_RIGHT: "KEY_EVENT_RIGHT", }; let heroImg, enemyImg, laserImg, canvas, ctx, gameObjects = [], hero, eventEmitter = new EventEmitter();
-
गेम सुरू करा
function initGame() { gameObjects = []; createEnemies(); createHero(); eventEmitter.on(Messages.KEY_EVENT_UP, () => { hero.y -=5 ; }) eventEmitter.on(Messages.KEY_EVENT_DOWN, () => { hero.y += 5; }); eventEmitter.on(Messages.KEY_EVENT_LEFT, () => { hero.x -= 5; }); eventEmitter.on(Messages.KEY_EVENT_RIGHT, () => { hero.x += 5; }); }
-
-
गेम लूप सेट करा
window.onload फंक्शनला रिफॅक्टर करा गेम सुरू करण्यासाठी आणि चांगल्या अंतरावर गेम लूप सेट करण्यासाठी. तुम्ही लेसर बीम देखील जोडाल:
window.onload = async () => { canvas = document.getElementById("canvas"); ctx = canvas.getContext("2d"); heroImg = await loadTexture("assets/player.png"); enemyImg = await loadTexture("assets/enemyShip.png"); laserImg = await loadTexture("assets/laserRed.png"); initGame(); let gameLoopId = setInterval(() => { ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.fillStyle = "black"; ctx.fillRect(0, 0, canvas.width, canvas.height); drawGameObjects(ctx); }, 100) };
-
शत्रूंना विशिष्ट अंतरावर हलवण्यासाठी कोड जोडा
createEnemies()
फंक्शनला रिफॅक्टर करा शत्रू तयार करण्यासाठी आणि त्यांना नवीन gameObjects क्लासमध्ये पुश करण्यासाठी:function createEnemies() { const MONSTER_TOTAL = 5; const MONSTER_WIDTH = MONSTER_TOTAL * 98; const START_X = (canvas.width - MONSTER_WIDTH) / 2; const STOP_X = START_X + MONSTER_WIDTH; for (let x = START_X; x < STOP_X; x += 98) { for (let y = 0; y < 50 * 5; y += 50) { const enemy = new Enemy(x, y); enemy.img = enemyImg; gameObjects.push(enemy); } } }
आणि हिरोसाठी समान प्रक्रिया करण्यासाठी
createHero()
फंक्शन जोडा.function createHero() { hero = new Hero( canvas.width / 2 - 45, canvas.height - canvas.height / 4 ); hero.img = heroImg; gameObjects.push(hero); }
आणि शेवटी, रेखाटणे सुरू करण्यासाठी
drawGameObjects()
फंक्शन जोडा:function drawGameObjects(ctx) { gameObjects.forEach(go => go.draw(ctx)); }
तुमचे शत्रू तुमच्या हिरो स्पेसशिपवर पुढे सरकायला सुरुवात करतील!
🚀 आव्हान
जसे तुम्ही पाहू शकता, तुमचा कोड 'स्पॅगेटी कोड' मध्ये बदलू शकतो जेव्हा तुम्ही फंक्शन्स, व्हेरिएबल्स आणि क्लासेस जोडायला सुरुवात करता. तुमचा कोड अधिक वाचनीय होण्यासाठी तुम्ही तो कसा चांगल्या प्रकारे आयोजित करू शकता? तुमचा कोड आयोजित करण्यासाठी एक प्रणाली तयार करा, जरी तो अजूनही एका फाइलमध्ये असला तरी.
व्याख्यानानंतर प्रश्नमंजुषा
पुनरावलोकन आणि स्व-अभ्यास
जरी आपण फ्रेमवर्कशिवाय आपला गेम लिहित आहोत, तरी गेम डेव्हलपमेंटसाठी अनेक जावास्क्रिप्ट-आधारित कॅनव्हास फ्रेमवर्क आहेत. याबद्दल वाचन करा.
असाइनमेंट
अस्वीकरण:
हा दस्तऐवज AI भाषांतर सेवा Co-op Translator वापरून भाषांतरित करण्यात आला आहे. आम्ही अचूकतेसाठी प्रयत्नशील असलो तरी कृपया लक्षात ठेवा की स्वयंचलित भाषांतरांमध्ये त्रुटी किंवा अचूकतेचा अभाव असू शकतो. मूळ भाषेतील दस्तऐवज हा अधिकृत स्रोत मानला जावा. महत्त्वाच्या माहितीसाठी व्यावसायिक मानवी भाषांतराची शिफारस केली जाते. या भाषांतराचा वापर करून उद्भवलेल्या कोणत्याही गैरसमज किंवा चुकीच्या अर्थासाठी आम्ही जबाबदार राहणार नाही.