ホームページ > 記事 > ウェブフロントエンド > Nervous Cat Game の純粋な HTML5 制作 - ソース コード download_javascript スキルを使用
HTML5 Surround the Nervous Cat ゲームの Web バージョンは、HTML5、jquery、Typescript およびその他のテクノロジーに基づいたゲームです。
デモとソース コードのダウンロードが添付されています。ここをクリックしてください デモを見る ソース コードをダウンロードします
昨年WeChatモーメントで流行ったミニゲーム「Surround Nervous Cat」も遊んでみました。ゲームは Egret エンジンを使用して開発されており、Egret は Typescript 言語を使用して構築されているため、ここでのゲームも Typescript を使用して開発されています。
ゲームルール:
画面上の灰色のグリッドをクリックして、緊張している猫をゆっくり囲んで捕まえます。猫がプレイエリアの端に到達すると、ゲームは失われます。
材料を準備する
インターネットで「Surround the Nervous Cat」ゲームを検索し、ゲームを開き、デバッグ インターフェイスを開きます。猫、灰色の円、オレンジ色の円などの写真をネットワークまたはリソースから削除し、ローカルに保存します。
Egret の新しい MovieCilp アーキテクチャ設計と MovieClip データ形式標準は、以前のものとは若干異なることに注意してください。新しいデータに従って修正された mc の json ファイルは適用されなくなりました。フォーマット標準は次のとおりです:
{"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} }}
コードを書く
主に、開発プロセス中に遭遇した 2 つの主な問題をまとめます。
質問 1、猫はどうやって逃げるべきですか?
このゲームでは、各円には 3 つの状態があります
は許容範囲、灰色の丸は
を示します障害物があり、実行不可能です。オレンジ色の円で示されています
猫が占領しており、猫のアニメーションが重ねられた灰色の円
灰色の円をクリックすると、オレンジ色の円に変わり、同時に猫がクリックに従って周囲へ進みます。
歩く方向
ゲーム領域は 9*9 の円で構成され、偶数番号の線が円の半径の幅だけくぼみます。このレイアウトにより、理論的には猫は 6 つの歩行方向を持つことができます (1 歩のみ)。時間)、つまり、左、左上、右上、右、右下、左下 これらの位置の円が障害物である場合、対応する方向は通行できません。
6 つの方向の 6 つの隣り合う 5 つが障害物である場合、もちろんルートを選択するのは簡単で、残りの 1 つが唯一の脱出方法ですが、状況はそれほど単純ではないことは明らかです。私たちが遭遇するより一般的な状況は、6 つの方向の隣接するものの中に、直接通行止め状態にあるもの (当然、このステップを実行することはありません) と、通行可能な状態にあるものもありますが、それぞれの端へのアクセスが困難であるというものです。他は違います。
たとえば、上の写真では、現在、猫は左方向に 3 歩、右上と右下方向に 4 歩歩くと端に到達できますが、右方向に 1 歩歩くと端に到達できます。左上と右の方向に進みますが、障害物に遭遇し、左下方向に 3 歩歩いて障害物にぶつかると端に到達できます。このとき、当然、この6つの方向性の優先順位を付けるべきです。
優先度
これが私の優先順位の設定方法です:
交通の方向> は、図に示すように、障害物の方向を示します: 左、右上、右下> 左上、右、左下
図に示すように、交通方向において、端に近いほど優先度が高くなります: 左 > 右、右上、右下
下の図左>右、左上に示すように、障害物が現れる方向に歩数が多いほど優先度が高くなります
これらの契約のアクセシビリティを数値で表し、この値が大きいほど優先度が高くなります。
進行方向
accessibility = 1/stepToEdge; //stepToEdge はエッジから残りのステップ数を示します
障害物が現れる方向
accessibility = (-1)/stepToBlock;//stepToBlock は障害物からの距離を表します
次に、分母が 0 の場合を考えます。最初のケースでは、分母が 0 で、現在猫が有利であることを意味するため、優先順位を判断する必要はなく、ゲームは失敗した。 2 番目のケースでは、分母が 0 であることは、外に出たときに障害物に遭遇することを意味するため、この方向を考慮せずに到達することは絶対に不可能であるため、優先度は -1 に設定されます。
この計算の後、6 方向のアクセシビリティ値は次のようになります:
左: 1/3
左上: -1
右上: 1/4
右: -1
右下: 1/4
左下: -1/3
この比較では、左 > 右上 > 右下 > 左下 > 左上 > 右の順に優先します。
左上と右上、右上と右下のグループ内の値が明らかに同じであるにもかかわらず、順番に並べているのはなぜですか?これは、計算が左方向から開始され、時計回りに回転するためです。値が同じ場合、それは出現する順序によって異なります。
つまり、上の写真のこの状況では、猫は左に一歩進みます。
質問 2、猫が囲まれているかどうかを確認するにはどうすればよいですか?
このゲームをオンラインでプレイしているときに、猫が囲まれると「囲まれる」アクションに変わることがわかりました。では、猫が囲まれたことをどのように判断してアクションアニメーションを変更するのでしょうか?
「包囲された」は「捕らえられた」と同じではなく、「捕らえられた」状態に先行します。猫の行き場がなくなったら「捕まえ」てゲームに勝ちます。 「囲まれた」とは、下の写真に示すように、猫にはまだ進むべき道があるにもかかわらず、囲まれて死ぬまで苦戦していることを意味します。
私のアイデアは次のとおりです:
猫の現在位置から6方向にある通行可能な隣人を見つけ、その隣からそれぞれの通行可能な隣人を探し続け、探索しながら、これまでに見つかった隣人を判断します。遊び場の端に隣人がいますか? もしいる場合、探索プロセスは早期に終了し、猫は囲まれていないと判断されます。通行可能な隣人がすべて見つかり、それらのどれもゲームエリアの端にない場合、判定結果は「猫は囲まれている」となります。
次に、この判定プロセスをコードを使用して実装します。
首先,需要准备一个方法,判断圆圈是否已经处在圆圈边缘了,假设这个方法名及参数如下,内部实现比较简单这里就不贴了。
/* 判断传入的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,猫被围住了,它的直接邻居及众多间接邻居中没有一个是在边缘的。