14 KiB
Jenga Mchezo wa Anga Sehemu ya 3: Kuongeza Mwendo
Jaribio la Kabla ya Somo
Michezo haiwi ya kufurahisha sana hadi pale unapokuwa na viumbe wa kigeni wakizunguka kwenye skrini! Katika mchezo huu, tutatumia aina mbili za mwendo:
- Mwendo wa Kibodi/Panya: pale mtumiaji anaposhirikiana na kibodi au panya ili kusogeza kitu kwenye skrini.
- Mwendo unaosababishwa na mchezo: pale mchezo unapohamisha kitu kwa muda maalum.
Kwa hiyo, tunahamishaje vitu kwenye skrini? Yote inahusu kuratibu kwa kutumia mfumo wa Cartesian: tunabadilisha eneo (x, y) la kitu na kisha kuchora tena skrini.
Kwa kawaida, unahitaji hatua zifuatazo ili kufanikisha mwendo kwenye skrini:
- Weka eneo jipya la kitu; hii inahitajika ili kuonekana kama kitu kimesogea.
- Futa skrini, skrini inahitaji kufutwa kati ya michoro. Tunaweza kuifuta kwa kuchora mstatili na kuujaza kwa rangi ya mandharinyuma.
- Chora tena kitu kwenye eneo jipya. Kwa kufanya hivi, tunafanikisha kusogeza kitu kutoka eneo moja hadi jingine.
Hivi ndivyo inavyoweza kuonekana kwenye msimbo:
//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);
✅ Je, unaweza kufikiria sababu kwa nini kuchora tena shujaa wako mara nyingi kwa sekunde kunaweza kusababisha gharama za utendaji? Soma kuhusu mbadala wa muundo huu.
Kushughulikia Matukio ya Kibodi
Unashughulikia matukio kwa kuambatanisha matukio maalum na msimbo. Matukio ya kibodi huchochewa kwenye dirisha lote wakati matukio ya panya kama click
yanaweza kuunganishwa na kubofya kipengele maalum. Tutatumia matukio ya kibodi katika mradi huu wote.
Ili kushughulikia tukio, unahitaji kutumia njia ya addEventListener()
ya dirisha na kuipatia vigezo viwili vya pembejeo. Kigezo cha kwanza ni jina la tukio, kwa mfano keyup
. Kigezo cha pili ni kazi ambayo inapaswa kuitwa kama matokeo ya tukio kutokea.
Hapa kuna mfano:
window.addEventListener('keyup', (evt) => {
// `evt.key` = string representation of the key
if (evt.key === 'ArrowUp') {
// do something
}
})
Kwa matukio ya funguo, kuna mali mbili kwenye tukio unazoweza kutumia kuona ni funguo gani ilibonyezwa:
key
, hii ni uwakilishi wa kamba wa funguo iliyobonyezwa, kwa mfanoArrowUp
keyCode
, hii ni uwakilishi wa nambari, kwa mfano37
, inahusiana naArrowLeft
.
✅ Udhibiti wa matukio ya funguo ni muhimu hata nje ya maendeleo ya michezo. Je, unaweza kufikiria matumizi mengine ya mbinu hii?
Funguo Maalum: Tahadhari
Kuna funguo zingine maalum ambazo huathiri dirisha. Hii inamaanisha kuwa ikiwa unasikiliza tukio la keyup
na unatumia funguo hizi maalum kusogeza shujaa wako, pia itasababisha kurasa kusogea kwa usawa. Kwa sababu hiyo, unaweza kutaka kuzima tabia hii ya kawaida ya kivinjari unapojenga mchezo wako. Unahitaji msimbo kama huu:
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);
Msimbo hapo juu utahakikisha kuwa funguo za mishale na funguo ya nafasi zimezimwa tabia yao ya kawaida. Utaratibu wa kuzima hutokea tunapopiga e.preventDefault()
.
Mwendo Unaosababishwa na Mchezo
Tunaweza kufanya vitu visogee vyenyewe kwa kutumia vipima muda kama vile kazi ya setTimeout()
au setInterval()
ambayo inasasisha eneo la kitu kwa kila muda maalum. Hivi ndivyo inavyoweza kuonekana:
let id = setInterval(() => {
//move the enemy on the y axis
enemy.y += 10;
})
Mzunguko wa Mchezo
Mzunguko wa mchezo ni dhana ambayo kimsingi ni kazi inayochochewa kwa vipindi vya kawaida. Unaitwa mzunguko wa mchezo kwa sababu kila kitu kinachopaswa kuonekana kwa mtumiaji kinachorwa ndani ya mzunguko. Mzunguko wa mchezo hutumia vitu vyote vya mchezo ambavyo ni sehemu ya mchezo, kuchora vyote isipokuwa kwa sababu fulani havipaswi kuwa sehemu ya mchezo tena. Kwa mfano, ikiwa kitu ni adui aliyepigwa na miale ya laser na kulipuka, hakipo tena katika mzunguko wa sasa wa mchezo (utajifunza zaidi kuhusu hili katika masomo yanayofuata).
Hivi ndivyo mzunguko wa mchezo unavyoweza kuonekana, ukiwakilishwa kwa msimbo:
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);
Mzunguko hapo juu unachochewa kila baada ya milisekunde 200
ili kuchora tena canvas. Una uwezo wa kuchagua muda bora unaofaa kwa mchezo wako.
Kuendelea na Mchezo wa Anga
Utachukua msimbo uliopo na kuupanua. Ama anza na msimbo uliokamilisha wakati wa sehemu ya I au tumia msimbo katika Sehemu ya II - mwanzo.
- Kusogeza shujaa: utaongeza msimbo kuhakikisha unaweza kusogeza shujaa kwa kutumia funguo za mishale.
- Kusogeza maadui: pia utahitaji kuongeza msimbo kuhakikisha maadui wanasogea kutoka juu kwenda chini kwa kasi fulani.
Hatua Zinazopendekezwa
Tafuta faili ambazo zimeundwa kwa ajili yako kwenye folda ndogo ya your-work
. Inapaswa kuwa na yafuatayo:
-| assets
-| enemyShip.png
-| player.png
-| index.html
-| app.js
-| package.json
Anzisha mradi wako kwenye folda ya your_work
kwa kuandika:
cd your-work
npm start
Hii itaanzisha Seva ya HTTP kwenye anwani http://localhost:5000
. Fungua kivinjari na uweke anwani hiyo, kwa sasa inapaswa kuonyesha shujaa na maadui wote; hakuna kinachosogea - bado!
Ongeza Msimbo
-
Ongeza vitu maalum kwa
hero
,enemy
, nagame object
, vinapaswa kuwa na mali zax
nay
. (Kumbuka sehemu kuhusu Urithi au muundo).KIDOKEZO
game object
inapaswa kuwa nax
nay
na uwezo wa kujichora kwenye canvas.kidokezo: anza kwa kuongeza darasa jipya la GameObject na mjengo wake kama ifuatavyo, kisha ichore kwenye canvas:
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); } }
Sasa, panua GameObject ili kuunda Hero na Enemy.
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) } }
-
Ongeza vishughulikia matukio ya funguo kushughulikia urambazaji wa funguo (sogeza shujaa juu/chini kushoto/kulia).
KUMBUKA ni mfumo wa Cartesian, kona ya juu-kushoto ni
0,0
. Pia kumbuka kuongeza msimbo wa kusimamisha tabia ya kawaida.kidokezo: unda kazi yako ya onKeyDown na uambatanishe kwenye dirisha:
let onKeyDown = function (e) { console.log(e.keyCode); ...add the code from the lesson above to stop default behavior } }; window.addEventListener("keydown", onKeyDown);
Angalia koni ya kivinjari chako kwa wakati huu, na uangalie funguo zinazobonyezwa zikiripotiwa.
-
Tekeleza Mfumo wa Pub sub, hii itahakikisha msimbo wako unasalia safi unapofuata sehemu zinazobaki.
Ili kufanya sehemu hii ya mwisho, unaweza:
-
Ongeza msikilizaji wa tukio kwenye dirisha:
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); } });
-
Unda darasa la EventEmitter kuchapisha na kujiandikisha kwa ujumbe:
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)); } } }
-
Ongeza vigezo vya kudumu na usanidi 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();
-
Anzisha mchezo
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; }); }
-
-
Sanidi mzunguko wa mchezo
Rekebisha kazi ya window.onload ili kuanzisha mchezo na kusanidi mzunguko wa mchezo kwa muda mzuri. Pia utaongeza miale ya laser:
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) };
-
Ongeza msimbo wa kusogeza maadui kwa muda fulani
Rekebisha kazi ya
createEnemies()
ili kuunda maadui na kuwasukuma kwenye darasa jipya la 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); } } }
na ongeza kazi ya
createHero()
kufanya mchakato sawa kwa shujaa.function createHero() { hero = new Hero( canvas.width / 2 - 45, canvas.height - canvas.height / 4 ); hero.img = heroImg; gameObjects.push(hero); }
na hatimaye, ongeza kazi ya
drawGameObjects()
ili kuanza kuchora:function drawGameObjects(ctx) { gameObjects.forEach(go => go.draw(ctx)); }
Maadui wako wanapaswa kuanza kusonga kuelekea kwenye chombo cha anga cha shujaa wako!
🚀 Changamoto
Kama unavyoona, msimbo wako unaweza kuwa 'msimbo wa tambi' unapoongeza kazi, vigezo, na madarasa. Unawezaje kupanga msimbo wako vizuri zaidi ili uwe rahisi kusoma? Chora mfumo wa kupanga msimbo wako, hata kama bado unakaa kwenye faili moja.
Jaribio la Baada ya Somo
Mapitio na Kujisomea
Ingawa tunaandika mchezo wetu bila kutumia mifumo, kuna mifumo mingi ya JavaScript inayotegemea canvas kwa ajili ya maendeleo ya michezo. Chukua muda kufanya usomaji kuhusu hizi.
Kazi
Kanusho:
Hati hii imetafsiriwa kwa kutumia huduma ya kutafsiri ya AI Co-op Translator. Ingawa tunajitahidi kuhakikisha usahihi, tafadhali fahamu kuwa tafsiri za kiotomatiki zinaweza kuwa na makosa au kutokuwa sahihi. Hati ya asili katika lugha yake ya awali inapaswa kuzingatiwa kama chanzo cha mamlaka. Kwa taarifa muhimu, tafsiri ya kitaalamu ya binadamu inapendekezwa. Hatutawajibika kwa kutoelewana au tafsiri zisizo sahihi zinazotokana na matumizi ya tafsiri hii.