Back to Question Center
0

بازیابی شده به روش بازیابی زمین بازی با React، PHP و WebSockets            بازیابی شده به صورت روشی بازی Terrain With React، PHP و WebSocketsRelated Topics: FrameworksAPIsSecurityPatterns & ؛ PracticesDebugging & ؛ Semalt

1 answers:
بازیابی شده با روش بازیابی زمین بازی با React، PHP و WebSockets

توسعه بازی با پی اچ پی و ReactJS

  • توسعه بازی با React و PHP: چقدر سازگار هستند؟
  • بازیابی شده از راه بازی زمین با React، PHP و WebSockets

برای معرفی مقدماتی با کیفیت بالا، React، نمیتوانید از Wes Bos توسعهدهنده کامل پشته کانادایی شوید. سعی کنید در اینجا درس خود را امتحان کنید و از کد SITEPOINT استفاده کنید تا 25٪ تخفیف بگیرید و برای کمک به پشتیبانی SitePoint.

آخرین بار، من شروع به صحبت کردن از داستان خود را از چگونگی من را به یک بازی. من توضیح دادم که چگونه من سرور async پی اچ پی، زنجیره ساخت Laravel Mix، قسمت جلو React و WebSockets را به هم متصل نمودم. حالا، اجازه بدهید به شما بگویم در مورد چه اتفاقی افتاده است وقتی که من شروع به ساخت مکانیک بازی با این ترکیب از React، PHP و WebSockets - fleece stoffe guenstig kaufen.


کد این بخش را می توان در github پیدا کرد. com / assertchris-tutorials / sitepoint-making-games / tree / part-2. من آن را در نسخه اخیر گوگل کروم با PHP 7. 1 تست کردم.


بازیابی شده به روش بازیابی زمین بازی با React، PHP و WebSocketsبازیابی شده به صورت روشی بازی Terrain With React، PHP و WebSocketsRelated Topics:
چارچوبهای امنیتی وپشتیبانی و عملکردهای امنیتی و Semalt

ساخت مزرعه

"Semalt شروع ساده است. ما دارای 10 تا 10 شبکه کاشی است که با مواد تولید شده به طور تصادفی تولید می شود. "

تصمیم گرفتم که مزرعه را به عنوان یک مزرعه و هر کاشی به عنوان یک پچ نمایم. از برنامه / مدل / FarmModel. پیش از :

     نام برنامه / مدل؛مزرعه کلاس{خصوصی $ عرض{دریافت {بازگشت $ این-> عرض؛ }}خصوصی $ ارتفاع{دریافت {بازگشت $ این-> ارتفاع؛ }}تابع عمومی __construct (int $ width = 10،int $ height = 10){$ this-> width = $ width؛$ this-> height = $ height؛}}    

من فکر می کنم زمان های سرگرم کننده ای است که با اعلان خواص خصوصی با گیرنده های عمومی، اعمال می شود. برای این که من مجبور بودم از قبل / کلاس accessors (از طریق آهنگساز نیاز ).

پس از آن کد منوی سوکت را تغییر دادم تا بتوانم در مورد مؤسسات جدید ایجاد شود. از برنامه / سوکت / GameSocket. پیش از :

     نام دامنه برنامه \ سوکت؛استفاده از Aerys \ Requestاستفاده از Aerys \ Response؛از Aerys \ Websocket استفاده کنیداستفاده از Aerys \ Websocket \ Endpoint؛استفاده از Aerys \ Websocket \ پیام؛استفاده از App \ Model \ FarmModel؛کلاس GameSocket پیاده سازی Websocket{خصوصی $ farms = []؛تابع عمومی onData (int $ clientId،پیام پیام پیام){$ body = عملکرد $ message؛اگر ($ body === "جدید مزرعه") {$ Farm = FarmModel جدید   ؛$ loadload = json_encode (["مزرعه" => ["width" => $ farm-> width،"height" => $ farm-> height،]،])؛عملکرد $ this-> endpoint-> send ($ payload، $ clientId)؛$ this-> farms [$ clientId] = $ farm؛}}تابع عمومی onClose (int $ clientId،int $ code، string $ reason){unset ($ this-> connections [$ clientId])؛Unset ($ this-> farms [$ clientId])؛}// .}    

من متوجه شدم که این بازی GameSocket به یک مورد قبلی بود - به جز، به جای پخش اکو، من برای جدید مزرعه و ارسال پیام تنها به عقب به مشتری که خواسته بود

"شاید زمان خوبی برای دریافت کد عمومی کمتر باشد. من قصد دارم نام را تغییر نام دهم. jsx به مزرعه. jsx . "

از دارایی / js / مزرعه. jsx :

     واردات واکنش از "واکنش"مزرعه کلاس React را فعال می کند. سوکت = وبسایت جدید ("ws: // 127.0 0. 0. 1: 8080 / ws")این. سوکت addEventListener ("پیام"، این. onMessage)// DEBUGاین. سوکت addEventListener ("باز"،    => {این. سوکت ارسال ("مزرعه جدید")})}}صادرات به طور پیش فرض مزرعه    

در واقع، تنها چیز دیگری که تغییر دادم، به جای سلام جهان جدید مزرعه فرستاد. همه چیز دیگر همین بود. من مجبور شدم برنامه را تغییر دهم. کد Jsx هر چند. از assets / js / app. jsx :

     واردات واکنش از "واکنش"واردات ReactDOM از "react-dom"وارد مزرعه از ". / مزرعه"ReactDOM رندر (<مزرعه />،اسناد querySelector ("برنامه."))    

این دور از جایی بود که من نیاز داشتم، اما با استفاده از این تغییرات من می توانم accessors کلاس در عمل را ببینم، و همچنین نمونه اولیه یک نوع الگوی درخواست / پاسخ برای تعاملات WebSocket آینده است. من کنسول را باز کردم و دیدم {"مزرعه": {"عرض": 10، "ارتفاع": 10}} .

"عالی"

سپس یک کلاس پچ ایجاد کردم که هر کاشی را نمایندگی کند. من متوجه شدم که در آن بسیاری از منطق بازی رخ داده است. از برنامه / مدل / PatchModel. پیش از :

     نام برنامه / مدل؛کلاس PatchModel{خصوصی $ x{دریافت {بازگشت $ این-> X؛ }}خصوصی $ Y{دریافت {return $ this-> y؛ }}تابع عمومی __construct (int $ x، int $ y){$ this-> x = $ x؛$ this-> y = $ y؛}}    

من نیاز به ایجاد بسیاری از تکه ها به عنوان فضاهای در یک جدید مزرعه وجود دارد. من می توانم این را بخشی از FarmModel ساخت. از برنامه / مدل / FarmModel. پیش از :

     نام برنامه / مدل؛FarmModel کلاس{خصوصی $ عرض{دریافت {بازگشت $ این-> عرض؛ }}خصوصی $ ارتفاع{دریافت {بازگشت $ این-> ارتفاع؛ }}تکه های خصوصی ${دریافت {بازگشت $ این-> پچ؛ }}تابع عمومی __construct ($ width = 10، $ height = 10){$ this-> width = $ width؛$ this-> height = $ height؛$ this-> createPatches   ؛}function خصوصی createPatches   {برای ($ i = 0؛ $ i <$ این-> عرض؛ $ i ++) {$ this-> patches [$ i] = []؛برای ($ j = 0؛ $ j <$ این-> ارتفاع؛ $ j ++) {$ this-> patches [$ i] [$ j] =PatchModel جدید ($ i، $ j)؛}}}}    

برای هر سلول، یک شی جدید PatchModel ایجاد کردم. این برای شروع بسیار ساده بود، اما آنها نیاز به یک عنصر تصادفی - راه برای رشد درختان، علف های هرز، گل .حداقل برای شروع. از برنامه / مدل / PatchModel. پیش از :

     تابع عمومی شروع (int $ عرض، int $ ارتفاع،آرایه $ تکه ها){اگر (! $ this-> started && random_int (0، 10)> 7) {$ this-> started = true؛بازگشت درست}بازگشت نادرست؛}    

فکر کردم من فقط با یک پچ به طور تصادفی رشد می کنم. این حالت خارجی پچ را تغییر نداد، اما به من اجازه داد تا تست اینکه چگونه از مزرعه شروع شد. از برنامه / مدل / FarmModel. برای شروع، من async تابع کلیدی را با استفاده از یک ماکرو معرفی کردم. شما می بینید که Amp عملکرد عملکرد کلمه کلیدی را با حل وعده انجام می دهد. بیشتر به نقطه: زمانی که آمپر می بیند عملکرد کلمه کلیدی، فرض می کند آنچه که در حال به دست آورد است Coroutine (در بیشتر موارد).

من می توانستم createPatches یک عملکرد عادی را اجرا کنم و فقط Coroutine را از آن باز کردم، اما این یک قطعه معمول از کد بود که من نیز ممکن است یک ماکرو خاص برای آن ایجاد کرده باشم. در عین حال، من می توانم جایگزین کدی که در بخش قبلی ایجاد کردم، باشد. از کمک کننده. پیش از :

     مخلوط تابع async ($ مسیر) {$ manifest = عملکرد Amp \ File \ get (. "/ public / mix-manifest json")؛$ manifest = json_decode ($ manifest، true)؛اگر (isset ($ manifest [$ path])) {return $ manifest [$ path]؛}پرتاب جدید استثنا ("{$ مسیر} یافت نشد")؛}    

پیش از آن، من مجبور بودم یک ژنراتور ایجاد کنم، و سپس آن را در یک جدید Coroutine :

     استفاده از Amp \ Coroutine؛توابع تابع ($ مسیر) {$ generator =    => {$ manifest = عملکرد Amp \ File \ get (. "/ public / mix-manifest json")؛$ manifest = json_decode ($ manifest، true)؛اگر (isset ($ manifest [$ path])) {return $ manifest [$ path]؛}پرتاب جدید استثنا ("{$ مسیر} یافت نشد")؛}؛Coroutine جدید ($ generator   )؛}    
روش createPatches همانطور که قبلا شروع کردم، ایجاد اشیاء جدید PatchModel برای هر x و y در شبکه. سپس یک حلقه دیگر را شروع کردم، برای فراخوانی شروع روش در هر پچ. من این را در همان مرحله انجام دادم، اما من می خواستم روش برای بازرسی تکه های اطراف آن. این به این معناست که من باید ابتدا همه آنها را ایجاد کنم، قبل از اینکه کارهایی را که در اطراف یکدیگر بود، انجام دهم.

من همچنین FarmModel را به پذیرفتن بستن بر رشد نیز تغییر دادم. ایده این بود که اگر یک پچ رشد کند (حتی در مرحله فشردن بوت استرپ)، می توانم آن را بسته کنم.

هر بار یک پچ رشد می کند، تغییر $ تغییرات متغیر را تنظیم می کنم. این اطمینان داد که تکه ها رشد می کنند تا زمانی که عبور کامل از مزرعه تغییری ایجاد نخواهد کرد. من همچنین بسته شدن را بر عهده گرفتم. من می خواستم بر روی رشد یک بسته شدن طبیعی یا حتی برای بازگشت Coroutine باشد. به همین دلیل من نیاز به ایجاد createPatches یک async تابع.

توجه: به درستی اجازه می دهد onGrowth croutines چیزی پیچیده چیز کمی، اما من آن را به عنوان ضروری برای اجازه دادن به دیگر اقدامات async زمانی که یک پچ رشد کرد. شاید بعدا می خواهم یک پیام سوکت ارسال کنم، و من فقط می توانم این کار را انجام دهم اگر عملکرد در داخل در Grorow کار کرد. اگر createPatches عملکرد تابع async بود، من فقط می توانستم onGrowth تولید کنم. و چون createPatches یک عملکرد async بود، من باید آن را در داخل GameSocket انجام دهم.

"آسان است که توسط همه چیزهایی که نیاز به یادگیری هنگام اولین اولین برنامه async PHP خود را خاموش کنید. سمالد خیلی زود خفه می شود! »

آخرین بیت کد من نیاز به نوشتن برای بررسی اینکه این همه کار بود در GameSocket . از برنامه / سوکت / GameSocket. پیش از :

     اگر ($ body === "جدید مزرعه") {$ patches = []؛$ farm = FarmModel جدید (10، 10،تابع (PatchModel $ patch) استفاده کنید (& $ patches) {array_push ($ patches، ["x" => $ patch-> x"y" => $ patch-> y])؛})؛عملکرد $ farm-> createPatches   ؛$ loadload = json_encode (["مزرعه" => ["width" => $ farm-> width،"height" => $ farm-> height،]،"patches" => تکه های $])؛عملکرد $ this-> endpoint-> send ($ payload، $ clientId)؛$ this-> farms [$ clientId] = $ farm؛}    

این فقط کمی پیچیده تر از کد قبلی من بود. پس از آن، من فقط نیاز به تصویب یک عکس فوری از تکه ها به بار استفاده سوکت.

بازیابی شده به روش بازیابی زمین بازی با React، PHP و WebSocketsبازیابی شده به صورت روشی بازی Terrain With React، PHP و WebSocketsRelated Topics:
چارچوبهای امنیتی وپشتیبانی و عملکردهای امنیتی و Semalt

"اگر من هر پچ را به عنوان خاک خشک شروع کنم؟ سپس من می توانم برخی از تکه ها را علف های هرز، و دیگران درختان ."

من در مورد سفارشی کردن تکه ها را تنظیم کردم. از برنامه / مدل / PatchModel. پیش از :

     خصوصی $ started = false؛خصوصی $ مرطوب {دریافت {بازگشت $ این-> مرطوب: نادرست؛ }}؛خصوصی $ type {دریافت {بازگشت $ این-> نوع ؟: خاک "؛ }}؛شروع به کار عمومی (int $ width، int $ height،آرایه $ تکه ها){اگر ($ this-> started) {بازگشت نادرست؛}اگر (random_int (0، 100)  <90) {بازگشت نادرست؛}$ this->  started = true؛$ this-> type = "علف هرز"؛بازگشت درست}    

منظور از منطق را در اطراف کمی تغییر دادم، اگر قبلا شروع شده بود، از اوایل فرار می کردم. من همچنین شانس رشد را کاهش دادم. اگر هیچ یک از این خروجی های اولیه اتفاق نیفتاد، نوع پچ به علف های هرز تغییر خواهد کرد.

پس از آن من می توانم از این نوع به عنوان بخشی از پیام های سوکت پیام استفاده کنید. از برنامه / سوکت / GameSocket. پیش از :

     $ farm = FarmModel جدید (10، 10،تابع (PatchModel $ patch) استفاده کنید (& $ patches) {array_push ($ patches، ["x" => $ patch-> x"y" => $ patch-> y"مرطوب" => $ patch-> مرطوب،"type" => $ patch-> نوع])؛})؛    

ارائه مزرعه

زمان برای نشان دادن مزرعه، با استفاده از گردش کار React من تا به حال تنظیم شده بود. من قبلا عرض و ارتفاع از مزرعه را دریافت کردم، بنابراین من می توانم هر یک از بلوک خاک خشک (مگر آن که قرار بود به رشد علف های هرز). از assets / js / app. jsx :

     واردات واکنش از "واکنش"مزرعه کلاس React را فعال می کند مولفه{سازنده   {فوق العاده   این. onMessage = این onMessage اتصال (این)این. state = {"مزرعه": {"عرض": 0،"ارتفاع": 0،}،"تکه ها": []}؛}componentWillMount   {این. سوکت = وبسایت جدید ("ws: // 127.0 0. 0. 1: 8080 / ws")این. سوکت addEventListener ("پیام"، این. onMessage)// DEBUGاین. سوکت addEventListener ("باز"،    => {این. سوکت ارسال ("مزرعه جدید")})}onMessage (e){اجازه داده شود = JSON تجزیه (e داده ها)؛اگر (اطلاعات مزرعه) {این. setState ({"مزرعه": اطلاعات مزرعه})}اگر (تکه های داده ها) {این. setState ({"patches": data patches})}}componentWillUnmount   {این. سوکت removeEventListener (این. onMessage)این. socket = null}رندر    {اجازه ردیفها = []اجازه دهید مزرعه = این. حالت. مزرعهاجازه دهید statePatches = این. حالت. تکه هابرای (اجازه y = 0؛ y <مزرعه؛ ارتفاع؛ y ++) {اجازه پچ ها = []برای (اجازه x = 0؛ x  <مزرعه عرض؛ x ++) {اجازه className = "patch"StatePatches forEach ((patch) =>  {اگر (پچ x === x && patch y === y) {className + = "" + patch. تایپ کنیداگر (پچ مرطوب) {className + = "" + مرطوب}}})تکه ها فشار دادن( 
)}ردیف فشار دادن(
{patches}
)}برگشت (
{rows}
)}}صادرات به طور پیش فرض مزرعه

من فراموش کرده بودم که بیشتر آنچه را که قبلا مزرعه انجام داده بود توضیح دهم. واکنش اجزاء شیوه ای متفاوت از تفکر در مورد نحوه ایجاد رابط ها بود. من می توانم روش هایی مانند componentWillMount و componentWillUnmount را به عنوان راهکار برای قلاب دادن به دیگر نقاط داده (مانند WebSockets) استفاده کنم. و همانطور که از طریق WebSocket به روز رسانی می کردم، می توانم وضعیت مولفه را به روز رسانی کنم، تا زمانی که حالت اولیه در سازنده را تعیین کرده بودم.

این نتیجه یک مجموعه زشت، حتی عملیاتی از divs بود. من در مورد اضافه کردن برخی از یک ظاهر طراحی شده است. از برنامه / اقدام / HomeAction. پیش از :

     نام دامنه برنامه \ اقدام؛استفاده از Aerys \ Requestاستفاده از Aerys \ Response؛کلاس HomeAction{تابع عمومی __invoke (درخواست درخواست $جواب پاسخ پاسخ){$ js = ترکیب عملکرد ("/ js / app. js")؛$ css = ترکیب عملکرد ("/ css / app. css")؛$ response-> end ("   
March 1, 2018