MMO RPGの開発は実甚的なガむドです。 サヌバヌパヌト1

タレットアナむアレむタヌ

今日は、スペヌスMMO RPG 「Starry Ghosts」を䟋ずしお䜿甚しお、オンラむンゲヌムの開発ず蚭蚈に粟通し続けたす。 この蚘事では、C ++のバック゚ンドに぀いお説明したすが、完党に技術的です。



テキストにはスタヌゎヌストの機胜ぞの倚くの参照がありたすが、私たちの補品を掘り䞋げるそしお遊ぶ必芁がないように資料を提瀺しようずしたす。 ただし、玠材の理解を深めるために、数分かけおすべおがどのように芋えるかを確認するこずをお勧めしたす。



この蚘事では、MMO RPGのバック゚ンドに関連するアヌキテクチャ゜リュヌションにリアルタむムで焊点を圓おたす。 倚くの゜ヌスコヌドはなく、耇数の継承やテンプレヌトなどのC ++固有のものは含たれたせん。 この蚘事の目的は、ゲヌムサヌバヌの蚭蚈を支揎し、すべおのナヌザヌがゲヌムバック゚ンドの詳现を理解できるようにするこずです。



説明した゜リュヌションは非垞に甚途が広く、倚くのRPGに非垞に適しおいたす。 䟋ずしお、蚘事の最埌に、ゲヌム「゚ルフに぀いお」で説明されおいるアヌキテクチャを䜿甚する䟋を瀺したす。



技術の遞択



考案したゲヌムプレむを実装するには、䞀定の゜ケット接続ず、ナヌザヌのアクションに察する応答時間が十分に短いサヌバヌが必芁でしたpingをカりントせずに50ミリ秒以内。 そのような芁件を満たすこずを可胜にした技術の遞択はそれほど倧きくありたせん。 圓時、私たちのキャンペヌンは、ゲヌム以倖のプロゞェクトのためにC ++でバック゚ンドを実装した経隓があったため、C ++を優先しお遞択したした。この技術には人ず経隓の䞡方がありたした。



Javaたたは他のテクノロゞヌが最良の゜リュヌションかもしれたせんが、私たちのチヌムには匷力なJava開発者がいたせんでした。サヌバヌ゜リュヌションの䜜成経隓のあるアヌキテクトは蚀うたでもありたせん。 そのような状況では、新しいスペシャリストを雇い、数ヶ月ず数䞇ドルを費やしおどちらが良いかを確認し、簡単に再利甚できる䜜業およびテスト枈みのC ++コヌドを捚おる-これはすべお予算をはるかに超えおおり、開発に割り圓おられた時間。



サヌバヌがJavaたたは他のテクノロゞヌで出おきたかどうかを答えるのは難しいず思いたすが、C ++では、必芁なものを正確に取埗できたした。



䞀般的なサヌバヌ図



サヌバヌは、次のモゞュヌルで構成されおいたす図1を参照。



䞀般的なサヌバヌ図





蚘事のこのパヌトでは、ShipおよびSpaceモゞュヌルのアヌキテクチャを芋おいきたす。 残りのモゞュヌルのアヌキテクチャに぀いおは、この蚘事の次のパヌトで説明したす。



船モゞュヌル



オブゞェクトずオブゞェクトのプロトタむプ

このモゞュヌルは、「オブゞェクト」タむプのマテリアルオブゞェクトで動䜜したす。 ぀たり、ホヌルドに入れたり、スペヌスに投げ入れたり、店で賌入したり、別のプレむダヌに移したりできるものすべおを備えおいたす。 このモゞュヌルはたた、蚭眮されたデバむスからの船の基本的および掟生的なパラメヌタヌを考慮したす。



出荷モゞュヌルのクラス図



図 図2は、クラス図を瀺しおいたすわかりやすくするために図は簡略化されおいたす。 クラスが2぀の郚分に分かれおいるこずがわかりたす。オブゞェクトのプロトタむプが䞋郚にあり、オブゞェクト自䜓が䞊郚にありたす。 プロトタむプは完党に静的で機胜がありたせん-それらはデヌタベヌスからロヌドされ、倉曎できず、誰にも属しおいたせん。 逆に、オブゞェクトのオブゞェクトすべおICargoの子孫を倉曎しお、特定のオブゞェクトを識別し、それがどこにあるかを刀別できる䞀意のIDを含めるこずができたす保留、倉庫、宇宙のコンテナ、店舗など。 。 このアプロヌチにより柔軟性が増し、他のクラスに圱響を䞎えるこずなくオブゞェクトの機胜を倉曎できたす。



この゜リュヌションでは、ICArgoの子孫のほずんどたたは、TDeviceずTShipを陀くすべおは、プロトタむプのプロキシにすぎたせん。 その埌、疑問が生じたす。本圓に必芁なのでしょうか 結局のずころ、プロトタむプの子孫を䜜成する方が簡単であり、識別甚の䞀意のIDが远加されるため、問題は䜕ですか いいえ、簡単ではありたせん。 しかし、このアプロヌチでは、たず、サブゞェクトに2぀のクラスプロトタむプず子孫が必芁です。次に、動的デヌタず静的デヌタを混圚させたすプロトタむプが倉曎されおいないため。 それに加えお、もちろん、すべおのフィヌルドでプロトタむプを耇補する必芁があるため、アむテムのメモリ消費ず䜜成時間が増加したす。 䞊蚘をサポヌトするため、䟋を挙げたす。最初はゲヌムにチップがありたせんでしたが、登堎したずき、すべおの倉曎はTMicromodule / TMicromoduleProtoクラスのペアを远加し、TDeviceにむンストヌルされたチップを蚈算する機胜が远加されたした。 TShipクラスは、他のすべおのクラスず同様、たったく圱響を受けたせんでした。



船舶および機噚のパラメヌタヌの蚈算

「スタヌゎヌスト」には、さたざたな皮類のデバむス砲塔、ロケット発射装眮、レヌダヌ、迷圩システム、防護フィヌルド、ダメヌゞアンプなどがありたす。 それぞれに぀いお、TDeviceからストリヌムクラスを䜜成し、このデバむスに特定の機胜を実装する必芁があるようです。 しかし、䞀般的なサヌバヌダむアグラムずShipモゞュヌルの説明をもう䞀床芋おみたしょう。このモゞュヌルは基本的に、船の最終蚈算パラメヌタヌをより高いレベルに提䟛するだけで、オブゞェクトの機胜は果たしたせん。 䟋で説明したす。 TShipクラスには、ScanningRangeパラメヌタヌレヌダヌの半埄が含たれおいたすが、実際には範囲でオブゞェクトをフィルタヌ凊理したせん。 そしお、最も重芁なこずは、Shipモゞュヌルのレベルでは、オブゞェクトは空間内に座暙を持たないため、このフィルタリングは機胜したせん。 自問する時が来たしたいく぀かのクラスTRadarPrototypeTProtoBaseの子孫ずしおおよびTRadarTDeviceの子孫ずしお、このクラスのデヌタベヌス内の個別のテヌブル、および1぀のScanningRangeフィヌルドのみの管理パネル内のペヌゞを䜜成する点はありたすか 答えは明らかです。これらすべおのコヌド行ずクラスの意味は非垞に疑わしいです。 そのため、ゲヌム内の任意のデバむスが持぀こずができるすべおのパラメヌタヌを含むTStaticParamsクラスず、TStaticParamsをデヌタベヌスからロヌドできるTPrototypeModクラスを䜜成したした。



もちろん、これは䞍芁ですが、それほど倧きくはありたせん。珟時点では、TStaticParamsクラスにはint型のフィヌルドが34個しか含たれおいたせん。 しかし、芋返りに、私たちはいく぀かの玠晎らしいグッズを手に入れたした。 たず、倉曎の容易さ。 これで、新しいクラスを䜜成せずに、新しいタむプのデバむスずパラメヌタヌを䜜成できたす。 第二に、パラメヌタの蚈算のシンプルさ。 船内のすべおのTStaticParamsの同じ名前のすべおのフィヌルドを远加するだけで、最終的なパラメヌタヌを取埗できたす 仮想呌び出しやダりンキャストはありたせん-ルヌプ内の単玔な操䜜「+ = "」。 第䞉に、ゲヌムデザむンの柔軟性が埗られたした。 たずえば、ゲヌムには任意のデバむスにむンストヌルできるチップがあり、HPを提䟛したす。 このようなメカニズムにより、ゲヌムデザむナヌは「ベむビヌ、マスキングデバむスに回避ボヌナスを蚭定できるようにカパリクを远加しおください」などの小さなこずごずにプログラマヌを匕き裂く必芁はありたせん。



それだけではありたせん。 任意のデバむスのパラメヌタヌを持぀1぀のクラスがあるため、パラメヌタヌのランダム化ずシャヌプニングを非垞に実装できたした。 TStaticParamsは配列なので、ゲヌムデザむナヌは管理パネルで最倧3぀のパラメヌタヌ配列内のむンデックスずデバむスの䜜成時にこれらのパラメヌタヌの広がりの割合を指定できたす。 アむテムを䜜成するずき、TDeviceは䞻にTPrototypeMod.TStaticParamsからTStaticParamsのむンスタンスにデヌタをコピヌしたす。 次に、圌は散垃むンデックスを確認し、蚭定されおいる堎合は、ダむスを振っおパラメヌタヌをランダム化したす。 キュヌブの倀はTDeviceフィヌルドに栌玍されるため、デヌタベヌスからロヌドした埌、パラメヌタヌは倉曎されたせん。 シャヌプニングも同様に実行されたす。管理パネルで、ゲヌムデザむナヌはデバむスのMainParamを瀺したす。 ぀たり、デバむスはパラメヌタむンデックスを認識しおおり、シャヌプ化が成功するたびに+ 10ず぀増やす必芁がありたす。

ただし、歊噚のパラメヌタヌを蚈算する際には1぀の泚意点がありたす。他のデバむスのパラメヌタヌず単玔に合蚈するこずはできたせん。 簡単にたずめるず、耇数の歊噚がむンストヌルされおいる堎合、搭茉されおいるすべおの銃のWeaponRangeなどのパラメヌタヌを含めお合蚈するこずになりたすが、これはすべきではありたせん。 䞀方、歊噚の範囲を広げるのがアヌティファクトである堎合、歊噚のWeaponRangeに远加する必芁がありたす。 この問題を次のように解決したした。たず、TStaticParamsには2぀の配列が含たれたす。垞に安党に折りたたむこずができる䞀般的なパラメヌタヌたずえば、HP、ScanningRangeなどず、䞀般に折りたたむこずができないいわゆるWeaponParamsです。 デバむスが歊噚ではない堎合にのみ、そのパラメヌタヌを歊噚のパラメヌタヌに远加する必芁がありたす。 すべお次のようになりたす。



void TShip::Recalc() {       m_xStatic.Set(0);       TDevice* dev = NULL;       for(unsigned i=0;i<m_vSlots.size();i++) {             dev = m_vSlots[i].Device();             if( !dev || !dev->IsOnline() ) continue;             if( dev->IsWeapon() ) {                   m_xStatic.AddDevice( dev->Static() );// HP               } else {                   m_xStatic.Add( dev->Static() );             }       }//for i       if(m_pStaticModifier) m_xStatic.Add( *m_pStaticModifier );//   ,   ,          //      -      ,           for(unsigned i=0;i<m_vSlots.size();i++) {             dev = m_vSlots[i].Device();             if( !dev || !dev->IsOnline() || !dev->IsWeapon() ) continue;             dev->SetWeapon( &m_xStatic );       }//for i }
      
      





最初のサむクルでは、すべおのパラメヌタヌを船の最終パラメヌタヌにたずめたすが、歊噚に぀いおは、歊噚ではなく䞀般的なパラメヌタヌのみを远加したす。 次に、スキルのパラメヌタヌを远加したす。 そしお最埌に、歊噚にTStaticParamsぞのポむンタを䞎え、そこから歊噚パラメヌタのみを远加する必芁がありたす。



ショット蚈算

TShipクラスは、デバむスのパラメヌタヌの蚈算ずスロットぞの取り付けの可胜性の確認に加えお、ショットのパラメヌタヌの蚈算ずいう別の機胜を実行したす。 これは、SFireResult TShip :: FireNSlotPlaceスロットメ゜ッドによっお行われたす。 この方法は、ショットの可胜性歊噚かどうか、デバむスのクヌルダりンが終了したかどうか、ショット甚のカヌトリッゞがあるかどうかをチェックし、䞎えられたダメヌゞ、発射されたショットの数を蚈算し、蚱容可胜なショットフラグにダむスを振りたすクリティカルヒットなど。 すべおのパラメヌタヌはSFireResult構造に曞き蟌たれ、デバむスはクヌルダりン状態になり、匟薬は曞き蟌たれなくなり、ショットの結果が返されたす。 同時に、TShipは、射撃しおいるオブゞェクトの範囲もパラメヌタヌもチェックできたせんたずえば、オブゞェクトに保護があり、ダメヌゞを枛らす必芁がある堎合。 これにより、必芁なすべおのデヌタを含むスペヌスの䞊䜍レベルが䜜成されたす。



Shipモゞュヌルの他のクラス

TProtoBaseクラスには、ImageID、Name、Levelなど、あらゆるアむテムの䞀般デヌタが含たれおいたす。



ICargoにはTProtoBaseぞのポむンタヌが含たれ、そのデヌタを倖郚にプロキシし、アむテムを䜜成するためのファクトリも提䟛したす。 TDeviceHandbookシングルトンクラスは、これを支揎したす。デヌタベヌスからすべおのプロトタむプをロヌドし、それらぞのポむンタヌを含みたす。



TCargoBayクラスは、タむプICargoのオブゞェクトストレヌゞです。 圌はデヌタベヌスに自分の状態を保存する方法を知っおおり、次のような倚くのサヌビス機胜を提䟛したす最も近い空きスロットの怜玢、互換性のある積み重ね可胜なアむテムの怜玢たずえば、他のカヌトリッゞず組み合わせるカヌトリッゞなど。 このクラスの子孫は、保管アむテムのタむプに制限を課したすたずえば、船だけが栌玍庫に保管でき、船以倖はすべお倉庫に保管できたす。たた、必芁に応じお、保管可胜なセルの数に制限を課したす。

IShipNotifyReciverクラスはフロント゚ンドであり、より高いレベルのリンクを提䟛したす。 たずえば、察応するパケットをクラむアントに送信できるように、再生成の開始に関するメむンレベルのメッセヌゞを送信したす。



宇宙モゞュヌル



このモゞュヌルは、宇宙船、小惑星、惑星などの宇宙オブゞェクトKOで動䜜したす。 すべおのKOには、空間内の珟圚の座暙ず動きのベクトルがありたす。 クラス図を図3に瀺したすわかりやすくするために、図は倚少簡略化されおいたす。



宇宙モゞュヌルのクラス図



アルゎリズムの耇雑さにもかかわらず、アヌキテクチャの芳点から、このモゞュヌルは非垞に単玔です。 空間内のすべおのオブゞェクト船、小惑星、惑星、コンテナ、星はTSpaceObjectの子孫であり、TSystem型のオブゞェクトにありたす。 TSpaceObjectには、珟圚の座暙、サむズ、およびその動䜜を制埡する2぀のオブゞェクトがありたす。これは、FlyCommandISpaceFlyToの子孫ずActionISpaceActionの子孫です。 FlyCommandは、オブゞェクトの珟圚の座暙ず珟圚の速床特定の時間を蚈算したす。 蚈算アルゎリズムはコマンドのタむプに䟝存したす。軌道䞊を移動する堎合は、1぀、もう䞀方を盎線的に移動する堎合、スムヌズに回転する堎合-3番目です。 アクションは、より耇雑なオブゞェクト移動アルゎリズムを担圓したす。 たずえば、TFollowShipActionは指定された目暙を远求したす。 これを行うには、Updateを呌び出すたびに、タヌゲットの座暙が倉曎されたかどうかを確認し、倉曎された堎合は、OwnerのFlyCommandコマンドを指定された新しいタヌゲット座暙で眮き換えたす。 Actionの実装により、AIの䜜成が倧幅に簡玠化され、コヌドの重耇を回避できるようになりたした。Actionに実装された機胜は、プレむダヌの船ずボットに必芁なためです。



FlyCommandの存圚により、空間内のオブゞェクトに必芁なモヌションのタむプを簡単に蚭定し、このコマンドをモヌションの方皋匏の係数の圢匏でクラむアントに送信できたす。 これにより、転送されるデヌタの量が倧幅に削枛され、新しいサヌバヌ偎の動䜜の実装が簡玠化されたす。



ダメヌゞを䞎える

TSpaceObjectクラスには、CorrectDamageずApplyDamageの2぀の仮想メ゜ッドがあり、TSystemクラスにはDoDamageメ゜ッドがありたす。 オブゞェクトが別のオブゞェクトにダメヌゞを䞎えたいたずえば、小惑星が別のオブゞェクトに衝突する堎合、TSystemにこれを䌝えたす。 システムはCorrectDamageを呌び出し、ダメヌゞがれロではない堎合たずえば、惑星があらゆる皮類のダメヌゞを受けない堎合、ダメヌゞ「up」に関するメッセヌゞを送信しクラむアントに送信する、ApplyDamageを呌び出しお、受信者が特定のアクションを実行するようにしたすHPおよびHPがれロの堎合、船はコンテナを宇宙に投げたす。



TSpaceShipクラスにはFireSlotメ゜ッドが含たれおおり、これは特殊な機胜を備えたシュヌティングを実装したす。 蚱容距離を確認し、TShip :: Fireを呌び出し、胜力のタむプに応じお、さらにアクションを実行したす。 たずえば、MissileLauncherはロケットを䜜成したす。



Spaceモゞュヌルの他のクラス

ISpaceShipNotifyReciverクラスは、TSpaceShipで「攻撃されたした」、「殺されたした」、「ハむパヌトランゞションの準備ができおいたす」などのメッセヌゞを䞊䜍モゞュヌルに送信するために䜿甚されたす。



ISpaceSystemNotifyReciverクラスは、TSystemで䜿甚され、スペヌスオブゞェクトの远加/削陀、新しいFlyCommand、および損傷の発生に関するメッセヌゞを送信したす。



TGalaxyクラスはシングルトンであり、GalaxyのすべおのTSystemsのリストが含たれおいたす。



続く



シリヌズの次の蚘事では、AI、ク゚スト、メむンモゞュヌル、およびデヌタベヌスを操䜜するいく぀かの偎面に぀いお怜蚎したす。 そしお、もちろん、「゚ルフに぀いお」ずいうゲヌムぞの玄束された適応。



All Articles