ノスタルゞアボンネットの䞋のタンキキでのうわさ

私たちの倚くは、ゲヌム業界のd明期のタンキキ、マリオ、その他の䞍朜の名䜜で育ちたした。 テレビ画面で友だちず䞀緒に䜕日も過ごし、グロヌブのようなゞョむスティックを倉えた日々を思い出すのはいいこずです。 しかし、時間は止たらず、䞀郚の利益は他の利益に取っお代わられたす。 ただし、叀き良きおもちゃぞの愛が消えないこずもありたす。

私はそのような人々に自分自身を尊重し、叀いゲヌムぞの私の関心はリバヌス゚ンゞニアリングに向けられ、それが私をロバにしたIT領域ぞず導いた。



有名なバトルシティゲヌム䞀般人の堎合は「タンキキ」で有名な任倩堂゚ンタヌテむメントシステム略しおNESの䞭囜のクロヌン「デンディ」はロシアでよく知られおいたす。 か぀お、この情報は私にはかなり興味をそそられたようでした-あなたにも同じように芋えるこずを願っおいたす。



背景



数幎前、私はさたざたなグラフィックラむブラリを勉匷しながら、タンキキの正確なクロヌンを曞くずいう目暙を蚭定したした。 その瞬間、私の友人の䞀人が元のゲヌムのコヌドを倉曎しおかなり興味深いリメむクを䜜成しおいたので、私は圌ず盞談するこずにしたしたずころで、蚘事の準備ず盞談に感謝したす。 それから、いく぀かの機胜が実装されたメ゜ッドを芋぀けたした。 だから、私は長幎、この知識を䞀般の人々ず共有するこずに決めたした。結局、これはgamedevストヌリヌの䞀郚であり、クラシックの愛奜家ず珟代のゲヌムの開発者の䞡方にずっお興味深いかもしれたせん。



ゲヌムを逆コンパむルする圌の努力に察しお、 Grieverずいうニックネヌムの人物に特別な感謝を申し䞊げたす。 たず第䞀に、圌が受け取った情報源のおかげで、そのような詳现に本質を掘り䞋げるこずが可胜になりたした。



レベルカヌド



Battle Cityのマップは、タむル8x8ピクセルのブロックで構成されおいたす。 画面に衚瀺される背景党䜓がマップです。仮に、ラむフカりンタヌを䜿甚しおも盞互䜜甚できたすが、実際にはこれはもちろん倱敗したす。



ただし、シリアル化された圢匏では、レベルはよりコンパクトに保存されたす。このため、タむルは2x2タむルのブロックに配眮されたす。 合蚈で16皮類のブロックがあり、以䞋の衚にリストされおいたす。 マップの䞻芁郚分13x14ブロックのみが栌玍され、その䞊で戊車が走行したす。静的な壁ずサポヌト情報を保持するこずは意味がありたせん。 1぀のブロックを曞き蟌むには4ビットが䜿甚されるため、カヌド党䜓で91バむトかかりたす。



ブロックする コヌド ブロックする コヌド ブロックする コヌド ブロックする コヌド
0 1 2 3
4 5 6 7
8 9 A B
C D E F




ブロックずは異なり、タむル自䜓の皮類ははるかに倚く、぀たり256個です。 キャラクタヌゞェネレヌタヌの1ペヌゞずたったく同じ倧きさ-各タむルが0〜255のむンデックスに察応するビデオメモリセクション。タむルは、レベル環境を䜜成し、敵の戊車数、ラむフなどの情報を衚瀺するために䜿甚されたす。 ただし、レベル芁玠では盎接22個のみが䜿甚されたす。そのうち6個はリストされたブロックを圢成するためのもので、残りの15個はレンガブロックの远加のタむルです。



マップが8x8ピクセルタむルで構成されおいる堎合、4x4ピクセルブリックミニブロックをどのように砎壊したすか 実際には、実際にはこのサむズの「レンガ」はなく、代わりに16皮類の通垞のタむルがありたす各状態に1぀ず぀。 ぀たり 4x4ブロックにヒットするず、実際にはタむル党䜓が眮き換えられ、発射物がヒットした堎所に応じお、レンガ自䜓が異なる状態になりたす。











したがっお、ずころで、レンガブロックの䞀郚を砎壊するずき、タンクは空いおいるスペヌスに入るこずができたせん-結局、タむル自䜓は砎壊されたせんでした。



マップ䞊のリスポヌンポむントずむヌグルポむントの䜍眮は固定されおおり、オブゞェクトは倖芳の堎所に関係なくその堎所に衚瀺されたす。 これは、組み蟌みのレベル゚ディタでこれらの領域が「壁で囲たれおいる」堎合に発生したす。



誰かがマッピングに興味がある堎合、これらの目的のために、ゲヌムの画像を盎接操䜜する優れた゚ディタヌQuarrelがありたす。



乱数生成



ランダムな倀を生成するタスクは、長い間人類を悩たせおきたした。 プログラムで真にランダムな倀を取埗するこずは䞍可胜なので、倚くの堎合、タスクは、ランダムな倀の兞型的な分垃に近い分垃を持぀擬䌌ランダムな倀を生成するように削枛されたした。



完党に決定的な動䜜をするコンピュヌタヌの堎合、擬䌌乱数の生成はさらに困難です。 たずえば、同じボタンを同時に抌すこずで同じ効果を持぀各起動時に、同じゲヌムの進行状況を取埗したす-ゲヌムプロセスの蚘録は、その時点で抌されたボタンが各フレヌムに保存され、 。 しかし、私たちにずっおこれはそれほど重芁ではありたせん。単䞀セッション内で可胜な限り「ランダムな」倀を取埗するこずが重芁です。



Battle Cityの状況を怜蚎しおください。 ここでは、いく぀かの「ランダム」゚ンティティを䜿甚しお擬䌌ランダム倀を生成したす。これは、前のランダム倀、2番目のカりンタヌ、およびいわゆるバむトです。 れロペヌゞ-RAMの最初の256バむト。NESプロセッサは、他のプロセッサよりも高速か぀簡単にアドレス指定できたす。 そのため、れロペヌゞに最も頻繁に䜿甚される倉数が含たれ、その結果、最も頻繁に倉曎される倉数が含たれ、より均䞀な分垃が保蚌されたす。



その結果、数倀の最終倀は、プレヌダヌが抌すボタン、画面䞊のすべおの戊車ず匟䞞の座暙、䞡方のプレヌダヌのポむント数、倚くのタむマヌの状態ボヌナスタむマヌなど、さらにはサりンドチャネルの状態など、倚くの芁因の圱響を受けたす もちろん、これは完党なリストではありたせん。



次の乱数を蚈算する匏自䜓は非垞に単玔です。 詳现には觊れず、Cでどのように芋えるかを瀺したす。

uint8 seed = 0; uint8 index = 0; uint8 rand() { seed = (seed << 3) - seed + secondsCounter + zeroPage[++index]; return seed; }
      
      







コヌドからわかるように、0〜255の範囲の擬䌌乱数倀をい぀でも受け取るこずができたす。さらに、その分垃は、䞍滅のゲヌムプレむからわかるように、非垞に適切です。



ボヌナス



ゲヌムには、ヘルメット、りォッチ、スペヌド、スタヌ、手ren匟、戊車、銃の7皮類のボヌナスがありたす。 同時に、埌者は元のゲヌムではたったく䜿甚されおいたせんが、海賊版の修正で芋぀けるこずができたす-そこで、即座に最倧のアップグレヌドを行いたす。 撮圱した3぀の星に盞圓したす䞀郚のバリ゚ヌションでは、「森」を砎壊するこずもできたす。 残りのボヌナスのアクションは、誰もが知っおいるず思いたす。 ただし、念のために申し䞊げたす。時蚈は敵を凍結させ、シャベルは本郚の呚りに鎧を䜜り、星は戊車の力を増加させ、手destroy匟は画面䞊のすべおの敵を砎壊しポむントは䞎えられたせん、戊車は呜の数を増やしたす。







ずころで、銃を持った海賊版では、別のボヌナスがありたす-あなたが氎の䞭を移動できる船です。 たた、䞀郚の倉曎では、察戊盞手がボヌナスを受け取るこずができ、これによりゲヌムのバランスが根本的に倉わりたす。 そのような倉曎のコレクション党䜓もあり、バヌゞョンはさたざたな同様の些现な点で異なっおいたした。



どうやら、圓初はゲヌムに8぀のボヌナスを含める予定でしたが、最終的には6぀のボヌナスがありたした。 ただし、ボヌナスが衚瀺されるず、8を法ずするランダムな倀0から7が取埗されたす。これは、ボヌナステヌブルのむンデックスであり、ゲヌムに含たれおいないボヌナスの堎所は星ず手g匟によっお再び占有されたす。 その結果、それらの損倱の確率は1/4であり、残りのボヌナスの確率は1/8に等しくなりたす。



ボヌナスりォッチずヘルメットは10秒間有効ですプレむダヌがリスポヌンするず、ヘルメットはリスポヌンの時間を含めお3秒間持続したす、ボヌナススペヌドは20秒です。



ボヌナスキャリア自䜓-点滅するタンク-敵の栌玍庫に17、10、たたは3぀のタンクが残っおいる堎合に衚瀺されたす。 ぀たり 4、11、18ずいう番号のタンクはボヌナスタンクです。



ゲヌムの暙準による秒は通垞より少し長く続くこずに蚀及する䟡倀がありたすコン゜ヌルのNTSCバヌゞョンは60フレヌム/秒のスクリヌンリフレッシュレヌトを持ち、秒を远跡する最も簡単な方法は、60を法ずするフレヌムカりンタヌがれロの堎合、各フレヌムの秒数を増やすこずです。 ただし、蚈算を簡玠化し、オヌバヌフロヌの結果ずしおフレヌムカりンタヌをリセットしおもこの方法では蚈算に圱響しないため、この数倀は64​​0x40に䞞められたした-このモゞュヌルで数倀を取埗するには、0x3Fで論理乗算を行うだけで十分です。 ゲヌムの秒は1.06実秒ですが、これはフレヌム数で枬定される期間には適甚されたせん。



ゲヌムに粟通しおいるすべおの人に知られおいる興味深い事実行動を止める前に、本郚呚蟺の防埡が「点滅」し始め、レンガたたは装甲フェンスに倉わりたすこれはボヌナスの最埌の4秒間に起こりたす。 この堎合、本瀟呚蟺の保護が郚分的たたは完党に砎壊された堎合でも、点滅するたびに、レンガの壁党䜓に完党に戻るたで埩元されたす。



盞手の知性



もちろん、戊車のAIは戊術的な分析噚ではありたせんが、いく぀かのロゞックはただ蚈算されおいたす。



たず、ゲヌムには動的な耇雑さがありたす。 耇雑さの指暙ずしお、敵のリスポヌン間の遅延の倀が䜿甚されたす。これは、プレむダヌのレベルず数に䟝存したす-これらの倀が高いほど、リスポヌンが速くなりたす。 特定のレベルれロからの番号付けのフレヌムでのリスポヌン時間ずプレむダヌ数は、次の公匏を䜿甚しお蚈算できたす 190 - level * 4 - (player_count - 1) * 20



。 秒単䜍で時間を取埗するには、結果に60を掛けるだけです。



戊車の動䜜には3぀の期間がありたす。最初にランダムに動き、次にプレむダヌを远いかけ、最埌に本郚を攻撃し始めたす。 最初の2぀の期間の期間は同じで、8぀のリスポヌン期間に等しくなりたす。 ぀たり、リスポヌン時間を8で割るず、秒単䜍で期間が埗られたすたたは、8倍するずフレヌム単䜍で同じ時間が埗られたす。たずえば、最初のレベルず1人のプレヌダヌの堎合は23秒になりたす。 3番目の期間は、秒カりンタがれロにリセットされる256に達するたで続き、期間のサむクルは再開したせん。



この敵の戊術はすべおコマンドシステムに基づいおおり、8バむトが割り圓おられおいたす。プレむダヌの戊車に2぀、敵の戊車に6぀です。 このバむトの䞊䜍4ビットはコマンドに䜿甚され、残りの䞋䜍4ビットは匕数に䜿甚されたす通垞、これは移動の方向です。 結果は16個のコマンドで、それぞれにハンドラヌがありたす。 ハンドラヌは、動きを凊理した埌、各タンクのフレヌムごずに1回呌び出されたす。



既存のコマンドを衚面的に怜蚎したす。





方向を倉曎する機胜がありたす。これは、行動の最初の期間で呌び出されたずきに、戊車の方向をランダムに倉曎したす.2番目の期間では、偶数の戊車に最初のプレむダヌに移動するコマンドを䞎え、奇数の戊車には-2番目に、そしお3番目に本郚に向かっお移動するコマンドを䞎えたす。



敵の戊車がタむルの境界を越えるずき䞡方の座暙が8の倍数になるずき、この関数が戊車に察しお呌び出される確率は1/16です。 戊車の座暙が8の倍数でない堎合、たたは方向転換機胜が呌び出されず、これで戊車が障害物にぶ぀かった堎合、1/4の確率で次のこずが起こりたす。少なくずも1぀の座暙が倍数でない堎合、戊車は反察方向に方向を倉えたす8、それ以倖の堎合、タンクは方向転換コマンドを䞎えられたす。



方向倉曎コマンドが実行されるず、䜕か他のこずが起こりたす確率1/2で、䞊蚘の関数が呌び出されたす。そうでなければ、等しい確率で、リストから前たたは次の方向が取られたす䞊、巊、䞋、右぀たり、タンクが回転したす時蚈回りたたは反時蚈回り。



このようなすべおのロゞックは、このような擬䌌コヌドの圢で想像できたす。

 void changeDirection(Tank tank) { // period duration in seconds, respawn time in frames const int periodDuration = respawnTime / 8; if (time() < periodDuration) { // first period tank.setRandomDirection(); tank.setCommand(cmdCheckTileReach); } else if (time() < periodDuration * 2) { // second period if ((firstPlayer.isAlive && tank.number % 2 == 0) || !secondPlayer.isAlive) { tank.setCommand(cmdMoveToFirstPlayer); } else { tank.setCommand(cmdMoveToSecondPlayer); } } else { // third period tank.setCommand(cmdMoveToEagle); } } void onCheckTileReachCommand(Tank tank) { if (!tank.isPlayer && tank.x % 8 == 0 && tank.y % 8 == 0 && rand() % 16 == 0) { changeDirection(tank); } else if (!tank.isPlayer && frontTile.isBarrier && rand() % 4 == 0) { if (tank.x % 8 != 0 || tank.y % 8 != 0) { tank.invertDirection(); } else { tank.setCommand(cmdChangeDirection); } } } void onChangeDirectionCommand(Tank tank) { if (rand() % 2 == 0) { changeDirection(tank); } else if (rand() % 2 == 0) { tank.rotateClockwise(); } else { tank.rotateAnticlockwise(); } }
      
      







タンクが障害物たたは壁に接するず興味深い状況が発生したす。この堎合、タンクが回転しなくおも、座暙の1぀は垞に8の倍数であり、その前にタむル障害物があるため、回転の確率が数倍増加するためです。 したがっお、戊車は実際には定䜍眮に留たりたせん。たずえ角やニッチになったずしおも、すぐにそこから移動したす。



敵の射撃の状況も同様に興味深いものです。 単独では、それらは戊車ずは完党に分離しお発生したす。各敵には1぀の匟䞞があり、各フレヌムのショットによっお、この匟䞞を発射するかどうかが決定されたす。 匟䞞がすでに飛行䞭の堎合、ショットは発生したせん。そうでない堎合、戊車が発砲する確率は1/32です。 この堎合、匟䞞は䞭倮の戊車の正面にあり、戊車の方向を継承したす。



デモンストレヌションモヌドでのプレむダヌの戊車の動䜜に぀いお、いく぀かの蚀葉を蚀う䟡倀がありたす。 ここではすべおが単玔です。画面にボヌナスがある堎合、戊車はそれらに気を配りたす匟䞞が圌らが遭遇する障害を越えお飛ぶず、圌らは道に沿っお立ち埀生するこずができたす。 そうでなければ、圌らは単に最初に利甚可胜な戊車を远いかけ、もし䜕も残っおいなければ、圌らは静止したす。 砲匟は敵の戊車ず同じルヌルに埓っお発射されたす。 デモモヌドでの単独の発射は効果がありたせん。



衝突凊理



衝突蚈算は、垞にかなり芁求の厳しい䜜業であり、NESのようなプロセッサにずっお重芁な堎合がありたす。 タンクず「額」の実装ずの盞互䜜甚の蚈算を誀るず、タンクの各ペアを比范する必芁がありたす。これは、数が少ないにも関わらず、クロック速床が1.76 MHzのプロセッサにずっおはかなり高䟡な手順です。 しかし、マップ䞊の戊車に加えお、解攟されたシェルも移動するこずを忘れないでください。 そのため、開発者はかなり興味深いトリックを行いたした。



事実は、各タンクがその䞋に目に芋えない壁を「描く」ずいうこずです。 したがっお、タンクずレベル芁玠ずの衝突怜出の段階で、タンク間の衝突怜出が発生したす。特定の座暙に障害物があるかどうかを刀断するのに十分です。 副䜜甚がありたす倚くの人は、タンクを前方に移動するタンクに「ドラむブ」しようずするず、タンクがある皋床の距離を移動するたでプレむダヌの動きがブロックされるこずに気づきたした-その瞬間、次のタむルに移動し、そこに新しいものを「描画」壁ず叀い「消去」。











砲匟が戊車に呜䞭しおも同じ効果が芋られたす。 芖芚的には、接觊はタンクのスプラむトの境界から異なる距離内偎ず倖偎の䞡方で発生したす-0から7ピクセルたで。 しかし、戊車がそれらの䞋に壁を描く堎合、匟䞞はそうではありたせん。 さらに、シェル間の衝突の蚈算には、ほずんどのフレヌム時間がかかりたす 特別な堎合には、それでも十分ではない堎合があり、これらの操䜜はすべお次のフレヌムに転送され、珟圚の操䜜は倉曎されたせん。 ぀たり はい、タンチキには遅れがありたす。



あるプレむダヌのシェルが別のプレむダヌにヒットした堎合、2番目のプレむダヌは192フレヌムのモヌションコントロヌルを倱いたす。 3秒間ゲヌムしたす。 しかし、デモンストレヌションモヌドでは、これは起こりたせん。



発射物には、衝突がチェックされる2぀のポむントがあるこずに泚意しおください。 それらは匟䞞の錻の偎面にあり、実際には2぀の衝突を同時に凊理できたすそうでなければ、少なくずも1぀を怜出した埌、発射物が消えたす。 これは、たずえば、レンガブロックの䞭心を狙った堎合に発生したす。ストリップ党䜓が砎壊されたす。



もう1぀の興味深い点は、䜎速の匟䞞速床が少し遅いがすべおのフレヌムではなく、フレヌム党䜓で凊理されるこずです。 理論的には、ゲヌムが奇数フレヌムごずにスロヌダりンし、プロセッサがそのような匟䞞の衝突の凊理に到達する時間がなく、それを延期する状況が発生する可胜性がありたす。 しかし、次のフレヌムでは、圌はそれをたったく凊理する必芁はありたせん このような状況の組み合わせにより、ゲヌムの速床が倧幅に䜎䞋した堎合、䞀郚の緊急事態では䜎速の匟䞞が壁を通り抜けお飛ぶこずがありたす。



ムヌブメント



ゲヌムの速床は、座暙を倉曎するずきにスキップされるフレヌムの数によっお決たりたす。 そのため、たずえば、プレヌダヌの座暙は、ゲヌムの最速の敵である4぀のうち3フレヌムごずに倉化したす。



同じこずがシェルにも圓おはたりたす。シェルには2぀のタむプがありたす。1フレヌムあたり4ピクセルの速床で飛行する高速ず、1フレヌムあたり2ピクセルの速床を持぀䜎速です。



タンク 速床、ピクセル/フレヌム 発射䜓タむプ タンク 速床、ピクセル/フレヌム 発射䜓タむプ
3/4 遅い 2/4 遅い
3/4 クむック 4/4 遅い
3/4 クむック 2/4 クむック
3/4 クむック 2/4 遅い




衝突は移動䞭にも凊理する必芁があるため、フレヌム党䜓に可胜な限り均等に分散しお蚈算を最適化するこずが適切です。 最も単玔なアプロヌチでは、すべおの敵の動きを偶数フレヌムで凊理し、奇数フレヌムでは高速装甲兵員茞送車の動きのみを凊理すれば十分です。 しかし、その埌、奇数フレヌムが過負荷になる可胜性があり、ゲヌムは単に遅れたす。



実際、負荷はかなり巧劙に分散されたす。 フレヌム番号ずタンク番号の間で「XOR」が䜜成され、その結果のみパリティ/奇数がチェックされたす。 その結果、偶数フレヌムでは䜎速タンクの半分が凊理され、奇数フレヌムではもう䞀方が凊理されるこずがわかりたす。



氷䞊での滑走に関するいく぀かの情報。 ここではすべおが簡単ですプレむダヌが氷の䞊で方向ボタンを攟した埌、タンクはさらに28フレヌム぀たり21ピクセルが通過するの間、たたは氷を離れるたで自力で動きたす。 この期間䞭、远跡されたトラックの状態は倉化せず、乗り物の音は倱われたせん。たた、氷䞊で方向ボタンを抌すず、この瞬間のスリップタむマヌがれロの堎合、特城的な音が再生されたす。



むヌスタヌ゚ッグ



むヌスタヌ゚ッグは圓時の倚くのゲヌムで芋られたすが 、バトルシティを迂回したせんでした。



タむトル画面で建蚭モヌドを遞択した堎合、7回START、STARTを抌しお入出しおから、2番目のボタンAを8回抌しお最初のゞョむスティックの䞋ボタンを抌し、次に最初のゞョむスティックを抌しお右に抌したす2番目のボタンBで12回、最埌に最初のゞョむスティックでSTARTボタンを抌すず、悲劇的なラブストヌリヌが衚瀺されたす。







さらに、ゲヌムでは未䜿甚のデヌタを芋぀けるこずができたす-開発者の名前倧久保良䞀、歊文歊道、小柀淳子および象圢文字は、ラブストヌリヌの䞻人公の名前ず通りの名前おそらく圌たたは圌の恋人が䜏んでいたを意味したす。







おそらく、ここの詳现には觊れたせん。これは、䞊蚘のリンクで詳现に説明されおいるためです。



゚ピロヌグ



結論ずしお、ゲヌムを䜜成する前は、ある意味、今よりも優れた芞術でした。 これは途方もないスキルです-ハヌドりェアの制限内に収たり、同時に良いゲヌムを䜜成したす。 これは、本質的に同じ目暙を远求する、想像するのが難しい傑䜜を䜜成するデモシヌンに䌌おいたす。



珟圚、これらはすべお過去のものであり、実際に実装する方法に぀いお考えるこずはできたせん。 私の意芋では、これはゲヌム開発プロセスに入るためのしきい倀を倧幅に䜎䞋させ、埐々にではあるが確実にアヌトよりも通垞のビゞネスに倉わりたす。 おそらく、私はこの点であたりにも矎的です。



All Articles