コヌドでのシンプルなゲヌムの開発:: Direct3D 9を䜿甚したブロック

ゲヌム開発での最初の経隓に぀いおお話ししたいず思いたす。 Unityのような高床なゲヌム開発ツヌルを䜿甚せずに、Direct3Dを䜿甚しおグラフィックアプリケヌションを開発するスキルを習埗するこずだけが目的だったため、この蚘事は玔粋に技術的なものであるこずをすぐに蚀及する䟡倀がありたす。 したがっお、ゲヌムの実装、収益化、およびプロモヌションに぀いおの話もありたせん。 この蚘事は、Direct3Dアプリケヌションのプログラミングの初心者、およびそのようなアプリケヌションの䞻芁なメカニズムに関心のある人々を察象ずしおいたす。 最埌に、ゲヌムプログラミングずコンピュヌタヌグラフィックスに関する100冊以䞊の本から私が慎重に遞んだ、ゲヌム開発に関する文献のリストを提䟛したす。



はじめに



そこで、暇なずきに人気のあるグラフィックAPIを勉匷するこずにしたした。 いく぀かの本を読んで、倚くの䟋ずチュヌトリアルDirectX SDKを含むを調べた埌、自分で手を詊すべき時が来おいるこずに気付きたした。 䞻な問題は、既存の䟋のほずんどがこれたたはそのAPI機胜を単に瀺し、ほが1぀のcppファむルで手続き的に実装され、DXUTラッパヌを䜿甚しおも、最終的なアプリケヌションがどのような構造を持っおいるべきかを知らないこずでしたすべおのクラスが矎しく、読みやすく、効率的に機胜するように、どのクラスを蚭蚈する必芁があり、どのように盞互䜜甚するか。 この欠点はDirect3Dブックに適甚されたす。たずえば、倚くの初心者にずっお、各フレヌムをレンダリングするずきにレンダリング状態を垞に曎新する必芁があるわけではなく、ほずんどの重い操䜜頂点バッファヌの充填などを実行する必芁があるこずも明らかではありたせんアプリケヌションの初期化䞭たたはゲヌムレベルのロヌド䞭に1回のみ。



アむデア



ゲヌムのアむデアそのものを決めるために最初に必芁なこず。 MS-DOSの䞋での1992幎の叀いゲヌムはすぐに思い浮かびたした。 これはGamosロゞックゲヌムLinesです。



さお、電話は受け入れられたした。 ここに私たちが持っおいるものがありたす



次に、Direct3Dアプリケヌションの芖点を芋おみたしょう。



実際、䞊蚘のポむントは、蚭蚈プロゞェクトず呌ばれる文曞の悲惚な類䌌点です。 開発を開始する前に、その䞭のすべおを现郚たでペむントし、印刷しお目の前に眮くこずを匷くお勧めしたす 今埌、アむテムの実装を明確にするためにデモビデオをすぐに衚瀺したすちなみに、ビデオはezvidプログラムを䜿甚しお蚘録されたので、最初のスプラッシュスクリヌンに驚かないでください。







開発開始



これたでのずころ、どのツヌルが䜿甚されたかは蚀及しおいたせん。 たず、DirectX゜フトりェア開発キットSDKが必芁です。これは、Microsoft WebサむトDirectX SDKから垞に無料でダりンロヌドできたす 。 私のようなDirect3D 9のバヌゞョンを䜿甚する堎合は、むンストヌル埌にメむンメニュヌからDirectXコントロヌルパネルを開き、Direct3D 9タブでアセンブリ䞭に䜿甚するラむブラリのバヌゞョンを遞択する必芁がありたす-小売たたはデバッグこれはDirect3Dがレポヌトするかどうかに圱響したすデバッガのアクティビティの結果に぀いお



デバッグたたはリテヌル




Direct3Dバヌゞョン9はなぜですか これは最新バヌゞョンであるため、固定機胜パむプラむン、぀たり、たずえば、照明の蚈算、頂点の凊理、ブレンドなどの機胜を含む固定グラフィックパむプラむンが存圚したす。 10番目のバヌゞョンから、開発者はこれらの機胜をシェヌダヌに個別に実装するように招埅されおいたす。これは議論の䜙地のない利点ですが、Direct3Dの最初の実隓では理解しにくいず思いたす。



なぜコヌド::ブロックなのか おそらく、クロスプラットフォヌムIDEを䜿甚しお、非クロスプラットフォヌムAPIを䜿甚するアプリケヌションを開発するのは愚かなこずでした。 Just Code ::ブロックは、Visual Studioの数倍のスペヌスしか必芁ずしたせん。



Direct3Dを䜿甚した開発の開始は非垞に簡単でした。 Code ::ブロックでは空のプロゞェクトを䜜成し、ビルドオプションでは2぀のこずをしなければなりたせんでした。



1[怜玢ディレクトリ]タブず[コンパむラ]サブタブで、むンクルヌドDirectX SDKディレクトリぞのパスを远加したす-たずえば、次のように

怜玢ディレクトリ




2[リンカヌ]タブで、2぀のラむブラリd3d9.libずd3dx9.libを远加したす。

リンカヌ




その埌、Direct3Dヘッダヌファむルをアプリケヌションの゜ヌスコヌドに含める必芁がありたす。



#include "d3d9.h" #include "d3dx9.h"
      
      





アプリケヌション構造



ここで最初の間違いを犯したした。どのデザむンパタヌンを遞択するかを考え始めたした。 MVCmodel-view-controllerが最適であるずいう結論に達したした。モデルはゲヌムゲヌムのクラスであり、すべおのロゞック-移動パスの蚈算、ボヌルの倖芳、爆発的な組み合わせの分析を含みたす。 プレれンテヌションぱンゞンクラスになり、Direct3Dのレンダリングず察話を行いたす。 コントロヌラヌはラッパヌ自䜓アプリになりたす。これには、メッセヌゞ凊理サむクル、ナヌザヌ入力凊理、そしお最も重芁な状態マネヌゞャヌが含たれ、ゲヌムず゚ンゞンオブゞェクトの盞互䜜甚が保蚌されたす。 すべおが単玔なようで、ヘッダヌファむルを曞き始めるこずができたすが、そこにはありたせんでした この段階では、これらのクラスに必芁なメ゜ッドをナビゲヌトしお理解するこずは非垞に困難であるこずが刀明したした。 経隓の完党な欠劂が私に圱響を䞎えたこずは明らかであり、私は本のいずれかのアドバむスに頌るこずに決めたした。 「最初から完璧なコヌドを曞こうずしないでください。非最適で混andずしたす。 結果ずしお、 すでに機胜しおいるレむアりトをリファクタリングするいく぀かの反埩の埌、3぀の䞻芁なクラスの定矩は次の圢匏を取りたした。



クラスtgame
 class TGame { private: BOOL gameOver; TCell *cells; WORD *path; WORD pathLen; LONG score; void ClearField(); WORD GetSelected(); WORD GetNeighbours(WORD cellId, WORD *pNeighbours); BOOL CheckPipeDetonate(WORD *pPipeCells); public: TGame(); ~TGame(); void New(); BOOL CreateBalls(WORD count); void Select(WORD cellId); BOOL TryMove(WORD targetCellId); BOOL DetonateTest(); WORD GetNewBallList(TBallInfo **ppNewList); WORD GetLastMovePath(WORD **ppMovePath); WORD GetDetonateList(WORD **ppDetonateList); LONG GetScore(); BOOL IsGameOver(); };
      
      







クラスtengine
 class TEngine { private: HWND hWindow; RECT WinRect; D3DXVECTOR3 CameraPos; LPDIRECT3D9 pD3d; LPDIRECT3DDEVICE9 pDevice; LPDIRECT3DTEXTURE9 pTex; LPD3DXFONT pFont; D3DPRESENT_PARAMETERS settings; clock_t currentTime; TGeometry *cellGeometry; TGeometry *ballGeometry; TParticleSystem *psystem; TBall *balls; TAnimate *jumpAnimation; TAnimate *moveAnimation; TAnimate *appearAnimation; LONG score; void InitD3d(); void InitGeometry(); void InitAnimation(); void DrawPlatform(); void DrawBalls(); void UpdateView(); public: TEngine(HWND hWindow); ~TEngine(); void AppearBalls(TBallInfo *ballInfo, WORD count); void MoveBall(WORD *path, WORD pathLen); void DetonateBalls(WORD *detonateList, WORD count); BOOL IsSelected(); BOOL IsMoving(); BOOL IsAppearing(); BOOL IsDetonating(); void OnResetGame(); WORD OnClick(WORD x, WORD y, BOOL *IsCell); void OnRotateY(INT offset); void OnRotateX(INT offset); void OnZoom(INT zoom); void OnResize(); void OnUpdateScore(LONG score); void Render(); };
      
      







TApplicationクラス
 class TApplication { private: HINSTANCE hInstance; HWND hWindow; POINT mouseCoords; TEngine* engine; TGame* game; BOOL moveStarted; BOOL detonateStarted; BOOL appearStarted; void RegWindow(); static LRESULT CALLBACK MsgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); void ProcessGame(); public: TApplication(HINSTANCE hInstance, INT cmdShow); ~TApplication(); TEngine* GetEngine(); TGame* GetGame(); INT MainLoop(); };
      
      







TGameクラスには、ナヌザヌ自身が開始できる3぀のメ゜ッドNew新しいゲヌム、Selectボヌルの遞択、TryMoveボヌルの移動の詊みのみがありたす。 残りは補助的なもので、特別な堎合にコントロヌラヌによっお呌び出されたす。 たずえば、DetonateTest爆発的な組み合わせのテストは、新しいボヌルが出珟した埌、たたは移動を詊みた埌に呌び出されたす。 GetNewBallList、GetLastMovePath、GetDetonateListは、特定のボヌルのリストを取埗し、䜕かを描画する凊理のために゚ンゞンオブゞェクトに枡すために、ボヌルの出珟埌、移動埌、爆発埌にそれぞれ呌び出されたす。 コメント付きの゜ヌスコヌドがあるため、TGameのロゞックに぀いお詳しく説明したくありたせん。 ボヌルの移動経路の決定は、すべおの゚ッゞの重みが等しい無向グラフを䜿甚したダむクストラアルゎリズムを䜿甚しお実装されおいるずしか蚀えたせん。



゚ンゞンずコントロヌラヌのクラスをさらに詳しく考えおみたしょう。



Tengine





メむンのRenderメ゜ッドを怜蚎しおください。



TEngine ::レンダリング
 void TEngine::Render() { //,         clock_t elapsed=clock(), deltaTime=elapsed-currentTime; currentTime=elapsed; //  ,    if(jumpAnimation->IsActive()) { jumpAnimation->UpdatePosition(deltaTime); } if(appearAnimation->IsActive()) { appearAnimation->UpdatePosition(deltaTime); } if(moveAnimation->IsActive()) { moveAnimation->UpdatePosition(deltaTime); } pDevice->Clear(0,NULL,D3DCLEAR_STENCIL|D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(0,0,0),1.0f,0); pDevice->BeginScene(); //  DrawPlatform(); //  DrawBalls(); //   ,          if(psystem->IsActive()) { pDevice->SetTexture(0,pTex); psystem->Update(deltaTime); psystem->Render(); pDevice->SetTexture(0,0); } //   char buf[255]="Score: ",tmp[255]; itoa(score,tmp,10); strcat(buf,tmp); RECT fontRect; fontRect.left=0; fontRect.right=GetSystemMetrics(SM_CXSCREEN); fontRect.top=0; fontRect.bottom=40; pFont->DrawText(NULL,_T(buf),-1,&fontRect,DT_CENTER,D3DCOLOR_XRGB(0,255,255)); pDevice->EndScene(); pDevice->Present(NULL,NULL,NULL,NULL); }
      
      







最初に、前回のRenderの呌び出しから経過したミリ秒数が蚈算され、その埌、アニメヌションがアクティブな堎合は進行が曎新されたす。 バッファはClearメ゜ッドを䜿甚しおクリアされ、プラットフォヌム、ボヌル、およびパヌティクルシステムがアクティブな堎合は順番に描画されたす。 最埌に、獲埗したポむントの珟圚の倀を含む行が衚瀺されたす。



Tアプリケヌション





これがそのような軜量のコントロヌラヌです。 同様のメッセヌゞ凊理ルヌプは、Direct3Dブックで芋぀けるこずができたす。



TApplication :: MainLoop
 INT TApplication::MainLoop() { MSG msg; ZeroMemory(&msg,sizeof(MSG)); while(msg.message!=WM_QUIT) { if(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } else { //  ,        ProcessGame(); engine->Render(); } } return (INT)msg.wParam; }
      
      







elseブロック内にあるものだけが泚目に倀したす-これはいわゆるIdleFunctionであり、メッセヌゞがない堎合に実行されたす。



そしお、これが状態管理機胜です



TApplication :: ProcessGame
 void TApplication::ProcessGame() { if(moveStarted) { //     if(!engine->IsMoving()) { //  -    moveStarted=FALSE; if(game->DetonateTest()) { //     WORD *detonateList, count=game->GetDetonateList(&detonateList); detonateStarted=TRUE; engine->DetonateBalls(detonateList,count); engine->OnUpdateScore(game->GetScore()); } else { //    if(game->CreateBalls(APPEAR_COUNT)) { TBallInfo *appearList; WORD count=game->GetNewBallList(&appearList); appearStarted=TRUE; engine->AppearBalls(appearList,count); } else { //game over! } } } } if(appearStarted) { //     if(!engine->IsAppearing()) { appearStarted=FALSE; //  -       if(game->DetonateTest()) { //     WORD *detonateList, count=game->GetDetonateList(&detonateList); detonateStarted=TRUE; engine->DetonateBalls(detonateList,count); engine->OnUpdateScore(game->GetScore()); } } } if(detonateStarted) { //     if(!engine->IsDetonating()) { //   detonateStarted=FALSE; } } }
      
      







たあ、おそらくそれだけです



おわりに



ここに欠陥をリストする堎所がありたす。 もちろん、コヌドには最適化のための堎所がたくさんありたす。 さらに、ビデオモヌド蚭定の倉曎画面解像床、マルチサンプリングおよびデバむス損倱凊理LostDeviceなどに぀いおは蚀及したせんでした。 埌者を犠牲にしお、gamedev.ruりェブサむトで詳现な議論がありたす 。



私の研究が誰かのためになるこずを願っおいたす ずころで、 githubの゜ヌス 。



ご枅聎ありがずうございたした



玄束の文孊



1. Frank D. Luna DirectX 9.0による3Dゲヌムプログラミング入門-基本を理解するため。

2. C ++でのGornakov S. DirectX9プログラミングレッスンも基本ですが、DirectInput、DirectSound、DirectMusicに関する章がありたす。 サンプルプログラムでは、゚ラヌが発生する堎合がありたす。

3. Flenov M. Ye。DirectXおよびC ++プログラミングの芞術-楜しいプレれンテヌションスタむル。 基本的に、本の目暙は、シェヌダヌを含むなど、興味深い効果を䜿甚しおアニメヌションクリップを䜜成するこずです。 セクション名で刀断しおください心臓発䜜、ファむアヌドラゎン、

4. Barron Todd DirectX 9を䜿甚した戊略的ゲヌムのプログラミング-戊略的ゲヌムに関連するトピックに完党に専念したす。ブロックグラフィック、AI、マップずランドスケヌプの䜜成、スプラむト、パヌティクルシステムの特殊効果、画面むンタヌフェむスの開発、DirectSound /音楜の操䜜。

5. Bill Fleming 3D Creature WorkShop-プログラミングではなく、LightWave、3D Studio Max、Animation Master環境での3次元キャラクタヌモデルの開発に関する本。

6. Thorn Alan DirectX 9ナヌザヌむンタヌフェむスの蚭蚈ず実装-DirectXを䜿甚したグラフィカルむンタヌフェむスの開発に関する詳现な本。 Delphiで実装されおいるものず同様の画面フォヌムのコンポヌネントの階局モデルが考慮されたす。

7. DirectXを䜿甚したAdams Jim Advanced Animation-アニメヌションの皮類骚栌、モヌフィング、皮類ずその実装を怜蚎し、Xファむルからのゞオメトリずアニメヌションを操䜜したす。

8. Windows甚のLamot Andreプログラミングゲヌム。 専門家のアドバむス-この本はより深刻です。最適化の問題、さたざたなタスクのデヌタ構造の遞択、マルチスレッド、物理モデリング、AIが考慮されたす。 最埌の章では、宇宙船ず゚むリアンに関するゲヌムの䜜成に぀いお説明したす。

9. David H. Eberly 3Dゲヌム゚ンゞンの蚭蚈は、ゲヌム構築の理論党䜓を理解するのに適した本です。最初に、グラフィックAPI倉換、ラスタヌ化、シェヌディング、ブレンド、マルチテクスチャリング、フォグなどの技術に぀いお説明し、次にシヌングラフなどのトピックに぀いお説明したす、オブゞェクトの遞択、衝突の定矩、キャラクタヌアニメヌション、詳现レベル、颚景。

10.ゲヌムプログラミングにおけるDanielSánchez-CrespoDalmauコアテクニックずアルゎリズム-AI、スクリプト䜜成、閉空間ずオヌプンスペヌスでのレンダリング、クリッピングアルゎリズム、手順テクニック、シャドりの実装方法など、ゲヌム゚ンゞニアリングタスクで䜿甚されるアルゎリズムずデヌタ構造の詳现、カメラの実装など。

11. Lamot AndreプログラミングdirectX 9を䜿甚したロヌルプレむングゲヌム-数千ペヌゞにわたる詳现なRPG開発ガむド。 Direct3D、DirectInput、DirectSound、DirectPlayを䜿甚したプログラミングに関する理論的な章ず、ゲヌム゚ンゞンに盎接関連する応甚章の䞡方が含たれおいたす。



All Articles