クロスプラットフォームカジュアルエンジンの作成に関する事後分析

当番では、カジュアルゲーム(ほとんどの場合、クエスト)のためにクロスプラットフォームエンジンを実装する必要がありました。 この記事では、開発中に決定した重要な問題について説明します。



はじめに



エンジンは、PC、MacOS X、iOSの少なくとも3つのプラットフォームをサポートする必要があります。 クエストの作成に使用されるため、パーティクルシステム、アニメーション、ビデオなどの視覚的な美しさに重点が置かれます。



エンジンは、次のエンティティに基づいています。

-メインエンジンクラス。ウィンドウの作成、ユーザー入力、フォーカスの獲得/喪失、エンジンの他のすべての部分の制御を担当します。

-レンダリングクラス;

-リソースマネージャー-リソース(テクスチャ、フォント)のロード、保存、アンロード。



これら3つの大きなエンティティ自体は完全に自給自足であり、他のエンジンに外部依存関係がないため、iOS用のアーケードを作成したときに、それらを取得してアクションラッパーをラップしました。



ベースの上に、ゲーム(クエスト)パーツが直接作成されました。 作成の主なアイデアは、ゲームエンティティの制御、作成、読み込みの均一性でした。

これは序論でしたが、今ではすべてについてさらに詳しく説明しています。



クロスプラットフォーム実装



それが私たちの主な関心事でした。 1年に10ゲームを作成し、このすべての不名誉の10言語に多くのローカライズを費やすので、各ゲームの個別の移植を追加する余裕はありませんでした。 なぜ分離するのですか? 私たちの会社は3つの都市に分散した5つのワーキンググループに分かれており、各グループには独自の自転車を選ぶ独自のプログラマーがいました。 作業を最適化するために、一般的なエンジンとツールのアイデアのために人々の道徳的な準備のために現在のゲームをすべて利用可能な最高のエンジンに一時的に移し、1人のプログラマーが解雇され、残りは現在のプロジェクト間で割り当てられ、新しい共通エンジンで作業する時間を割り当てました。



移植を簡素化するために、できるだけ少ないクラスですべてのプラットフォーム固有のコードをローカライズし、すべてのプラットフォームに共通のコードを使用して主な作業を実行しようとしました。 その結果、テクスチャ、レンダリングクラス、ウィンドウマネージャー、ファイルシステムアクセス、サウンドなどのプラットフォーム依存のクラスになりました。 残りのコードが使用されているプラ​​ットフォームを知らないようにするために、低レベルのオブジェクトの作成をファクトリに行い、制御ディレクティブに応じて目的のオブジェクトを作成しました。 低レベルのオブジェクトを直接(新規)作成することは禁止されていました。



PCとMacOS Xの実装はPlaygroundライブラリを使用して行われました。これは、このライブラリを長い間使用しており、非常に多くのユーザーが使用できるゲームを確実に入手できるためです。 iOSの場合、OpenGL ESにすべてを実装しました。 テクスチャへのレンダリングとテクスチャ内の任意のピクセルへのアクセスを除いて、そこに問題はありませんでした。



ゲームエンティティの構造化



私はすでにこの1つの投稿についてサンドボックスで書いていますが、どうやらそうではなかったようです。



アイデアは、すべてのゲームエンティティが共通のシステムにあり、1つの共通のインターフェイスを持っているということです。 どのゲームも、エンジンとゲーム自体に分けることができます。 そのため、ゲーム自体とその中のエンティティは、エンジンで定義され、プロセス、入力、レンダリング、ロード、アンロード、子の管理などのすべての基本操作を実装するオブジェクトの1つの共通クラスから継承されます。 各オブジェクトには、レベル設計者が生成または設定する一意の名前があります。 共通のインターフェイスを1つ持っているので、プログラマはどこでもコードを修正できます。すべてがどこでも同じだからです。 すでに3つのゲームを完了した後、ゲームコードを分析し、ベースオブジェクトに実装されていないゲームオブジェクトの一意のメソッドの数がクラスごとに1つまたは2つ以下であることに気付きました。 クラスやメソッドのこの動物園と一緒に住んでいたことを想像することはできません。



このアイデアの第2の側面は、ツリー構造を作成することでした。 各オブジェクトは誰かに属し、誰かがそれを作成し、誰かがそれを削除します。 すべてのオブジェクトは互いに接続されています。 この階層の最上部には、「ルート」と「ボールト」の2つのオブジェクトがあります。 ルートに接続されているすべてのものが描画され、処理され、入力が処理されます。 ルートに固執するものはすべて自動的にリソースをロードします。 それから切り離されたものはリソースをアンロードします。 「リポジトリ」は、まだ必要ではないものを内部に保存するだけですが、便利になる可能性があり、ダウンロードする時間がありません。 また、「リポジトリ」には保存されたアイテムがあり、そのステータスを記憶し、後でまったく同じ形式でユーザーに表示する必要があります。 つまり、これら2つのスーパーオブジェクト間でオブジェクトをドラッグすることにより、画面に表示されるものを制御します。 再帰的な検索手順により、オブジェクトへのアクセスは一意の名前で実行されます。



オブジェクトを作成してどこにでもアタッチすることはできませんが、最初に、このオブジェクトは描画またはアニメーション化されないため、作成者がすぐに気付きます。次に、検索手順を使用して見つけることができません。 、これもすぐに気付き、削除されます。



ゲームエディター



C#でエディターを作成しています。 便利で高速であり、レベルの設計者は標準のWindowsインターフェイスとホットキーに満足しています。 そして、ゲームをC ++で作成します。 そして、ここで問題が発生し始めます...



レベルデザイナーの夢は、ゲームと組み合わせたエディターです。つまり、ゲームをプレイする-バグを見つける-エディターモードに切り替える-バグを修正する-ゲームモードに切り替える-さらにプレイする つまり、エディターの要件は次のとおりでした。一方では、ゲームは同時にエディターである必要があり、他方では、エディターには標準のウィンドウ、コントロール、および管理原則が必要です。



最初は、OpenGLとDirectXのさまざまなコントロールライブラリについて考えましたが、設計者は、ユーザーフレンドリなどではなく、自分の好きではないものをいじくり回し始めました。 私たちは彼らに会いに行きました-彼らはまだプログラマーの5倍です。



それから、多くの変革を経て、私たちが今持っているものになるという考えが生まれました。 詳細に煩わされないように、すぐに最終バージョンをお知らせします。



要するに、ゲームには実際にエディターが含まれています。つまり、制御コード全体がゲーム内、より正確にはエンジン内にあり、エディターはこのコードを制御できる美しい制御シェルにすぎません。 ゲームとエディターの開始時に、彼らはお互いに初期データを交換し、エディターのボタンを押すことでいつでもゲームが編集モードに入り、デザイナーにすべての機能を提供します。 エディタウィンドウには、ロードされたモジュールおよびその他のサービス情報が表示されます。 同時に、エディターはそれ自体に何も保存せず、コマンドの送信と回答の受信のみを行います。 これは、エディターとゲーム内の情報の重複、および両方の場所でデータを更新する大規模なhemoを避けるために行われました。 このソリューションには、関連するデータを取得するためにいくつかの場所で数回クリックするという欠点がありますが、現時点では許容することにしました。

ゲームとエディターの間でWM_COPYDATAメッセージを使用してデータが交換され、アプリケーション間でデータを送信できます。 データはXMLでパッケージ化されます。 これは、将来の変更を簡素化するために行われます。



おわりに



これらは、シンプルでポータブルなゲームエンジンの実装を可能にした主なポイントでした。 別の記事で発行されるより多くの詳細がありました。



All Articles