35キロバむトの栞埌キャラバン

プレヌンなJavaScript、7぀の郜垂、荒れ地、攟射性ダモリ、食甚サボテン、近づいおくるキャラバン、盗賊の35キロバむトの瞮小コヌド。 これは䜕ですか これはブラりザで実行される小さなゲヌムです。 その原理は簡単に繰り返すこずができ、最も原始的なバヌゞョンでは、出力デバむスず乱数ゞェネレヌタヌがあれば、おそらくどのデバむスでも再䜜成できたす。 しかし、今日は、最新のブラりザにどのように実装したかを䌝えたいず思いたす。



珟圚のバヌゞョンでは、プレむダヌは栞戊争埌に郜垂間を移動するキャラバンを制埡したす。 ほくろのネズミは食料を盗み、攟射性ダモリはブラフミンを殺したす。 泥棒はキャラバンを远跡し、お金の䞀郚を盗むこずができたす。砂挠では、攟射性の悪鬌、襲撃者、その他の盗賊が攻撃できたす。



蚭定党䜓、䞖界、ロゞックは自由に倉曎できたす。゜ヌスコヌドずグラフィックスはパブリックドメむンずしお、぀たり、コピヌず䜿甚に制限なく配垃されたす。







ゲヌム機胜



レンゞャヌは、食甚サボテンや戊前の猶詰を芋぀けるかもしれたせん。 砂挠では、他の旅行者の死䜓を芋぀けるこずができ、そこから少しのお金を集めるこずができたす。 近づいおくるキャラバンから食べ物やバラモンを賌入したり、人を雇ったりするこずができたす。 そしお、あなたはカリスマでそれらを打った堎合、近づいおいるトランプ、時には盗賊にさえ参加するこずができたす。 冗談。 実際、ゲヌムにはただカリスマ性はなく、ランダムな家によっお゚ミュレヌトされおいたす。



実際、このゲヌムはテキストゲヌムの進化の次の段階であり、䞖界地図䞊の動き、ランダムな出䌚い、JavaScriptにモゞュヌルを远加する機胜を远加したした。



機胜は簡単に拡匵でき、カリスマ性やその他の実際の圹割芁因は自分で远加できたす。 プログラミングしたくない堎合でも、メモ垳で䞀連のむベントを䜿甚しおファむルを開き、新しいむベントを远加したり、バランスを倉曎したり、䞖界ず耳錻咜喉科を完党に曞き盎したりするこずができたす。 たたは、異なる恒星系の間で宇宙船をさたよいながらただし、道路を暪切る可食性サボテンを捚おる必芁がありたす。



このゲヌムの仕組みは非垞にシンプルで、そのグラフィカル機胜はダむアログ、むンゞケヌタヌ、䞖界地図䞊の動きです。 圌女の匷みは、最も信じられないほどの冒険を蚀葉で衚珟できるテキストゲヌムの魔法にありたす。



プログラムの䞻なアむデアずロゞック



ゲヌムの基本的な考え方は非垞に単玔です-無限ルヌプを開始し、その内郚で4぀の基本操䜜が実行されたす。



  1. 特定のポむントぞの移動
  2. 日のカりントダりン
  3. 食物摂取
  4. 荒れ地で私たちを埅っおいるむベントの確率チェック


最埌の操䜜は非垞に嗅ぎやすい箱で、そこから、地獄、盗賊、悪鬌、死んだ旅行者ずの出䌚い、飛び出しで思い぀く他のすべおの冒険がありたす。



これはどうですか 非垞にシンプル-各むベントはキャラバンたたは䞖界の数倀パラメヌタヌを倉曎し、ログに報告するだけです。 ここに魔法がありたす-パラメヌタヌは同じでもかたいたせんが、たったく異なる理由を報告できたす。 食べ物の数単䜍を枛らしたすか これらは、ラットの攻撃、攟射性降䞋物、たたは空腹のベビヌカヌです。 プラス数個の食物 それで、あなたの人々は食甚のサボテン、道端の遺跡で発掘された戊前の猶詰、たたは道に柔らかい靎底の玠晎らしい革のブヌツを芋぀けたした。



私が実隓を始めた最初のバヌゞョンは、説明したアルゎリズムのわかりやすい図のように芋えたした。







このプロトタむプからオレゎンキャラバンゲヌムのリメむクずしおこのプロトタむプを䜜りたした。



䞀次元のプロトタむプ-js13kGamesのキャラバン



私が芋぀けたチュヌトリアルのゲヌムは1次元でした。キャラバンは1぀のポむントを離れお別のポむントに移動したした。 途䞭、ランダムなむベント、盗賊や商人ずの䌚合がありたした。







このバヌゞョンのプレヌダヌは非垞に限られおいた。 基本的に、圌はむベントログを賞賛しなければなりたせんでした。 むンタラクションは、店や山賊が登堎したずきにのみ発生したした。 さらに、すべおのむベントの確率は等しく、1぀の配列に栌玍されおいたした。



結果を芋るず、ゲヌムを実際のサンドボックスに拡匵できるこずに気付きたした。 必芁なこずは、自由を远加し、コヌドをモゞュヌル化し、むベントを異なるモゞュヌルに配垃するこずだけでした。 コヌドをほが完党に䜜り盎す必芁がありたした。



倉曎履歎
  1. 再利甚可胜な旅-ゲヌムは目暙の達成で止たらない
  2. 䞖界ず郜垂の2次元地図
  3. 䞖界のもう䞀぀の蚭定であり、赀痢はありたせん
  4. 盗賊は亀枉ず関䞎ができる
  5. 郜垂に到着するず自動的に売買される远加補品
  6. モゞュラヌシステム-プラグむンベヌスのロゞックず䞀連のむベントを別々のファむルに




キャラバン゚ンゞンずアヌキテクチャ



既に述べたように、このゲヌムはサヌドパヌティのラむブラリを䜿甚せずに玔粋なJavaScriptで䜜成されおいたす必芁に応じお自分で远加できたす。 通垞のHTMLずCSSを䜿甚しお、䞖界地図ずむンタヌフェむスを衚瀺したす。 それらを倉曎するには、基本的なDOM操䜜ず埓来のdocument.getElementById操䜜が䜿甚されたす。



キャラバンのプレむダヌ数を衚瀺する䟋
this.view = {}; //     DOM this.view.crew = document.getElementById('game-stat-crew'); //      // ... this.view.crew.innerHTML = world.crew; //        html
      
      







WorldState-䞖界のモデル



ゲヌムの䞖界はWorldStateクラスです。 すべおの重芁なパラメヌタが保存され、ロゞックは含たれおいたせん。 プラグむンのため、ロゞックを埌で結びたす。



 function WorldState(stats) { this.day = 0; //  ,    this.crew = stats.crew; //   this.oxen = stats.oxen; //   this.food = stats.food; //   this.firepower = stats.firepower; //   this.cargo = stats.cargo; //    this.money = stats.money; // //  ,  ,    // { day: 1, message: " ", goodness: Goodness.positive} this.log = []; //  ,     this.caravan = { x: 0, y: 0}; this.from = {x: 0, y: 0}; this.to = {x: 0, y: 0}; this.distance = 0; //    this.gameover = false; // gameover this.stop = false; //    ,    this.uiLock = false; //     }
      
      





ゲヌム-䞖界の創造ずゲヌムサむクル



ゲヌムルヌプは、Gameオブゞェクトによっお開始および制埡されたす。 同じオブゞェクトが䞖界を䜜成したす。 プラグむンフィヌルドに泚意しおください-デフォルトでは空の配列です。 ゲヌムはプラグむンに぀いお䜕も知りたせんが、2぀のこずを陀いお-初期化䞖界初期化関数ず曎新曎新関数が必芁です。



 Game = { plugins: [], //  , }; Game.init = function () { //           //   StartWorldState   data this.world = new WorldState(StartWorldState); var i; for (i = 0; i < this.plugins.length; i++) { this.plugins[i].init(this.world); } }; //   Game.addPlugin = function (plugin) { this.plugins.push(plugin); }; //   Game.update = function () { if (this.world.gameover) return; //   var i; for (i = 0; i < this.plugins.length; i++) { this.plugins[i].update(); } }; Game.resume = function () { this.interval = setInterval(this.update.bind(this), GameConstants.STEP_IN_MS); }; Game.stop = function () { clearInterval(this.interval); }; Game.restart = function () { this.init(); this.resume(); };
      
      





新しいゲヌムを開始するには、Game.restart関数を呌び出す必芁がありたす。 ただし、これが発生する前に、䜕らかのプラグむンを远加する必芁がありたす。远加しないず、ゲヌムサむクルをアむドル状態でプレむする必芁がありたす。



食べる、生きる、移動する-CorePlugin



キャラバンの最も基本的なアクション-移動、時間のカりント、食べ物の摂取-は、CorePluginオブゞェクトに実装されおいたす。



CorePlugin゜ヌスコヌド
 CorePlugin = {}; CorePlugin.init = function (world) { this.world = world; //  world this.time = 0; //     ,   this.dayDelta = GameConstants.STEP_IN_MS / GameConstants.DAY_IN_MS; //       this.lastDay = -1; //     this.speedDelta = Caravan.FULL_SPEED - Caravan.SLOW_SPEED; //       }; CorePlugin.update = function () { if (this.world.stop) return; //   -   this.time += GameConstants.STEP_IN_MS; //   this.world.day = Math.ceil(this.time / GameConstants.DAY_IN_MS); //  ,  //      ,    this.updateDistance(this.dayDelta, this.world); //       if (this.lastDay < this.world.day) { this.consumeFood(this.world); this.lastDay = this.world.day; } }; //       CorePlugin.consumeFood = function (world) { world.food -= world.crew * Caravan.FOOD_PER_PERSON; if (world.food < 0) { world.food = 0; } }; //           CorePlugin.updateDistance = function (dayDelta, world) { var maxWeight = getCaravanMaxWeight(world); var weight = getCaravanWeight(world); //   - Caravan.SLOW_SPEED //  0  - Caravan.FULL_SPEED var speed = Caravan.SLOW_SPEED + (this.speedDelta) * Math.max(0, 1 - weight/maxWeight); // ,        var distanceDelta = speed * dayDelta; //     var dx = world.to.x - world.caravan.x; var dy = world.to.y - world.caravan.y; //      -  if(areNearPoints(world.caravan, world.to, Caravan.TOUCH_DISTANCE)){ world.stop = true; return; } //     -    //      var angle = Math.atan2(dy, dx); world.caravan.x += Math.cos(angle) * distanceDelta; world.caravan.y += Math.sin(angle) * distanceDelta; world.distance += distanceDelta; }; //     Game.addPlugin(CorePlugin);
      
      







ここではすべおが基本です。 たず、ゲヌムが開始されるず、initが呌び出されたす。これにより、䞖界のモデルぞのリンクを保存できたす。 次に、ゲヌムルヌプでupdateを呌び出したす。これは、シリヌズ「シリコンバレヌ」のキャラクタヌが奜んで蚀うように、䞖界をより良く倉えるでしょう。 それは冗談です-䞖界はあらゆる方向に倉化したす。



基本的なプラグむンは、ミリ秒単䜍で時間をカりントし、それらを日数に倉換しおから、距離ず食糧備蓄を曎新したす。 原則ずしお、プラグむンオブゞェクトにはinitworldおよびupdate関数を含めるだけで、䜕でもできたす。 他のHTML5ゲヌムを呌び出すか、ダむアログボックスを䜜成するこずもできたす。



プラグむンを接続するには、Gameオブゞェクトの定矩ずGame.restartの最初の呌び出しの間にそのコヌドを远加する必芁がありたす。 珟圚index.htmlで行われおいる方法に぀いお



 <script src="js/Game.js"></script> <!--  --> <script src="js/plugins/CorePlugin.js"></script> <!--   --> <script> Game.restart(); </script>
      
      





キャラバンゲヌムの䜜り方



あなたが経隓豊富なプログラマヌなら、「むベントの配列からの動きずランダムな遞択が存圚するサむクル」ずいうアむデアから始めお、どんな蚀語やグラフィックレベルでもこの​​ようなおもちゃを確実に実装できたす。 特に最近の出版物には非垞に興味深いグラフィカル機胜があるこずが瀺されおいるため、bashのゲヌムでさえ完党に機胜するず思いたす。



JavaScriptに粟通しおいる堎合、基本的なレベルであっおも、この蚀語で䜜成したゲヌムの゜ヌスをダりンロヌドしお、自由に倉曎および改善できたす。 電流が自分に合わない堎合は、任意のアヌキテクチャを䜿甚できたす。 しかし、最も簡単なオプションは、䞊蚘の原則に埓っお実装されたプラグむンを単に远加するこずです。



既存のプラグむンは、index.htmlから゜ヌスコヌドを削陀するか、コヌドの最埌にあるGame.addPluginSomePluginで行をコメントアりトするこずで無効にできたす。 圌らはお互いに぀いお䜕も知らず、単に䞖界のモデルたたはゲヌムのむンタヌフェヌスを倉曎したす。



さお、ラむタヌの最埌のオプション-デヌタディレクトリのファむルを開き、むベントず定数の説明を線集するだけです。 これらは同じJavaScript゜ヌスですが、簡単に倉曎できたす。 特にテキスト。 これを蚌明するために、珟圚のバヌゞョンで他のプラグむンがどのように配眮されおいるかを簡単に説明したす。



ランダムむベント



すべおのプリミティブランダムむベントは、次の圢匏の倉数RandomEventsのdata / RandomEvents.jsファむルにありたす。



 var RandomEvents = [ { goodness: Goodness.negative, stat: 'crew', value: -4, text: '   ! : -$1' }, { goodness: Goodness.negative, stat: 'food', value: -10, text: '     .  : -$1' }, { goodness: Goodness.positive, stat: 'money', value: 15, text: '    .    . : +$1' }, { goodness: Goodness.positive, stat: 'crew', value: 2, text: '   ,       . : +$1' },
      
      





ランダムむベントオブゞェクトは䞭括匧で囲たれおいたす。 この䟋では、4぀のオブゞェクトのみを匕甚したしたが、䞀般的にはその数は䜕でもかたいたせん。 むベントの数が増えるず、特定のむベントが萜ちる可胜性が䜎くなるこずに泚意しおください。



最初のフィヌルド-良さ-は、ログ内のメッセヌゞのポゞティブ、ネガティブ、およびニュヌトラルカラヌを意味したす。 2番目のフィヌルドstatには、倉曎する必芁があるWorldStateパラメヌタヌの名前が含たれおいたす。 倀は、このパラメヌタヌを倉曎する平均倀です。 最埌のフィヌルド-䜕が起こったかを説明する任意のテキストを含む必芁がありたす。 $ 1蚘号の代わりに、テキストはゲヌムに衚瀺されるパラメヌタヌの実際の倉曎に眮き換えられたす。



RandomEventPluginオブゞェクトでランダムむベントの発生がチェックされ、ログのプレヌダヌの倖芳が喜ばれたす。







最埌の泚意RandomEvents.jsには、ランダムむベントの発生の確率定数を持぀倉数がありたす。 これは、キャラバンの1詊合あたりの平均むベント数ずしお定矩されたす。 さたざたな倀を詊しおみたずころ、どのような方法でも圱響を受けないランダムなむベントが倚すぎお、非垞にむラむラするこずがわかりたした。 察話性の欠劂は、これらの単玔なむベントの䞻な欠点です。 だからこそ、私は頭を掻き、他のプラグむンから呌び出すこずができるナニバヌサルダむアログモゞュヌルを䜜成するこずにしたした。



ダむアログの䜜成たたは線集方法



DialogWindowオブゞェクトは、ダむアログシステムを担圓したす。 ゜ヌスコヌドを芋るず、HTMLコヌド内で必芁なdiv芁玠を芋぀け、䞀般的なマりスクリックハンドラヌをバむンドするミュヌタントが衚瀺されたす。 このオブゞェクトに新しいダむアログを衚瀺するように䟝頌するず、ダむアログの配列が枡されたす。 たた、特定の遞択肢をクリックするためのハンドラヌは、次の圢匏の特定のダむアログで説明されおいたす。



 var DeathDialogs = { "start": { icon: "images/pic_death.jpg", //   url  title: "  ", //   desc: "", //    desc_action: function (world, rule) { //       var desc = "  : "+rule.text+".    "+Math.floor(world.distance) + "    "+Math.floor(world.money) + " "; desc += " ,    ?" return desc; }, choices:[ //   { text: '  ', //    action: function () { return "stop"; } // ,     } ] }, };
      
      





死のダむアログには、「開始」フィヌルドず呌ばれるオプションが1぀しかありたせん。 しかし、そのようなオプションは無限にありたす。 たずえば、盗賊の察話では、12のフォヌクを実装したした。 それらの間の移行はどうですか show関数を呌び出すず、ナニバヌサルDialogWindowオブゞェクトは転送されたダむアログのリストを保存し、「開始」フィヌルドで定矩されたダむアログを衚瀺したす。



次のダむアログを衚瀺するずき、その遞択肢配列は、遞択番号が曞き蟌たれる属性にボタンのセットずしお衚瀺されたす。 たた、遞択肢からのすべおのアクション関数は、dialogActionsの内郚配列に曞き蟌たれたす。 遞択ボタンをクリックするず、ナニバヌサルハンドラヌはdialogActionsの関数の数を決定しお呌び出し、このダむアログで䜿甚するこずにした2぀の匕数を途䞭で枡したす。 したがっお、山賊ずの察話では、特定の遞択肢のアクション関数は、䞖界の状態䞖界ず珟圚の山賊の説明山賊を受け入れるこずができたす。 そしお、他のプラグむンぞのダむアログで-他のパラメヌタヌ。 はい、特に遞択の意味がゲヌムりィザヌドのように単に察話を終了するこずである堎合、それらなしでも可胜です。







ダむアログを終了し、プレむダヌが䞖界地図に戻るには、choiceオブゞェクトのアクション関数が予玄枈みのタグ「finish」、「exit」、「stop」のいずれかを返す必芁がありたす。 䞀般に、この関数の意味は、次のフォヌクの名前を返すこずです。 しかし、この倧事な垰還の前に、ロゞック、次の分岐を遞択できる蚈算、「実行」、「戊い」、あるいは「愛」さえも挿入するこずができたす。



プラグむンからダむアログを呌び出す方法



動䜜䞭のプラグむンの曎新の任意の時点で、次のようにダむアログを呌び出すこずができたす。



  // ... -   update  - //  ,   world.stop = true; //        DeathDialogs //      world  rule DialogWindow.show(DeathDialogs, world, rule, this);
      
      





たた、onDialogClose関数はプラグむンに実装する必芁がありたす-このコヌルバックはダむアログを閉じた埌に呌び出されたす。 死の始たりを決定するプラグむンの䟋



 DeathCheck.onDialogClose = function () { Game.restart(); };
      
      





既存のプラグむンの簡単な説明



ゲヌムの珟圚のバヌゞョンでは、次のプラグむンが䜿甚されおいたす。



Map2DPlugin-マップ䞊でキャラバンを移動したす。 index.htmlでtopパラメヌタヌずleftパラメヌタヌを持぀通垞のdivずしお指定されおいる郜垂を怜玢したす。 ここで、郜垂ぞの到着が決定され、自動取匕が行われたす。



ShopPlugin-ランダムに接近するキャラバンたたは他の商人を生成したす。 食料、ブラフミンを賌入し、merc兵を雇うこずができたす。 たたは䜕も買わずに次に進みたす。



BanditPlugin-山賊ずの䌚議ず察話。 このプラグむンの途䞭で、簡単なチュヌトリアルを䜜成するずいうアむデアに興奮したした。 シンプルでうたくいきたせんでした、ごめんなさい。 盗賊はあなたに雇うこずができたす、そしお圌らが死に飢えおいるならば、あなたがお金のために雇うこずを拒吊するならば、圌らは無料で圌らを受け入れるようあなたに頌みたす。



DropPlugin-オヌバヌロヌドプラグむン。 オレゎンのキャラバンに関するチュヌトリアルのプロトタむプでは、ゲヌム自䜓が自動的に物を萜ずしたした。たず歊噚、次に食べ物です。 それは非垞に快適で䞍可解ではありたせんでした-どのようにそうですか 結局、歊噚で食べ物を手に入れるこずができ、「揚げ肉で敵を殺すこずはできたせん」cFallout 4からの有名なストリヌムの1぀です。だから私は、単に䜕を取り陀くかを遞択する察話をするこずにしたした。



DeathCheckはデスチェックプラグむンです。 これはただ非垞にシンプルなプラグむンであり、確かに質問があるかもしれたせん。 たずえば、なぜ食べ物が終わるずすぐに死ぬのですか さお、私はこの質問に自分で答えるこずを提案したす-すべおがうたくいけば次のバヌゞョンを埅ちたす。



WorldViewPluginはむンタヌフェむスプラグむンです。 むンタヌフェむスを曎新するだけで、䞖界の珟圚のパラメヌタヌが衚瀺されたす。 おそらく、この考えは誰かにずっお奇劙に思えたす-曎新サむクルの倉数の倉化を監芖する独立したむンタヌフェむスオブゞェクト。 しかし、この奇劙なアむデアのおかげで、倚数のupdateUiを取り陀き、異なるロゞックのブロック間の独立性を獲埗したした。



珟圚のゲヌムずバランスに関するいく぀かのヒント



珟圚、重芁なパラメヌタは食物の量です。 他のキャラバンずの䌚議で補充するこずができたす-発生した堎合、最倧限に賌入する必芁がありたす。 もちろん、郜垂で賌入を远加するのが賢明でしょうが、これたでのずころ、圌らは皆、食料の䞍足に苊しんでいるず仮定したす。



2番目の重芁なパラメヌタヌは、キャラバンの人数です。 圌らはそうあるべきです。 すべおの人がノックアりトされた堎合-ゲヌムは終了したす。



バランスのすべおの倉化は、食物ぞのダメヌゞず人数を増加させ、ゲヌムの耇雑さを劇的に増加させたす。



リンクず配垃



pixabay.orgずopengameart.orgのCreative Common 0ラむセンスでグラフィックスを䜿甚したため、グラフィックスずコヌドの䞡方がこれらの条件䞋で配垃されたす-コピヌず䜿甚は無料で、矩務はありたせん。



GitHubから゜ヌスコヌドを取埗するか、こちらから zipアヌカむブをダりンロヌドできたす 。 より頻繁に曎新されるため、最初のオプションが望たしいです。



テストには、ロヌカルコンピュヌタヌ䞊でも、ブラりザヌでindex.htmlを開くだけで十分です。サヌバヌを必芁ずする機胜はそこで䜿甚されたせん。



ラむブビルドゲヌムはここでテストできたす 。 レむアりトは、モバむル画面甚ではなく、通垞のモニタヌ甚に蚭蚈されおいたす。



All Articles