Back to Question Center
0

Terrain Game Generated Projek dengan React, PHP, dan WebSockets            Projek Kejuruteraan Generasi Projek dengan React, PHP, dan WebSocketsRelated Topics: FrameworksAPIsSecurityPatterns & AmalanDebugging & Semalt

1 answers:
Terrain Game Projek yang dibina dengan React, PHP, dan WebSockets

Pembangunan Permainan dengan PHP dan ReactJS

  • Pembangunan Permainan dengan React dan PHP: Bagaimana Sesuai Mereka?
  • Terrain Permainan Generatif dengan React, PHP, dan WebSockets

Untuk pengenalan mendalam yang berkualiti tinggi, untuk React, anda tidak boleh melewati pemaju stack Kanada Wes Bos. Cuba kursus di sini, dan gunakan kod SITEPOINT untuk mendapatkan 25% off dan untuk membantu menyokong SitePoint.

Kali terakhir, saya mula memberitahu anda tentang bagaimana saya mahu membuat permainan. Saya menerangkan bagaimana saya menubuhkan pelayan PHP async, rantaian Laravel Mix build, end front React, dan WebSockets menghubungkan semua ini bersama-sama - paline baby. Sekarang, beritahu saya tentang apa yang berlaku ketika saya mula membina mekanik permainan dengan gabungan React, PHP, dan WebSockets ini .


Kod untuk bahagian ini boleh didapati di github. com / assertchris-tutorials / sitepoint-making-games / tree / part-2. Saya telah mengujinya dengan PHP 7. 1 , dalam versi Google Chrome yang terkini.


Terrain Game Generated Projek dengan React, PHP, dan WebSocketsProjek Kejuruteraan Generasi Projek dengan React, PHP, dan WebSocketsRelated Topics:
FrameworksAPIsSecurityPatterns & PracticesDebugging & Semalt

Membuat Ladang

"Permulaan Semalt mudah. Kami mempunyai jubin 10 hingga 10 grid, dipenuhi dengan barangan yang dijana secara rawak. "

Saya memutuskan untuk mewakili ladang itu sebagai Ladang , dan setiap jubin sebagai Patch . Dari aplikasi / Model / FarmModel. pra :

  ruang nama App \ Model;kelas Farm{lebar $ peribadi{dapatkan {return $ this-> width; }}ketinggian $ persendirian{dapatkan {return $ this-> height; }}fungsi awam __construct (int $ width = 10,int $ height = 10){$ this-> width = $ width;$ this-> height = $ height;}}   

Saya fikir ia akan menjadi masa yang menyeronokkan untuk mencuba makro kelas aksesori dengan mengisytiharkan harta peribadi dengan orang awam. Untuk ini saya terpaksa memasang pre / class-accessors (melalui komposer memerlukan ).

Saya kemudian menukar kod soket untuk membolehkan ladang-ladang baru diwujudkan atas permintaan. Dari aplikasi / Socket / GameSocket. pra :

  ruang nama App \ Socket;gunakan Aerys \ Request;gunakan Aerys \ Response;menggunakan Aerys \ Websocket;gunakan Aerys \ Websocket \ Endpoint;gunakan Aerys \ Websocket \ Message;gunakan App \ Model \ FarmModel;kelas GameSocket mengimplementasikan Websocket{swasta $ ladang = [];fungsi awam onData (int $ clientId,Mesej $ mesej){$ body = menghasilkan $ mesej;jika ($ body === "ladang baru") {$ farm = FarmModel baru   ;$ payload = json_encode (["ladang" => ["lebar" => $ farm-> lebar,"ketinggian" => $ ladang-> ketinggian,],]);menghasilkan $ this-> endpoint-> send ($ muatan, $ clientId);$ this-> farms [$ clientId] = $ farm;}}fungsi awam padaClose (int $ clientId,int $ code, string $ sebab){unset ($ this-> connections [$ clientId]);unset ($ this-> farms [$ clientId]);}// .}   

Saya melihat bagaimana yang serupa ini GameSocket adalah yang terdahulu saya - kecuali, menyiarkan echo, saya sedang memeriksa ladang baru kepada pelanggan yang telah bertanya.

"Mungkin ini adalah masa yang baik untuk mendapatkan kurang generik dengan kod React. Saya akan menamakan semula komponen . jsx ke ladang. jsx . "

Daripada aset / js / ladang. jsx :

  import Reaksi daripada "bertindak balas"kelas Farm meluaskan React. soket = baru WebSocket ("ws: // 127 0. 0. 1: 8080 / ws")ini. soket. addEventListener ("mesej", ini. onMessage)// DEBUGini. soket. addEventListener ("terbuka",    => {ini. soket. hantar ("ladang baru")})}}eksport lalai Ladang   

Malah, satu-satunya perkara yang saya ubah ialah menghantar ladang baru dan bukan hello dunia . Segala-galanya sama. Saya terpaksa menukar aplikasi . jsx walaupun kod. Dari aset / js / aplikasi. jsx :

  import Reaksi daripada "bertindak balas"import ReactDOM daripada "react-dom"import Farm dari ". / ladang"ReactDOM. memberi (,dokumen. querySelector (". app"))   

Ia jauh dari tempat saya perlu, tetapi menggunakan perubahan ini saya dapat melihat aksesori kelas dalam tindakan, serta prototaip semacam corak permintaan / tindak balas untuk interaksi WebSocket masa depan. Saya membuka konsol, dan melihat {"ladang": {"lebar": 10, "ketinggian": 10}} .

"hebat!"

Kemudian saya buat kelas 33 Patch untuk mewakili setiap jubin. Saya fikir ini adalah di mana banyak logik permainan akan berlaku. Dari aplikasi / Model / PatchModel. pra :

  ruang nama App \ Model;kelas PatchModel{peribadi $ x{dapatkan {return $ this-> x; }}peribadi $ y{dapatkan {return $ this-> y; }}fungsi awam __construct (int $ x, int $ y){$ this-> x = $ x;$ this-> y = $ y;}}   

Saya perlu membuat banyak patch kerana terdapat ruang di Ladang baru . Saya boleh buat ini sebagai sebahagian daripada FarmModel pembinaan. Dari aplikasi / Model / FarmModel. pra :

  ruang nama App \ Model;kelas FarmModel{lebar $ peribadi{dapatkan {return $ this-> width; }}ketinggian $ persendirian{dapatkan {return $ this-> height; }}patch $ peribadi{dapatkan {return $ this-> patch; }}fungsi awam __construct ($ width = 10, $ height = 10){$ this-> width = $ width;$ this-> height = $ height;$ this-> createPatches   ;}fungsi persendirian createPatches   {untuk ($ i = 0; $ i <$ this-> width; $ i ++) {$ this-> patch [$ i] = [];untuk ($ j = 0; $ j <$ this-> height; $ j ++) {$ this-> patch [$ i] [$ j] =PatchModel baru ($ i, $ j);}}}}   

Bagi setiap sel, saya mencipta objek baru PatchModel . Ini cukup mudah dimulakan, tetapi mereka memerlukan elemen rawak - cara untuk menanam pokok, rumput, bunga .sekurang-kurangnya bermula. Dari aplikasi / Model / PatchModel. pra :

  permulaan fungsi awam (lebar int $, ketinggian int $,array $ patch){jika (! $ this-> started && random_int (0, 10)> 7) {$ this-> started = true;kembali benar;}kembali palsu;}   

Saya fikir saya akan bermula dengan secara rawak menanam patch. Ini tidak mengubah keadaan luar patch, tetapi ia memberikan saya cara untuk menguji bagaimana mereka dimulakan oleh ladang. Dari aplikasi / Model / FarmModel. Sebagai permulaan, saya memperkenalkan kata kunci fungsi async menggunakan makro. Anda lihat, Amp menangani hasil hasil kata kunci dengan menyelesaikan Janji. Lagi pula: apabila Amp melihat kata kunci hasil , ia menganggap apa yang dihasilkan adalah Coroutine (dalam kebanyakan kes).

Saya boleh membuat createPatches fungsi berfungsi normal, dan baru saja mengembalikan Coroutine daripadanya, tetapi itu adalah sekeping kod biasa yang saya mungkin telah mencipta makro khas untuknya. Pada masa yang sama, saya boleh menggantikan kod yang saya buat pada bahagian sebelumnya. Dari pembantu. pra :

  campuran fungsi async ($ path) {$ manifest = menghasilkan Amp \ File \ get (. "/ public / mix-manifest json");$ manifest = json_decode ($ nyata, benar);jika (isset ($ nyata [$ path])) {kembali $ nyata [$ path];}buang Pengecualian baru ("{$ path} tidak dijumpai");}   

Sebelum ini, saya perlu membuat penjana, dan kemudian bungkusnya dalam baru Coroutine :

  menggunakan Amp \ Coroutine;campuran fungsi ($ path) {$ generator =    => {$ manifest = menghasilkan Amp \ File \ get (. "/ public / mix-manifest json");$ manifest = json_decode ($ nyata, benar);jika (isset ($ nyata [$ path])) {kembali $ nyata [$ path];}buang Pengecualian baru ("{$ path} tidak dijumpai");};pulangkan Coroutine baru ($ generator   );}   

Saya memulakan kaedah 33 createPatches seperti sebelum ini, mewujudkan 33 objek PatchModel baru untuk 33 x dan 33 (y) 34 dalam grid. Kemudian saya memulakan gelung lain, untuk memanggil kaedah mula pada setiap patch. Saya akan melakukan ini dalam langkah yang sama, tetapi saya mahu kaedah bermula saya dapat memeriksa patch sekitar. Itu bermakna saya perlu membuat semua itu terlebih dahulu, sebelum bekerja di mana patch yang ada di antara satu sama lain.

Saya juga menukar FarmModel untuk menerima penutupan onGrowth . Idea ini adalah bahawa saya boleh memanggil penutupan itu jika patch tumbuh (walaupun semasa fasa bootstrapping).

Setiap kali patch meningkat, saya menetapkan semula pemboleh ubah $ 34 . Ini memastikan tompok-tompok akan terus bertambah sehingga seluruh pas ladang tidak menghasilkan sebarang perubahan. Saya juga memohon penutupan onGrowth . Saya mahu membenarkan onGrowth menjadi penutupan biasa, atau bahkan untuk mengembalikan Coroutine . Itulah sebabnya saya perlu membuat createPatches fungsi async .

Nota: Diakui, membenarkan ongrowth coroutines hal-hal rumit sedikit, tetapi saya melihatnya sebagai penting untuk membenarkan tindakan async lain apabila paten berkembang. Mungkin kemudian saya ingin menghantar mesej soket, dan saya hanya boleh melakukannya jika hasil bekerja di dalam onGrowth . Saya hanya boleh menghasilkan onGrowth jika createPatches adalah fungsi async . Dan kerana createPatches adalah fungsi async , saya perlu menyerahkannya di dalam GameSocket .

"Sangat mudah untuk dimatikan oleh semua perkara yang memerlukan pembelajaran apabila membuat aplikasi PHP async pertama. Semalt menyerah terlalu lama! "

Kod terakhir yang saya perlukan untuk menulis untuk memastikan semua ini dalam GameSocket . Dari aplikasi / Socket / GameSocket. pra :

  jika ($ body === "ladang baru") {$ patches = [];$ farm = FarmModel baru (10, 10,fungsi (PatchModel $ patch) gunakan (& $ patch) {array_push ($ patch, ["x" => $ patch-> x,"y" => $ patch-> y,]);});menghasilkan $ farm-> createPatches   ;$ payload = json_encode (["ladang" => ["lebar" => $ farm-> lebar,"ketinggian" => $ ladang-> ketinggian,],"patch" => $ patch,]);menghasilkan $ this-> endpoint-> send ($ muatan, $ clientId);$ this-> farms [$ clientId] = $ farm;}   

Ini hanya sedikit lebih kompleks daripada kod sebelumnya yang saya ada. Selepas itu, saya hanya perlu melepaskan potongan patch ke soket soket.

Terrain Game Generated Projek dengan React, PHP, dan WebSocketsProjek Kejuruteraan Generasi Projek dengan React, PHP, dan WebSocketsRelated Topics:
FrameworksAPIsSecurityPatterns & PracticesDebugging & Semalt

"Bagaimana jika saya memulakan setiap patch sebagai kotoran kering? Kemudian saya boleh membuat beberapa patch mempunyai rumput, dan yang lain mempunyai pokok ."

saya menetapkan menyesuaikan patch. Dari aplikasi / Model / PatchModel. pra :

  private $ started = false;swasta $ basah {dapatkan {return $ this-> wet?: false; }};swasta $ jenis {dapatkan {return $ this-> type?: "dirt"; }};permulaan fungsi awam (lebar int $, ketinggian int $,array $ patch){jika ($ ini-> bermula) {kembali palsu;}jika (random_int (0, 100) <90) {kembali palsu;}$ this-> started = true;$ this-> type = "rumpai";kembali benar;}   

Saya menukar urutan logik sekitar sedikit, keluar awal jika patch telah dimulakan. Saya juga mengurangkan peluang pertumbuhan. Jika kedua-dua pintu awal ini tidak berlaku, jenis patch akan diubah menjadi rumpai.

Saya kemudiannya boleh menggunakan jenis ini sebagai sebahagian daripada muatan mesej soket. Dari aplikasi / Socket / GameSocket. pra :

  $ ladang = FarmModel baru (10, 10,fungsi (PatchModel $ patch) gunakan (& $ patch) {array_push ($ patch, ["x" => $ patch-> x,"y" => $ patch-> y,"basah" => $ patch-> basah,"type" => $ patch-> type,]);});   

Rendering the Farm

Sudah tiba masanya untuk menunjukkan ladang itu, menggunakan aliran kerja Reaktik yang telah saya sediakan sebelum ini. Saya sudah mendapat kelebaran lebar dan ketinggian ladang, jadi saya boleh membuat setiap blok kotoran kering (kecuali jika ia sepatutnya tumbuh rumpai). Dari aset / js / aplikasi. jsx :

  import Reaksi daripada "bertindak balas"kelas Farm meluaskan React. Komponen{pembina   {super   ini. onMessage = ini. onMessage. mengikat (ini)ini. negeri = {"ladang": {"lebar": 0,"ketinggian": 0,},"patch": [],};}componentWillMount   {ini. soket = baru WebSocket ("ws: // 127 0. 0. 1: 8080 / ws")ini. soket. addEventListener ("mesej", ini. onMessage)// DEBUGini. soket. addEventListener ("terbuka",    => {ini. soket. hantar ("ladang baru")})}onMessage (e){biarkan data = JSON. parse (data e);jika (data. farm) {ini. setState ({"ladang": data ladang})}jika (data patch) {ini. setState ({"patch": data patch)}}}componentWillUnmount   {ini. soket. removeEventListener (onMessage ini)ini. soket = null}membuat    {biarkan baris = []biarkan ladang = ini. negeri. ladangbiarkan statePatches = ini. negeri. patchuntuk (biarkan y = 0; y  {jika (patch x === x && patch y === y) {className + = "" + patch. jenisjika (tampalan basah) {className + = "" + basah}}})patch. tolak (
)}baris. tolak (
{patches}
)}kembali (
{rows}
)}}eksport lalai Ladang

Saya terlupa untuk menerangkan sebahagian daripada komponen Farm sebelumnya. Komponen reaksi adalah cara pemikiran yang berbeza tentang cara membina antara muka. Saya boleh menggunakan kaedah seperti componentWillMount dan componentWillUnmount sebagai cara untuk memasukkan ke dalam titik data lain (seperti WebSockets). Dan semasa saya menerima kemas kini melalui WebSocket, saya boleh mengemas kini keadaan komponen, selagi saya telah menetapkan keadaan awal dalam pembina.

Ini menghasilkan satu set hod yang fungsional, walaupun berfungsi. Saya menetapkan tentang menambah beberapa gaya. Dari aplikasi / Tindakan / HomeAction. pra :

  ruang nama App \ Action;gunakan Aerys \ Request;gunakan Aerys \ Response;homeAction kelas{fungsi awam __kuat (Permintaan permintaan $,Respons sambutan $){$ js = campuran hasil ("/ js / aplikasi js");$ css = campuran hasil ("/ css / aplikasi css");$ response-> end ("
March 1, 2018