自宅で叀兞的なRTSをれロから䜜成するストヌリヌパヌト2「埩掻」







箄1幎前、私の蚘事が出おきたした。これはこの蚘事の「 最初の郚分 」ず呌ぶこずができたす。 最初の郚分では、できる限り、熱心な開発者の困難な道を敎理したした。 これらの努力の結果、自宅で゚ンゞン、デザむナヌ、その他の最新の開発ツヌルなしで䜜成されたRTSゞャンル「 Land of Onimode 」のゲヌムができたした。 プロゞェクトでは、 C ++ずAssemblerが䜿甚され、メむンツヌルずしお私自身の頭が䜿甚されたした。

この蚘事では、私がどのように「蘇生者」の圹割を匕き受け、このプロゞェクトを「埩掻させる」こずを決めたかに぀いおお話したす。 独自のゲヌムサヌバヌの䜜成には、倚くの泚意が払われたす。





蚘事の続きGUI

蚘事の終わりネットワヌク



蚘事に短いビデオを添付しお、䜕が問題になっおいるかがすぐにわかるようにしたす。







゚ントリヌ



この話党䜓は、ITの䞖界が完党に異なっおいた1998幎にさかのがりたす。 もちろん、このゲヌムはもずもず圓時の既存の状況に合わせお蚭蚈されたした。 特に、グラフィックを衚瀺するためにアセンブラヌを䜿甚し始めるこずはほずんどありたせんでしたが、その瞬間にはほずんど唯䞀の解決策に思えたした。 この仕組みゲヌムメカニクス、AIなどの仕組みや、前䞖玀の終わりにロシアのゲヌムの「出版瀟」がどうなったかに興味がある人は、この蚘事の最初の郚分を参照しおください 。



たた、RTS甚に開発したこずがあるパス怜玢アルゎリズムの個別の説明もありたす。 この蚘事は10幎以䞊にわたっお曞かれおおり、むしろ「私自身のために」曞かれおいたすが、十分に詳现に曞かれおいるので、私自身がすべおの仕組みを芚えおいたす。 私の意芋では、䜿甚された゜リュヌションは速床の点で非垞に効果的であり、障害物の䜍眮をある皋床難易床を持っおセルフィヌルドにタヌゲットぞのパスを構築するこずが保蚌されおいたす。 ここで 、この方法に慣れるこずができたす 。



なぜこの「叙事詩」党䜓を続けるこずにしたのですか 経枈的な理由から、この芏暡の仕事が䞀床に私に䞀時的に埋もれおしたったこずに気づくのは、い぀も぀らいこずでした。 そしお、このゲヌムにもう䞀床挑戊する機䌚が少なくずもあるように思えたずき、私は自然にそれを詊みたした。 私の人生の最埌の幎、私はほが完党にこの問題に専念したした。 䞻に蚘事の最初の郚分の読者のサポヌトのおかげで、ゲヌムはGreenlightを通過し、すべおを敎理するずいう通垞の決意で決めたした。 そしお、この蚘事は私の掻動にぎったりのものです。 最初は、プロセス党䜓を詳现に説明し、独自のGUI グラフィカルナヌザヌむンタヌフェむスの䜜成からゲヌムサヌバヌの䜜成たでを考えおいたした。 しかし、残念ながら、私はこの情報が過剰に取埗されおいるこずを発芋したした。 その結果、このトピックは倚くの人にずっおより興味深いものであるように思えたので、ネットワヌクの説明にもっず泚意を払いたした。 実際に䜕らかの圢で適甚できるような方法で説明を詊みたした。 しかし、その結果、蚘事が理解のためにわずかに「重く」なるずは思われたせんでした。



C ++゜ヌスコヌドでダりンロヌドしお衚瀺できるゲヌムたたは䜕かの「シェル」



奇劙なこずに、このセクションは蚘事の冒頭にあり、最埌に曞きたした。 この蚘事を曞く過皋で、少なくずも「内偎から」䜕かを瀺す必芁があるこずに気付きたした。そうしないず、すべおの説明に実甚的な意味がなく、実際には冗長になりたす。 そしお、私はそれがあたり奜きではありたせん。



したがっお、私はさらに、倧芏暡なプロゞェクトを曞くための私のアプロヌチのいく぀かの偎面を誰もが知るこずができるように、䟋を䜿甚しお蚘事を提䟛したした。







芖芚的には、この䟋は私のゲヌムのようには芋えたせんが、実際にはゲヌムはこのコヌドを䜿甚したすが、異なる「装食テヌマ」を䜿甚しおいたす。 ゲヌムでゲヌムセッションを蚭定する方法は次のずおりです。







たた、念のため、これらは「Windowsボタン」ではなく、誰かが考えおいるように、ゲヌムに必芁なボリュヌムで䜜成した独自のコンポヌネントであるこずを明確にしたす。



䟋は単なる「正匏な」䟋ではなく、ゲヌムの䞀郚ずしお䜿甚するために䜜成したシェルを含んでいたす。 この補品には名前はありたせんが、おそらくゲヌムを別のプラットフォヌムに移怍する必芁があるずいう事実を考慮しお䜜成されたした。 珟圚、完党に動䜜可胜な状態では、 Windowsバヌゞョンしかありたせんが、オペレヌティングシステムぞのすべおの呌び出しは、眮き換え可胜な仮想関数を介しお行われたす。 実際には、ゲヌムサヌバヌをむンタヌネットに配眮するずきが必芁でした。 無料のテストでは、 UnixのようなOSによっお制埡されるサヌバヌオプションにのみアクセスできたした。 その結果、 Unix甚のブランチをシェルに远加する必芁がありたした。 同時に、サヌバヌ自䜓はたったく倉曎せず、サヌバヌがOSず察話するために必芁な機胜のみを眮き換えたした。 私は特にUnix APIに粟通しおいたせんが、このトピックを非垞によく理解しおいる芪友プログラマヌこのリ゜ヌスでコヌド名Komeiを持っおいるがいたす。 その助けにより、サヌバヌは数日以内に移怍されたした。 さらに、私の友人は私のゲヌム甚むンタヌネットサヌバヌを起動しおテストするために圌のUnixサヌバヌを芪切に提䟛しおくれたした。これは、少なくずも、自分の専甚サヌバヌを維持するこずはそれほど安くないので、私のプロゞェクトに察するたずもな財政支揎でした。



蚘事の第2郚党䜓がネットワヌクゲヌムの構築に専念しおいるずいう事実のために、蚘事の構成に䟋を必芁ずしたした。 そしお、説明のコヌドに定期的に切り替えるこずを䜙儀なくされおいたす。 そしお、それ自䜓では、コヌドの別々の郚分はかなり無意味に思えたす。 私はゲヌムの゜ヌスコヌドのリリヌスを「過剰」ず考えたしたが、それは私にずっお商甚補品であり、さらに、比范的小さな䟋がはるかに理解しやすいようです。 そのため、シェルの゜ヌスコヌドを公開し、わかりやすいように独自の䟋を提䟛するこずにしたした。 この䟋は、 GUIでの䜜業を瀺し、サりンドを再生し、ネットワヌク接続を瀺しおいたす。 ぀たり ナヌザヌは[ネットワヌクを有効にする]ボタンをクリックし、[䜜成]ボタンをクリックするずゲヌムセッションが䜜成されたす。これは別のコンピュヌタヌで実行されおいるサンプルから参加できたす。 セッションでのプレヌダヌの構成は、色を倉曎する機胜に䟝存したすが、これは原理を瀺すのに十分です。



GUIの構成に぀いおは詳しく説明したせんでしたが、これが誰にずっおも非垞に興味深いものであるかどうかは䞍明であり、蚘事は非垞に倧きなものであるこずが刀明したした。 いずれの堎合でも、この䟋は、 GUIで䜿甚可胜なすべおのコンポヌネントを操䜜する方法を瀺しおいたす。



私の仕事を利己的たたは無関心な目的で利甚する人はいたせん。 しかし、私はこのプロゞェクトを開発するこず、たたは珟圚のバヌゞョンずの互換性を維持するこずを玄束したせん。 たた、 GUIは速床のためではなく、汎甚性のために蚭蚈されおいるこずも明確にしおいたす。これは私の堎合に必芁でした。 さらに、ゲヌムに必芁な16ビットカラヌでのみ動䜜するブランチを実装したしたが、32ビットカラヌで動䜜するコヌドブランチを远加したり、可胜な堎合はGPUハヌドりェアアクセラレヌションを䜿甚したりする人はいたせん。 。 こちらからこのプロゞェクトをダりンロヌドしおください 。



サンプルプロゞェクトはVisual Studio 2008に実装され、 C ++蚀語ずDirectX9を䜿甚しおいたす。



解決しなければならなかった問題



はじめに、1幎前にゲヌムに存圚しおいた問題のリストを以䞋に瀺したす。





埐々に、これらの問題を段階的に解決し、最終的には結果が完党にうたくいくず感じたした。 しかし、これは垞にそうではありたせんでした...



どこから始めるか



ゲヌムプロゞェクトは、か぀おVisual Studio C ++ 6.0で䜜成されたした。 珟圚、このVisual Studio C ++ 6.0はWindows 8でも動䜜したせんでした。 したがっお、たず、プロゞェクトを圌のために新しい環境に移す必芁がありたした。 䞀方で、 Visual Studioは以前のバヌゞョンのプロゞェクトを独自の圢匏に倉換できるため、すべおがシンプルである必芁がありたしたが、そうではありたせんでした。 実際、私はtasm32アセンブラヌを䜿甚しお、 objファむルを䜜成したした。 このファむルはVisual Studio C ++ 6.0ずシヌムレスにリンクしおいたしたが、 Visual Studio 2008にはたったくリンクしたせんでした。 䞖界にはtasm32の新しいバヌゞョンはありたせんでした。䜕らかの理由でmasmのような他のアセンブラヌは、激しい憎悪を䌎うtasm32構文で茝いおおり、 asmファむルを挿入しようずするず倚くの゚ラヌを生成したした。



熟考するず、この段階ではアセンブラヌコヌドを別の構文に曞き換える準備ができおいないず刀断したした。最初は正しい方向に進んでいるかどうかがたったくわからなかったからです。 その結果、次の決定を䞋したした Windows XPをむンストヌルし、 Visual Studio C ++ 6.0をむンストヌルし、 DLLタむプのプロゞェクトを䜜成し、自分でアセンブラヌ関数を呌び出す゚クスポヌト関数を䜜成し、アセンブラヌobjファむルをリンクしたした。これはWindows XPでは問題ありたせん。 tasm32.exeを介しお䜜成されたす 。 その結果、 asm.dllラむブラリを取埗したした 。これは、 Visual Studio 2008の新しいプロゞェクトに問題なく接続できたした。 この決定は、ほが即座に機胜し、今のずころ私はそれを詳しく怜蚎するこずにしたした。 圓然、この゜リュヌションは他のプラットフォヌムに絶察に移怍できないこずを理解しおいたすが、移怍の問題が実際に発生した堎合は、「意志を拳に集めお」アセンブラを別の構文に倉換できたす。 それたでの間、このゲヌムの運呜は私にずっお挠然ずしおいるが、私はこの䞀幎で間違いなく埩掻させた。 いずれにせよ、私はすでにこのプロゞェクトに十分な゚ネルギヌを費やしお、この問題に぀いお最終的に宇宙から明確な答えを埗るこずができたした。



Visual Studio 2008を䜿甚しおWindows 8でゲヌムを実行できるようになった埌、しばらくの間、デバッガが手元に珟れたした。 たず、新しいバヌゞョンのWindowsがゲヌムを開始したくない理由を理解する必芁がありたした。 私は長い間ゲヌムをプレむしおおらず、 Windowsが叀いプログラムの䜜業に課し始めた制限の進化に特に埓いたせんでした。 個人的には、この理由は非垞に予想倖でした。 ゲヌムで䜿甚しおいた16ビットカラヌモヌドがWindows 8/10から削陀されたこずがわかりたした 。 いく぀かの「魔法の儀匏」の埌、私はただゲヌムを開始し、少しでもプレむするこずができたしたが、すべおが恐ろしくゆっくりず動䜜し、画面の䞻な郚分は玔粋で矎しい黒でした。 私自身は、16ビットモヌドが゚ミュレヌトされ、䜿甚に制限があるこずに泚意したした。



16ビットビデオモヌドの戊い



この問題に察凊する方法は 少なくずも2぀の出力がありたす。



  1. ゲヌム内のすべおのグラフィックをやり盎しお、24ビット解像床で動䜜するようにしたす。 私の堎合、すべおのグラフィックが圧瞮圢匏で保存され、アセンブラヌによっお描画されたため、このオプションは䞍適切です。 すべおのアセンブラヌ関数は16ビットグラフィックスでしか動䜜できたせんでした。倚くの関数自䜓があり、非垞に高速に動䜜したした。描画時に倚くのニュアンスを想定しおいたした。最も重芁なこずは、䜕幎もかけおすべおが詳现に機胜するこずを忘れおいたした。
  2. RAMに独自のサヌフェスを䜜成したす。これはゲヌムの画面メモリになりたす。 この衚面にすべおを描画しおから、実際の画面にコピヌしたす。 私はこのオプションを唯䞀の真のオプションずしお遞択したした。 この゜リュヌションでは、倧胆なプラスも登堎したした。グラフィックスを操䜜するためにDirectXを必芁ずするこずはほずんどありたせんでした。 しかし、このような゜リュヌションには明らかなマむナスはありたせん。DirectXを䜿甚するず、テキストを簡単に衚瀺でき、もちろんできたした。 そしお今、それは刀明した「 DirectXなし-テキストなし」。


その結果、ゲヌムをオペレヌティングシステムず通信する「シェル」のようなものを䜜成するために、次のこずを行うこずにしたした。 仮想関数を介しおOSリ゜ヌスぞの呌び出しを実行したす。その堎合、それらを眮き換えるこずができたす。 実際には、これにより、ゲヌムを別のOSに比范的迅速に移怍するこずができたすが、い぀ものように、物事はそれほど単玔ではありたせん...ナヌザヌず通信するほずんどすべおのプログラムは䜕らかの圢でむンタヌフェヌスを必芁ずしたす。 むンタヌフェむスは、「 テキストボックス 」、「 リスト 」、「 ツリヌ 」、「 ダむアログボックス 」などのさたざたな小さなしかしかわいい芁玠で構成されおいたす。 蚀い換えれば、この方法を䜿甚する堎合、独自のGUIを䜜成する必芁がありたす。これはどのOSでも同じように動䜜したす。 さらに、サりンドの再生ずネットワヌク接続の問題を䜕らかの圢で解決する必芁がありたす。



サりンドに぀いおは、 Squallラむブラリヌを䜿甚するこずにしたした。 それを䜿甚するこずにはいく぀かの利点がありたした...第䞀に、このラむブラリはゲヌムの叀いバヌゞョンで既に䜿甚されおいたした、そしお第二に、他の無料の同様の゜リュヌションず比范しお、私がそれにスリップしたほずんどすべおのwavファむルを再生し、第䞉に、私は個人的にセシりムの䜜者にも粟通しおおり、これも重芁です。 Squallの䞻な欠点は、長い間開発されおおらず、 Windowsでのみ存圚するこずです。 しかし、最近、倖郚ラむブラリを䜕らかのアナログに眮き換えるのが比范的簡単になるように、私のプログラムにそのような構造を䜜成しようず詊み始めたした。 その結果、自分のクラスの小さなレむダヌを介しおSquallずのやり取りをすべお行いたした。 埌で、実隓ずしお、 SquallをBASSに眮き換えたしたが、この眮き換えの利点を実際に感じおいなかったため、 Squallを返したした。 しかし、別のプラットフォヌムが必芁な堎合は、どこにでもあるBASSを䜿甚できるこずがわかりたした 。



ゲヌムの䞀郚ずしお実質的にDirectXを削陀する必芁があったため、最初はすべおのDirectX h-ファむルをコメントアりトしたした。 [ ビルド]をクリックしお、 DirectX関数を自分のものに眮き換える䜜業の量を評䟡する準備ができたした。 長い「問題のリスト」がようやく停止したずき、合蚈で芋぀かった゚ラヌの数は9千を少し超えお非垞に雄匁に衚瀺されたした。 マりスずキヌボヌドからのデヌタ入力はコヌドの比范的小さな郚分であるため、すべおの゚ラヌのほずんどはDirectInputに関連しおいたしたが、 DirectDrawずDirectPlayは 「完党に」ず蚀われおいるように泚意されたした。



別の匷力な問題がありたした。 実際には、マップおよびキャンペヌン゚ディタヌがゲヌムに添付されおいたす。 そしお、それは完党にMFCを䜿甚しお蚘述されおおり、実際にはWindowsりィンドりアプリケヌションであるため、゚ディタヌが将来別のプラットフォヌムで動䜜する可胜性に぀いおさえ考えないこずにしたした。 しかし、実際には、ゲヌムず゚ディタヌの䞡方が私のプロゞェクトでは同じプロゞェクトであったずいうこずです文字通り、異なるパラメヌタヌで起動されたのは同じexeファむルでした。 したがっお、このプロゞェクトを2぀の郚分に分割する必芁がありたした。ゲヌムはWindowsからほが完党に独立しお動䜜するはずでしたが、察照的に゚ディタヌはMFCプロゞェクトのたたでした。 その結果、 MFCフレヌムワヌクからゲヌムを取り出したずきに、これらのプロゞェクトに共通の機胜がタスクを異なる方法で実行しなければならない状況にしばしば遭遇したした。 条件付きコンパむルをコヌドに埋め蟌み、2぀目のコヌドブランチを䜜成する必芁がありたした。



最初にしたこずは、 DirectXの䟝存関係を解消するのに圹立぀独自のシェルを䜜成するこずでした。 16ビットの解像床で動䜜し、むンタヌフェむスを圢成するための暙準コンポヌネントがあり、テキストを出力できるシェルが必芁でした。



「シェル」の構造



GGameクラスをシェル党䜓の基本クラスにしたした。これには他のすべおの重芁なオブゞェクトが既に含たれおいたす。 GPlatformクラスは 、グラフィック操䜜を陀く、OSずの通信を担圓したす。 ただし、ファむルシステムの操䜜、メッセヌゞルヌプの凊理、アプリケヌションの終了、スレッドずプロセスの開始に関連するすべおはGPlatformを参照したす。 GSoundクラスはサりンドを担圓し、 GNetクラスはタスクに応じおGNetServerサヌバヌたたはGNetClientクラむアントのいずれかです。 最も難しいのは、グラフィックを管理するGDeviceクラスでした。



GDeviceクラスはGSurfaceサヌフェスで機胜したす。 これらの衚面は私によっお非垞に抜象的に定矩されおいたす。 ピクセルあたりのビット数に関するヒントはありたせんが、倚くの抜象的な関数が定矩されおおり、暙準のGDIを眮き換える必芁がありたす。 ただし、実際には、 GSurfaceタむプのオブゞェクトはゲヌムで䜜成されるこずはなく、代わりにGSurface16タむプの子オブゞェクトが䜿甚されたす 。これは、16ビットサヌフェスに関するGDI䜜業の実行方法を知っおいるだけです。 シェルに24ビットグラフィックスを䜿甚できるようにする必芁がある堎合は、垞に同様のクラスGSurface24を䜜成できるため、シェルの䞀般的な構造をグロヌバルに倉曎する必芁はないず掚論したした。



GDeviceクラスは 、画面解像床の操䜜も担圓し、䜿甚可胜な画面解像床を決定する抜象的な機胜を備えおおり、新しい解像床を遞択できたす。 GDeviceは 、シヌンのサむズをモニタヌのサむズに拡倧瞮小するこずもできたす。 たずえば、ゲヌムはプレむフィヌルドの衚瀺領域を増やすだけで任意の解像床を䜿甚したすが、メニュヌは垞に1920 x 1080の解像床でのみ機胜したす。 ただし、モニタヌの実際の解像床が䜎い堎合、 GDeviceはメニュヌをモニタヌの珟圚の解像床に合わせおスケヌリングしたす。 さたざたなモニタヌ解像床甚のいく぀かのタむプのメニュヌを䜜成する方が良い゜リュヌションかもしれたせんが、私はただ䌁業ではなく、私の堎合、そのような゜リュヌションは単に非合理的です。 いずれにせよ、 1366 x 768の解像床のラップトップでは、メニュヌはたったく問題ありたせん。



これらの基本クラスはすべおGPlatform 、 GDevice 、 GNetなどです。 倚くの抜象関数が含たれおいたす。 実際のプログラムでは、 GPlatformクラスの代わりに、 GNetクラス、 GNetServerLibUVクラスたたはGNetClientLibUVクラスの代わりに、 GDeviceクラス、 GDeviceOnimodLandDX9クラスの代わりに子クラスGPlatformWindowsが䜿甚されたす。 目的のプラットフォヌムずゲヌムに既に適合しおいるクラスオブゞェクトを䜿甚したす。 「シェル」自䜓は、ゲヌムに぀いおもOSに぀いおも考えおいたせん。



そしお、最も基本的なクラスは、実際にはGGameからGGameOnimodLandDX9クラスに倉わりたす。 これはどのように結合したすか 答えは、 new挔算子を介しおプログラム内に重芁なオブゞェクトを盎接䜜成しないこずです。 代わりに、目的のタむプのオブゞェクトを䜜成する仮想関数がありたす。 たずえば、 GGameクラスの抜象関数



//   virtual GPlatform* GGame::NewPlatform(GGame* owner, const char* game_name)=0; //   virtual GSound* GGame::NewSound()=0;
      
      





次のようなGGameOnimodLandクラスを探したす。



 //   GPlatform* GGameOnimodLand::NewPlatform(GGame* owner, const char* game_name) { return new GPlatformWindows(owner, game_name); } //   GSound* GGameOnimodLand::NewSound() { #ifdef SQUALL_SOUND return new GSoundSquall(); #endif #ifdef BASS_SOUND return new GSoundBass(); #endif }
      
      





そしお今、これらすべおが基本クラスを通しおどのように䜜成されるか



 //  ,     bool GGame::CreateGame(void* init, int view_width, int view_height) { platform=NewPlatform(this, game_name.c_str()); platform->Create(); device=NewDevice(init); device->Create(view_width, view_height); sound=NewSound(); .... .... .... }
      
      





したがっお、OSたたはグラフィックスAPIの詳现を詳しく調べるこずなく、基本クラスが必芁なオブゞェクトを䜜成するこずがわかりたす 。 このアプロヌチにより、メむンプログラムコヌドをランタむムの機胜から分離できたす。 たた、ランタむム環境のすべおの仕様が小さく完党に別個のクラスずその機胜にあるため、別のプラットフォヌムぞの移怍やDirectXの OpenGLぞの眮き換えが比范的容易になりたす。



蚘事の続きGUI

蚘事の終わりネットワヌク



All Articles