Versi web permainan HTML5 Surround the Nervous Cat ialah permainan berdasarkan HTML5, jquery, Typescript dan teknologi lain.
Dilampirkan kepada anda ialah muat turun demo dan kod sumber, klik di sini Lihat demo Muat turun kod sumber
Saya juga cuba bermain permainan mini "Surround Nervous Cat" yang popular di WeChat Moments tahun lepas. Permainan ini dibangunkan menggunakan enjin Egret, dan oleh kerana Egret dibina menggunakan bahasa Typescript, permainan di sini juga dibangunkan menggunakan Typescript.
Peraturan permainan:
Klik pada grid kelabu pada skrin untuk perlahan-lahan mengelilingi kucing yang gementar dan menangkapnya. Permainan itu hilang jika kucing itu sampai ke tepi kawasan permainan.
Sediakan bahan
Cari di Internet untuk permainan "Surround the Nervous Cat", buka satu dan buka antara muka penyahpepijatan Alih keluar gambar kucing, bulatan kelabu, bulatan oren, dll. daripada rangkaian atau sumber dan simpannya secara setempat.
Perlu diambil perhatian bahawa reka bentuk seni bina MovieCilp baharu dan standard format data MovieClip agak berbeza daripada yang saya ambil dari Internet tidak lagi terpakai. Fail json mc selepas pengubahsuaian mengikut data baharu standard format adalah seperti berikut :
{"mc":{ "stay":{ "frameRate":20, "labels":[], "frames":[ {"res":"stay0000","x":0,"y":0}, {"res":"stay0001","x":0,"y":0}, {"res":"stay0002","x":0,"y":0}, {"res":"stay0003","x":0,"y":0}, {"res":"stay0004","x":0,"y":0}, {"res":"stay0005","x":0,"y":0}, {"res":"stay0006","x":0,"y":0}, {"res":"stay0007","x":0,"y":0}, {"res":"stay0008","x":0,"y":0}, {"res":"stay0009","x":0,"y":0}, {"res":"stay0010","x":0,"y":0}, {"res":"stay0011","x":0,"y":0}, {"res":"stay0012","x":0,"y":0}, {"res":"stay0013","x":0,"y":0}, {"res":"stay0014","x":0,"y":0}, {"res":"stay0015","x":0,"y":0} ] }}, "res":{ "stay0000": {"x":0,"y":0,"w":61,"h":93}, "stay0001": {"x":61,"y":0,"w":61,"h":93}, "stay0002": {"x":122,"y":0,"w":61,"h":93}, "stay0003": {"x":183,"y":0,"w":61,"h":93}, "stay0004": {"x":0,"y":93,"w":61,"h":93}, "stay0005": {"x":61,"y":93,"w":61,"h":93}, "stay0006": {"x":122,"y":93,"w":61,"h":93}, "stay0007": {"x":183,"y":93,"w":61,"h":93}, "stay0008": {"x":0,"y":186,"w":61,"h":93}, "stay0009": {"x":61,"y":186,"w":61,"h":93}, "stay0010": {"x":122,"y":186,"w":61,"h":93}, "stay0011": {"x":183,"y":186,"w":61,"h":93}, "stay0012": {"x":0,"y":279,"w":61,"h":93}, "stay0013": {"x":61,"y":279,"w":61,"h":93}, "stay0014": {"x":122,"y":279,"w":61,"h":93}, "stay0015": {"x":183,"y":279,"w":61,"h":93} }}
Tulis kod
Ringkaskan terutamanya dua masalah utama yang saya hadapi semasa proses pembangunan.
Soalan 1, bagaimanakah kucing harus melarikan diri?
Dalam permainan ini, setiap bulatan mungkin mempunyai tiga keadaan
boleh dilalui, bulatan kelabu menunjukkan
Terdapat sekatan jalan dan ia tidak boleh dilaksanakan, ditunjukkan oleh bulatan oren
Diduduki oleh kucing, bulatan kelabu dengan animasi kucing ditindih padanya
Setiap kali anda klik pada bulatan kelabu, ia akan bertukar menjadi bulatan oren, iaitu keadaan sekatan jalan Pada masa yang sama, kucing akan mengikut klik dan mengorak langkah ke kawasan sekitar.
Arah berjalan
Kawasan permainan terdiri daripada 9*9 bulatan, dan garisan bernombor genap dienden mengikut lebar jejari bulatan ini menyebabkan kucing secara teorinya boleh mempunyai 6 arah berjalan (hanya satu langkah di masa), iaitu kiri, Kiri atas, kanan atas, kanan, kanan bawah, kiri bawah Jika bulatan di kedudukan ini adalah sekatan jalan, arah yang sepadan tidak boleh dilalui.
Jika lima daripada enam jiran di enam arah adalah penghalang jalan, maka sudah tentu mudah untuk memilih laluan, dan yang selebihnya adalah satu-satunya jalan keluar, tetapi jelas keadaannya tidak boleh semudah itu. Situasi yang lebih biasa yang kami hadapi ialah di kalangan jiran dalam enam arah, ada yang secara langsung dalam keadaan sekatan jalan (sememangnya, kami tidak akan mengambil langkah ini), dan ada yang berada dalam keadaan boleh dilalui, tetapi kebolehcapaian ke tepi setiap lain lain.
Sebagai contoh, dalam gambar di atas, pada masa ini, kucing boleh mencapai tepi dengan mengambil tiga langkah ke arah kiri, empat langkah di arah kanan atas dan kanan bawah, ia boleh sampai ke tepi dengan mengambil satu langkah dalam arah kiri dan kanan atas tetapi menghadapi sekatan jalan, dan ia boleh sampai ke tepi dengan berjalan tiga langkah ke arah kiri bawah Melanggar penghadang jalan. Pada masa ini, sudah tentu kita harus meletakkan keutamaan enam arah ini.
Keutamaan
Beginilah cara saya menetapkan keutamaan saya:
Arah lalu lintas> akan menunjukkan arah sekatan jalan, seperti yang ditunjukkan dalam gambar: kiri, kanan atas, kanan bawah> kiri atas, kanan, kiri bawah
Dalam arah trafik, semakin dekat dengan tepi, semakin tinggi keutamaan, seperti yang ditunjukkan dalam gambar: kiri > kanan, kanan atas, kanan bawah
Dalam arah di mana sekatan jalan akan muncul, lebih banyak langkah yang anda boleh ambil, lebih tinggi keutamaan, seperti yang ditunjukkan dalam gambar di bawah kiri > kanan, kiri atas
Kebolehcapaian perjanjian ini dinyatakan sebagai nilai berangka untuk perbandingan Biarkan nilai ini kebolehaksesan.
Arah perjalanan
kebolehcapaian = 1/stepToEdge; //stepToEdge menunjukkan bilangan langkah yang tinggal dari tepi
Arah di mana sekatan jalan akan muncul
kebolehcapaian = (-1)/stepToBlock;//stepToBlock mewakili jarak dari sekatan jalan
Seterusnya, pertimbangkan apa yang perlu dilakukan jika penyebutnya ialah 0. Dalam kes pertama, penyebutnya ialah 0, yang bermaksud bahawa kucing sedang berada di tepi, jadi tidak perlu menilai keutamaan, dan permainan mempunyai gagal. Dalam kes kedua, penyebut 0 bermakna anda akan menghadapi sekatan jalan apabila anda keluar arah ini sama sekali tidak boleh dicapai tanpa mengambil kiranya, jadi keutamaannya ditetapkan kepada -1.
Selepas pengiraan ini, nilai kebolehaksesan dalam enam arah ialah:
Kiri: 1/3
Kiri atas: -1
Atas kanan: 1/4
Kanan: -1
Kanan bawah: 1/4
Kiri bawah: -1/3
Dalam perbandingan ini, keutamaan harus berada di kiri > kanan atas > kanan bawah > kiri bawah > kiri atas > kanan.
Mengapa nilai-nilai di dalam kumpulan kiri dan kanan atas, kanan atas dan kanan bawah jelas sama, tetapi kami masih menyusunnya mengikut urutan? Hanya kerana pengiraan kami bermula dari arah kiri dan berputar mengikut arah jam. Jika nilai adalah sama, maka ia bergantung pada susunan di mana ia muncul.
Jadi dalam keadaan dalam gambar di atas ini, kucing akan mengambil langkah ke kiri.
Soalan 2, bagaimana untuk mengetahui sama ada kucing dikelilingi?
Semasa bermain permainan ini dalam talian, saya mendapati bahawa apabila kucing dikelilingi, ia akan bertukar kepada tindakan "dikelilingi" Jadi bagaimana untuk menilai bahawa kucing itu dikelilingi dan kemudian menukar animasi aksinya?
"Dikepung" tidak sama dengan "tangkap", ia mendahului keadaan "terperangkap". Apabila kucing tidak mempunyai tempat untuk pergi, ia "ditangkap" dan permainan dimenangi. "Dikelilingi" bermakna kucing masih mempunyai jalan untuk pergi, tetapi ia dikelilingi dan bergelut hingga mati, seperti yang ditunjukkan dalam gambar di bawah.
Idea saya ialah:
Cari jiran yang boleh dilalui dalam enam arah dari kedudukan semasa kucing, dan kemudian mulakan dari jiran ini untuk mencari jiran yang boleh dilalui masing-masing Teruskan mencari dengan cara ini, dan semasa mencari, nilai yang telah ditemui setakat ini. Adakah terdapat mana-mana jiran di pinggir kawasan permainan Jika ya, proses carian akan tamat lebih awal, dan keputusan penghakiman adalah: kucing tidak dikelilingi. Jika semua jiran yang boleh dilalui ditemui dan tiada seorang pun daripada mereka berada di pinggir kawasan permainan, maka keputusan penghakiman ialah: kucing itu dikelilingi.
Seterusnya, gunakan kod untuk melaksanakan proses penghakiman ini.
首先,需要准备一个方法,判断圆圈是否已经处在圆圈边缘了,假设这个方法名及参数如下,内部实现比较简单这里就不贴了。
/* 判断传入的circle是否在边界上 */ private isCircleAtEdge(circle:Circle):boolean { ... }
再准备一个方法,获取某圆圈周围某方向的邻居。
private getCircleNeighbor(circle:Circle,direction:Direction):Circle{ ... }
最后,是判断的核心方法。
/* 能否在circle位置出发找到路线到达边缘 */ private canExitAt(circle:Circle):boolean{ var ignoreArr=[];//不用再处理的circle集合 var toDealWithArr=[circle];//还需进行判断的circle集合 while(true){ if(toDealWithArr.length<1){ return false; }else{ var _first=toDealWithArr.shift(); ignoreArr.push(_first); if(_first.getStatus()!==CircleStatus.Blocked&&this.isCircleAtEdge(_first)){ return true; }else{ for(var i=Direction.LEFT;i<=Direction.BOTTOM_LEFT;i++){ var nbr=this.getCircleNeighbor(_first,i); if(!(ignoreArr.indexOf(nbr)>-1||toDealWithArr.indexOf(nbr)>-1)) if(nbr.getStatus()!==CircleStatus.Available){ ignoreArr.push(nbr); }else{ toDealWithArr.push(nbr); } } } } } }
在方法体的最开始,准备好两个数组,一个用来存储不用再处理的圆圈集合ignoreArr,另一个用来存储还需要进行判断的圆圈集合toDealWithArr。每找到一个可通行的邻居,首先要判断它是不是第一次出现(因为几个圆圈可能会有共同的邻居,所以一个圆圈可能因为它是多个圆圈的邻居而被找到多次),判断的标准就是它有没有出现在ignoreArr或toDealWithArr里,如果没有那么就是第一次出现,如果它是路障,那么塞到ignoreArr,如果不是路障,那么推入toDealWithArr尾部等待判断。
每次循环开始时,我们会从toDealWithArr头部弹出一个圆圈对象,对它是否在边缘做判断,如果是,那么返回true跳出循环,猫没有被围住,它可以通过某条路线到达边缘。如果toDealWithArr全部判断完了都不在边缘,那么返回false,猫被围住了,它的直接邻居及众多间接邻居中没有一个是在边缘的。