Phaser 3, Express va Socket.IO bilan ko'p o'yinchi karta o'yinini qanday qurish mumkin

Men stol usti o'yinlarini ishlab chiqaruvchiman va doimiy ravishda o'yin tajribasini raqamlashtirish usullarini qidiraman. Ushbu qo'llanmada biz Phaser 3, Express va Socket.IO yordamida ko'p o'yinchi karta o'yini qurmoqchimiz.

Old shartlar bo'yicha siz mashinangizda Node/NPM va Git o'rnatilgan va sozlanganligiga ishonch hosil qilishni xohlaysiz. JavaScript bilan ishlash tajribasi foydali bo'ladi va siz buni hal qilishdan oldin Phaser -ning asosiy qo'llanmasidan o'tishingiz mumkin.

Mavzu bo'yicha darslik uchun Skott Westoverga katta rahmat, Kal_Torak va Phaser hamjamiyati mening barcha savollarimga javob bergani uchun va mening yaxshi do'stim Mayk bu loyihaning me'morchiligini tushunishga yordam bergani uchun.

Eslatma: biz " Entromancy: Hacker Battles" karta o'yinining aktivlari va ranglaridan foydalanamiz . Agar xohlasangiz, o'zingizning rasmlaringiz (yoki hatto Phaser to'rtburchaklar) va ranglardan foydalanishingiz mumkin va siz GitHub -dagi butun loyiha kodiga kirishingiz mumkin.

Agar siz ko'proq vizual darslikni xohlasangiz, ushbu maqolaning hamrohlik qilgan videosini kuzatib borishingiz mumkin:

Qani boshladik!

Oyin

Bizning oddiy karta o'yinimizda Phaser mijozi bo'ladi, u o'yin mantig'ining ko'p qismini boshqaradi va kartalar bilan ishlash, tortish-tushirish funksiyasini ta'minlash va hokazo.

Orqa tomonda biz mijozlar o'rtasida muloqot qilish uchun Socket.IO-dan foydalanadigan ekspress-serverni aylantiramiz va shunday qilamizki, bitta o'yinchi kartani o'ynasa, u boshqa o'yinchining mijozida ko'rinadi va aksincha.

Ushbu loyihadan maqsadimiz - ko'p o'yinchi karta o'yinining asosiy asosini yaratish, uni siz o'z o'yiningiz mantig'iga moslashtira olasiz.

Birinchidan, mijoz bilan shug'ullanamiz!

Mijoz

Mijozni isbotlash uchun biz GitHub-da Phaser 3 veb-paketining yarim rasmiy shablonini klonlaymiz.

Sevimli buyruq qatori interfeysini oching va yangi papka yarating:

Git loyihasini klonlash:

Bu buyruq shablonni "multipaser-card-project" ichida "phaser3-project-template" nomli papkaga yuklaydi. Agar siz bizning o'quv qo'llanmamizning fayl tuzilishini kuzatmoqchi bo'lsangiz, davom eting va shablon papkasining nomini "mijoz" deb o'zgartiring.

Yangi katalogga o'ting va barcha bog'liqliklarni o'rnating:

Sizning loyiha papkasining tuzilishi shunday bo'lishi kerak:

Fayllarni yig'ishdan oldin, CLI -ga qaytamiz va /client papkasida quyidagi buyruqni kiritamiz:

Bizning Phaser shablonimiz mahalliy serverni ishga tushirish uchun Webpack -dan foydalanadi, bu esa o'z navbatida bizning brauzerimizda oddiy o'yinlar dasturiga xizmat qiladi (odatda http: // localhost: 8080). Pokiza!

Loyihamizni sevimli kod muharririda ochamiz va karta o'yinimizga mos keladigan ba'zi o'zgartirishlar kiritamiz. /Client/src/aktivlaridagi hamma narsani o'chirib tashlang va ularni GitHub -dan karta tasvirlari bilan almashtiring.

/Client /src katalogiga "sahnalar" va boshqasini "yordamchilar" deb nomlangan papkani qo'shing.

/Client/src/scenes -da "game.js" deb nomlangan bo'sh faylni qo'shing.

/Client/src/helpers -ga uchta bo'sh faylni qo'shing: "card.js", "dealer.js" va "zone.js".

Sizning loyiha tuzilmangiz endi shunday bo'lishi kerak:

Ajoyib! Sizning mijozingiz sizni xatolarga yo'l qo'yishi mumkin, chunki biz ba'zi narsalarni o'chirib tashladik, lekin xavotir olmang. /Src/index.js -ni oching, bu bizning oldingi ilovamizning asosiy kirish nuqtasi. Quyidagi kodni kiriting:

Biz bu erda qilgan ishimiz, hamma narsani bitta faylda to'plashga urinishdan ko'ra, o'yin sahnalarini ajratishimiz uchun, Phaser -ning "sahna" tizimini ishlatish uchun qozon panelini qayta qurish. Agar siz bir nechta o'yin dunyosini yaratayotgan bo'lsangiz, ko'rsatmalar ekrani kabi narsalarni qurayotgan bo'lsangiz yoki umuman tartibni saqlashga harakat qilsangiz, sahnalar foydali bo'lishi mumkin.

Keling, /src/scenes/game.js ga o'tamiz va ba'zi kodlarni yozamiz:

Biz oldindan yuklash (), yaratish () va yangilash () funktsiyalarini o'z ichiga olgan yangi O'yin sahnasini yaratish uchun ES6 sinflaridan foydalanamiz.

preload () ishlatiladi. yaxshi O'yinimiz uchun foydalanadigan barcha aktivlarni oldindan yuklang.

create () o'yin boshlanganda ishga tushadi va bu erda biz ko'p foydalanuvchilar interfeysi va o'yin mantig'ini o'rnatamiz.

update () har bir kvadrat uchun bir marta chaqiriladi va biz uni darsimizda ishlatmaymiz (lekin bu sizning talablaringizga qarab o'z o'yiningizda foydali bo'lishi mumkin).

Create () funktsiyasida biz "DEAL CARDS" degan matnni yaratdik va uni interaktiv qilib o'rnatdik:

Juda zo'r. Keling, hamma narsa ishga tushganidan keyin qanday ishlashini xohlashimizni tushunish uchun biroz joy kodi kodini yarataylik. Create () funktsiyasiga quyidagilarni qo'shing:

Biz juda ko'p tuzilmani qo'shdik, lekin ko'p narsa sodir bo'lmadi. Endi sichqonchamiz "DEAL CARDS" matni ustida turganida, u pushti pushti rangda ajratilgan va ekranda tasodifiy karta bor:

Biz tasvirni (300, 300) (x, y) koordinatalariga joylashtirdik, uning masshtabini biroz kichik qilib o'rnatdik va interaktiv va sudrab yuradigan qilib qo'ydik. Biz sudralganda nima bo'lishi kerakligini aniqlash uchun biroz mantiq qo'shdik: u sichqonchamizning (x, y) koordinatalariga amal qilishi kerak.

Biz, shuningdek, "DEAL CARDS" matnini bosganimizda chaqiriladigan bo'sh dealCards () funktsiyasini yaratdik. Bundan tashqari, biz "bu" ni - hozirda ishlayotgan sahnani - "o'z" deb nomlangan o'zgaruvchiga saqladik, shunda biz uni o'z vazifalarimiz davomida ko'lami haqida qayg'urmasdan ishlata olamiz.

Bizning o'yin sahnamiz tezda buzilib ketadi, agar biz harakatni boshlamasak, shuning uchun "this.card" bilan boshlangan kod blokini o'chirib tashlaymiz va yozish uchun /src/helpers/card.js manziliga o'tamiz:

Biz sahnani parametr sifatida qabul qiladigan va (x, y) koordinatalarini va spritni qabul qiladigan render () funktsiyasiga ega bo'lgan yangi sinf yaratdik. Endi biz bu funktsiyani boshqa joydan chaqirib, kartalarni yaratish uchun kerakli parametrlarni berishimiz mumkin.

Keling, o'yin sahnasining yuqori qismidagi kartani import qilaylik:

Bizning bo'sh dealCards () funktsiyasiga quyidagi kodni kiriting:

"DEAL CARDS" tugmachasini bosganimizda, endi biz kartalarni yaratadigan va ularni ketma -ket ekranda ko'rsatadigan for loop orqali takrorlaymiz:

ZO'R. Biz bu kartalarni ekran bo'ylab harakatlantira olamiz, lekin o'yin mantig'ini qo'llab -quvvatlash uchun ularni qaerga tashlab qo'yish mumkinligini cheklash yaxshi bo'lardi.

Keling, /src/helpers/zone.js ga o'tamiz va yangi sinf qo'shamiz:

Phaser-da o'rnatilgan o'yin zonalari mavjud bo'lib, ular bizga o'yin ob'ektlarini qaerga qo'yish kerakligini belgilashga imkon beradi va biz bu erda uni o'rnatdik va unga kontur taqdim etdik. Shuningdek, biz "kartalar" deb nomlangan kichik ma'lumotlarni qo'shib qo'ydik.

Keling, yangi zonamizni O'yin sahnasiga kiritamiz:

Va uni create () funktsiyasida chaqiring:

Kartalarni zonaga qanday tushirish kerakligini aniqlash uchun biz biroz mantiq qo'shishimiz kerak. Keling, buni "this.input.on (" tortish ") funksiyasi ostida bajaramiz:

Kodning pastki qismidan boshlab, kartani tashlaganimizda, biz "zonalar" ma'lumotlarining qiymatini ko'paytiramiz va kartaning (x, y) koordinatalarini, qancha karta borligiga qarab, tomchi zonaga belgilaymiz. . Shuningdek, biz kartalarni olib tashlamasliklari uchun interaktivlikni o'chirib qo'yamiz:

Biz ham shunday qildikki, kartalarimiz tortilganda boshqa rangga ega bo'ladi va agar ular zonadan tushmasa, ular boshlang'ich pozitsiyalariga qaytadilar.

Garchi mijozimiz to'liq bo'lmasa -da, biz orqa tomonni amalga oshirishdan oldin qo'limizdan kelganini qildik. Endi biz kartalar bilan shug'ullanishimiz, ekran bo'ylab sudrab borishimiz va ularni zonaga tashlashimiz mumkin. Ammo oldinga siljish uchun bizga ko'p o'yinchi funksiyasini muvofiqlashtira oladigan serverni o'rnatish kerak bo'ladi.

Server

Keling, ildiz katalogimizda (yuqorida /mijoz) yangi buyruq satrini ochamiz va yozamiz:

Biz yangi package.json -ni ishga tushirdik va Express, Socket.IO va Nodemon -ni o'rnatdik (bu bizning serverimizni kuzatib turadi va o'zgarishlar bilan uni qayta ishga tushiradi).

Kod tahrirlovchisida, pack.json -ning "skriptlar" bo'limini o'zgartiramiz:

Zo'r. Biz o'z serverimizni birlashtirishga tayyormiz! Bizning asosiy katalogimizda "server.js" deb nomlangan bo'sh fayl yarating va quyidagi kodni kiriting:

Biz Express va Socket.IO -ni import qilmoqdamiz va serverni 3000 -portda tinglashni so'raymiz. Mijoz bu portga ulanganda yoki undan uzilsa, biz voqeani mijozning rozetkasi bilan konsolda qayd qilamiz.

Yangi buyruq qatori interfeysini oching va serverni ishga tushiring:

Bizning serverimiz endi localhost: 3000 da ishlashi kerak va Nodemon har qanday o'zgarishlarni bizning oxirgi fayllarimizni kuzatib boradi. "Server ishga tushdi!" Konsol jurnalidan boshqa hech narsa bo'lmaydi.

Boshqa ochiq buyruq qatori interfeysida /mijoz katalogiga qaytamiz va Socket.IO mijoz versiyasini o'rnatamiz:

Endi biz uni O'yin sahnasida import qilishimiz mumkin:

Ajoyib! Biz faqat old va orqa uchlarimizni bog'ladik. Biz qilishimiz kerak bo'lgan narsa, create () funktsiyasida ba'zi kodlarni yozishdir:

Biz mahalliy 3000 portimizni ko'rsatadigan va ulanish paytida brauzer konsoliga kiradigan yangi "soket" o'zgaruvchisini ishga tushiramiz.

Http: // localhost: 8080 (bizning Phaser mijozimizga xizmat ko'rsatiladi) saytida bir nechta brauzerlarni oching va yoping va siz buyruq satri interfeysida quyidagilarni ko'rishingiz kerak:

VAJJAJ. Server.js faylimizga mantiq qo'shishni boshlaymiz, bu bizning karta o'yinining ehtiyojlarini qondiradi. Mavjud kodni quyidagilar bilan almashtiring:

Biz "pleyerlar" deb nomlangan bo'sh qatorni ishga tushirdik va mijoz har safar serverga ulanganida unga soket identifikatorini qo'shamiz, shu bilan birga rozetka identifikatori o'chirilganda o'chiriladi.

Agar mijoz birinchi bo'lib serverga ulansa, biz Socket.IO -dan "A o'yinchi" bo'ladigan voqeani "chiqarishni" so'raymiz. Keyinchalik, server "dealCards" yoki "cardPlayed" deb nomlangan voqeani olganda, u mijozlarga mos ravishda yangilanishi kerak.

Ishoning yoki ishonmang, bu bizning serverimiz ishlashi uchun kerak bo'lgan kod! Keling, diqqatimizni O'yin sahnasiga qaratamiz. Create () funktsiyasining yuqori qismida quyidagilarni kiriting:

"This.socket.on (ulanish)" bilan boshlanadigan kod bloki ostiga quyidagilarni yozing:

Endi, agar bizning mijozimiz birinchi bo'lib serverga ulansa, server mijozga "A o'yinchi" bo'lishini aytadigan voqeani chiqaradi. Mijoz rozetkasi bu hodisani oladi va bizning "isPlayerA" booleanini "false" dan "true" ga aylantiradi.

Eslatma: bu vaqtdan boshlab, mijozning serverdan to'g'ri uzilishi va serverga to'g'ri ulanishi uchun, Webpack siz uchun avtomatik tarzda bajarilishi o'rniga, brauzer sahifasini qayta yuklashingiz kerak bo'ladi (http: // localhost: 8080).

Mijoz bizga raqibimiznikidan farqli bo'lishi mumkin bo'lgan kartalar to'plamini berishini xohlagan holda, o'yinimizning ko'p o'yinchi tomonini qo'llab -quvvatlash uchun dealCards () mantig'ini qayta sozlashimiz kerak. Bundan tashqari, biz raqib kartalarining orqa qismini ekranda ko'rsatishni xohlaymiz va aksincha.

Biz bo'sh /src/helpers/dealer.js fayliga o'tamiz, card.js faylini import qilamiz va yangi sinf yaratamiz:

Bu yangi sinf yordamida biz mijozning A o'yinchi ekanligini tekshiramiz va har qanday holatda qanday spritlardan foydalanish kerakligini aniqlaymiz.

Keyin, biz mijozga kartalar tarqatamiz, shu bilan birga raqib kartalarining orqa qismini ekranning yuqori qismida ko'rsatamiz va ularni O'yin sahnamizda boshlangan raqib kartalari qatoriga qo'shamiz.

/Src/scenes/game.js dileriga import qiling:

Keyin dealCards () funktsiyasini quyidagi bilan almashtiring:

"This.socket.on ('isPlayerA')" bilan boshlanadigan kod blokiga quyidagilarni qo'shing:

Bundan tashqari, bu o'zgarishlarga mos kelish uchun dealText funktsiyasini yangilashimiz kerak:

Puf! Biz yangi dilerlar sinfini yaratdik, u bizga kartalar bilan shug'ullanadi va raqib kartalarini ekranga chiqaradi. Mijoz rozetkasi serverdan "kelishuv kartalari" hodisasini olganda, bu yangi sinfdan dealCards () funktsiyasini chaqiradi va hech qanday sababsiz kartalar ishlab chiqarishni davom ettira olmasligimiz uchun dealTextni o'chirib qo'yadi.

Nihoyat, biz dealText funksiyasini o'zgartirdik, shunda u bosilganda mijoz serverga biz kartalar bilan shug'ullanmoqchi bo'lgan voqeani yuboradi, u hamma narsani bir -biriga bog'lab qo'yadi.

Http: // localhost: 8080 ga ishora qilgan ikkita alohida brauzerni yoqing va ulardan birida "DEAL CARDS" ni bosing. Har qanday ekranda siz turli xil spritlarni ko'rishingiz kerak:

Yana shuni esda tutingki, agar sizda bu qadam bilan bog'liq muammolar mavjud bo'lsa, har ikkala mijoz ham serverdan uzilganligiga ishonch hosil qilish uchun brauzerlardan birini yopishingiz va birinchisini qayta yuklashingiz kerak bo'ladi, bu sizning buyruq satri konsoliga kirishi kerak.

Biz hali ham tushgan kartalarimizni raqib mijoziga qanday ko'rsatishni aniqlashimiz kerak va aksincha. Biz bularning barchasini o'yin sahnamizda qila olamiz! "This.input.on (" tomchi ") bilan boshlanadigan kod blokini oxirida bitta satr bilan yangilang:

Mijozga karta tushirilganda, rozetka "cardPlayed" deb nomlangan voqeani chiqaradi, o'yin obyekti va mijozning isPlayerA boolean tafsilotlarini uzatadi (bu to'g'ri yoki yolg'on bo'lishi mumkin, bu birinchi bo'lib ulangan mijozga bog'liq) serverga).

Eslatib o'tamiz, bizning server kodimizda Socket.IO shunchaki "cardPlayed" hodisasini oladi va voqeani boshlagan mijozdan o'yin ob'ekti va isPlayerA haqidagi bir xil ma'lumotni barcha mijozlarga qaytaradi .

Mijoz "this.socket.on ('dealCards')" kod bloki ostida serverdan "cardPlayed" hodisasini olganda nima bo'lishini yozaylik:

Kod bloki avval serverdan olgan isPlayerA booleanini mijozning o'z isPlayerA bilan taqqoslaydi, bu voqeani qabul qilayotgan mijoz uni yaratgan bilan bir xilligini aniqlash.

Keling, Socket.IO -ni ulagich sifatida ishlatib, mijoz -server aloqasi qanday ishlashining asosiy komponentini ochib berar ekan, biroz o'ylab ko'ramiz.

Mijoz birinchi server ulanadi, va u o'z isPlayerA Boolean o'zgartirish kerak, deb "isPlayerA" tadbir orqali aytgan deylik haqiqiy. Bu shuni anglatadiki, foydalanuvchi ushbu mijoz orqali "DEAL CARDS" tugmachasini bosganda, u qanday turdagi kartalarni ishlab chiqaradi.

Agar mijoz B serverga ikkinchi marta ulansa, hech qachon uning isPlayerA booleanini o'zgartirmang, bu yolg'onbo'lib qoladi . Bu, shuningdek, qanday kartalar ishlab chiqarilishini aniqlaydi.

A mijozi kartani tushirganda, u serverga "cardPlayed" hodisasini yuboradi, u tushib qolgan karta va uning isPlayerA mantiqiyligi haqidagi ma'lumotlarni uzatadi, bu to'g'ri. Keyin server barcha ma'lumotlarni o'z mijozlariga "cardPlayed" hodisasi bilan qaytaradi.

A mijozi bu hodisani serverdan oladi va serverdan kelgan isPlayerA mantiqiyligi haqiqat ekanligini qayd etadi, ya'ni bu voqeani A mijozi o'zi yaratgan. Hech qanday maxsus narsa bo'lmaydi.

B mijozi xuddi shu hodisani serverdan oladi va mijozning isPlayerA -si noto'g'ribo'lsa -da, serverdan kelgan isPlayerA mantiqiyligi to'g'riekanligini qayd etadi. Bu farq tufayli, u kod blokining qolgan qismini bajaradi.

Keyingi kod serverdan olgan o'yin ob'ektining "teksturekeyini" - tasvirini "sprite" deb nomlangan o'zgaruvchiga saqlaydi. U ekranning yuqori qismida ko'rsatiladigan raqib karta orqa qismlaridan birini yo'q qiladi va biz kartalarni chapdan o'ngga joylashtirishda davom etishimiz uchun "zonalar" ma'lumotlarining qiymatini oshiradi.

Keyin kod boshqa mijozga qo'yilgan kartani yaratish uchun sprite o'zgaruvchisidan foydalanadigan yangi zonani yaratadi (agar sizda o'yin ob'ektiga biriktirilgan ma'lumotlar bo'lsa, uni shu erga biriktirish uchun ham xuddi shunday yondashuvdan foydalanishingiz mumkin) ).

Sizning oxirgi /src/scenes/game.js kodingiz shunday bo'lishi kerak:

Hammasini saqlang, ikkita brauzerni oching va "DEAL CARDS" ni bosing. Agar siz bitta mijozga kartani sudrab tashlasangiz, u boshqa birining zonasida ko'rsatilishi kerak, shu bilan birga karta o'ynalganligini bildiruvchi kartani o'chirib tashlaydi:

Bo'ldi shu! Endi siz o'zingizning kartalaringiz, san'atingiz va o'yin mantig'ini qo'shishingiz mumkin bo'lgan ko'p o'yinchi karta o'yini uchun funktsional shablonga ega bo'lishingiz kerak.

Birinchi qadam, dilerlar sinfiga bir nechta kartalarni aralashtirib, tasodifiy kartani qaytarib qo'shish bo'lishi mumkin (maslahat: Phaser.Math.RND.shuffle ([qator])).

MS Farzan, t.f.n. u yuqori darajadagi video o'yin kompaniyalari va Electronic Arts, Perfect World Entertainment, Modus Games va MMORPG.com kabi tahririyat veb-saytlarida yozgan va ishlagan va Dungeons & Dragons Neverwinter va Mass Effect: Andromeda kabi o'yinlar uchun hamjamiyat menejeri bo'lib ishlagan. . U " Entromancy: Cyberpunk Fantasy RPG " ijodiy direktori va bosh o'yini dizayneri va "Nightpath trilogy" muallifi . MS Farzanni Twitterda @sominator -da toping.

MS Farzan, t.f.n. Nightpath nashriyotiga kirish uchun ijodiy direktor va etakchi o'yin dizayneridir va Electronic Arts, Perfect World Entertainment va MMORPG.com uchun yozgan va ishlagan.

Agar siz hozirgacha o'qigan bo'lsangiz, muallifga o'z g'amxo'rligingizni ko'rsatish uchun tvit yozing. Tweet rahmat

Bepul kodlashni o'rganing. freeCodeCamp -ning ochiq manbali o'quv dasturi 40,000 dan ortiq odamga dasturchi sifatida ishga joylashishga yordam berdi. Ishni boshlang

freeCodeCamp-donorlar tomonidan qo'llab-quvvatlanadigan 501 (c) (3) nodavlat notijorat tashkiloti (AQShning Federal soliq identifikatsiya raqami: 82-0779546)

Bizning vazifamiz: odamlarga bepul kod yozishni o'rganishga yordam berish. Biz bunga minglab videolar, maqolalar va interaktiv kodlash darslarini yaratish orqali erishamiz - bularning barchasi ommaga ochiq. Bizda butun dunyo bo'ylab minglab freeCodeCamp o'quv guruhlari mavjud.

FreeCodeCamp -ga xayr -ehsonlar bizning ta'lim tashabbuslarimizga yo'naltiriladi va serverlar, xizmatlar va xodimlar uchun haq to'lashga yordam beradi.