2021/10/15
Q.
ソードの描画
A.
ソードの描画に不良が発生することがありました。申し訳ありません。p.370のMyShip.cppを以下のように修正してください。
修正前:for (int i=0, k=0; i<SWORD_TRAILS-1; i++) {
修正後:for (int i=0, k=0; i<SWORD_TRAILS; i++) {
2021/10/15
Q.
Visual Studio 2022におけるビルドと実行
A.
以下の環境におけるビルドと実行に対応したサンプルファイルを作成しました。動作確認はWindows 11 Home 21H2とVisual Studio 2022 Community RC (Release Candidate、リリース候補)で行いました。
2007/01/14
Q.
d3dx9_30.dllがないためにサンプルプログラムが実行できません。
A.
『シューティングゲーム プログラミング』P.17にありますとおり、以下のウェブサイトからSDKをダウンロードしてインストールしてください。
開発を行う場合には「DirectX SDK」がお勧めですが、サンプルを実行するだけならば「DirectX エンドユーザー ランタイム ウェブ インストーラ」が簡単です。
なお、事前にインストールしていたSDKを再インストールしたところ実行できるようになった、という御報告も頂いております。SDKをインストールしているはずなのにサンプルプログラムが動作しない、という方はお試し下さい。
2007/01/14
Q.
ゲームが処理落ちします。
A.
グラフィックチップの性能によっては処理落ちが発生することもあります。特にノートパソコンでは処理落ちが多く見られます。本書のサンプルのように、3D描画や半透明描画を使ったり、解像度を高くしたりすると、特に遅くなりやすいようです。
全画面モードで実行すると多少高速になる場合がありますので、一度お試し頂けましたら幸いです。サンプルの実行中にウィンドウ右上の最大化ボタンを押すか、Alt+Enterキーを押すと全画面モードになります。
2010/06/25
Q.
DirectXランタイムやDirectX SDKの入手先は。
A.
本書の発売後にランタイムやSDKのバージョンが変わったため、分かりにくくなり申し訳ございません。
以下のランタイムおよびSDKをお使いください。
2010/06/25
Q.
Visual C++ 2005 Express Editionの入手先は。
A.
本書の発売後にVisual C++ 2005 Express Editionの提供が終了したため、入手しづらくなり申し訳ございません。
以下のURLからはまだ入手できるようです。
2006/10/23
Q.
付録CD-ROM収録のソースコードがビルドできません。
A.
DirectX関連のインクルードファイルへのパスが通っていない可能性があります。
VisualStudio2005のメニューで[ツール|オプション]を選択し、オプションダイアログの[プロジェクトおよびソリューション]の[実行ファイル][インクルードファイル][ライブラリファイル]にそれぞれDirectX関連のパスが設定されているかどうか、ご確認ください。
例えば以下のようなパスを含める必要があります(DirectX SDKをインストールしたパスに合わせてください)。
VisualStudio2005の後にDirectX SDKをインストールした場合には、自動的に上記のパスが設定されるかと思いますので、一度DirectX SDKを再インストールすると上手くいく可能性もあります。
2006/11/03
Q.
.NET2003版サンプルプログラムがコンパイルできません。
A.
おそらくLibGame.dspもしくはLibGame.dswをお使い頂いたのかと存じます。これらはもう使っていない古いファイルだったですが、消しそびれてCD-ROMに収録してしまいました。大変申し訳ございません。
同じフォルダにあるLibGame.vcprojをお使い頂くか、またはShtGame_*フォルダ以下のShtGame.slnをお使い頂いて、コンパイルしてください。
2006/11/04
Q.
自作プロジェクトにUtil.hとUtil.cppのみを加えてビルドを行うと、エラーが発生します。
A.
以下のビルド方法をお試しください。
2006/11/08
Q.
VisualStudio2005でビルドの際に以下のエラーが発生してビルドできません。
[[ エラー 1 error LNK2005: ”public: __thiscall std::bad_cast::bad_cast(char const *)” (??0bad_cast@std@@QAE@PBD@Z) は既に LibUtil.lib(Util.obj) で定義されています。 LIBCMTD.lib ]]
A.
bad_castビルドエラーに関しては、古いVisualStudioでビルドしたライブラリをリンクしようとしたときなどに発生する模様です。(
参考資料
)
LibUtil.libやLibGame.libも含めて、一度全てVisualStudio2005でリビルド(ビルドではなく)して頂くと、解決する可能性があります。付録CD-ROMに収録したソリューション(例えばShtGame_Arrange\ShtGame.sln)をVisualStudio2005で開いて、リビルドしてみてください。また、付録CD-ROMのファイルはvs2003用ではなくvs2005用をお使いください。
なお、VisualStudioをリインストールしたらビルドに成功したというご報告を読者様から頂きました。
2008/09/17
Q.
DShow.hがincludeできないためにビルドできません。
A.
DShow.hはDirectShow関連のヘッダファイルです。本書のサンプルではBGM再生に利用しています。
DShow.hはPlatform SDK(本書p.18参照)に含まれています。Platform SDKは現在はWindows SDKに変わりましたので、誠にお手数ですがこちらをインストールしてください。
2008/09/17
Q.
dmusicc.hまたはdmusici.hがincludeできないためにビルドできません。
A.
dmusicc.hとdmusici.hはDirectMusic関連のヘッダファイルですが、DirectX SDK August 2007を最後に廃止されました。本書のサンプルでは効果音再生にDirectMusicを使用していますので、誠にお手数ですがDirectX SDK August 2007以前をご利用ください。
最新のDirectX SDKを使う場合には、サウンド再生を行わないようにプログラムを変更するか、あるいはDirectMusic以外の方法で再生する必要があります。サウンド再生の方法としては、DirectXのXAudioやXACTを使う方法、DirectX以外のライブラリ(例えばOgg Vorbis)を使う方法などがあります。
2009/10/06
Q.
DSBVOLUME_MINやDSBVOLUME_MAXについて、定義されていない識別子だというエラーが出ます。
A.
DSBVOLUME_MINとDSBVOLUME_MAXはDirectSound関連の定数で、音量の最小値と最大値を表します。DSBVOLUME_MINは-10000、DSBVOLUME_MAXは0となるようにDsound.h内で定義されていますが、SDKのバージョンによっては定義されていないようです。
誠にお手数ですが、定義されているバージョンのSDKを使用するか、エラーが出るファイルに対して、例えば下記のような定義を追記してみてください。
#define DSBVOLUME_MIN -10000
#define DSBVOLUME_MAX 0
2006/11/16
Q.
ビデオの早送りのようにゲームを高速に進行させたいのですが。
A.
移動だけではなく描画も速くする場合には、VSYNC待ちをOffにするのが有効です。
Graphics.cppの中に、
d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_ONE;
という箇所がありますが、ここを、
d3dpp.PresentationInterval=D3DPRESENT_INTERVAL_IMMEDIATE;
に変更します。
こうすると、画面表示の際にVSYNCを待たなくなります。VSYNCを待つと画面のリフレッシュレート(60Hzなど)によって速度の上限がおさえられてしまいますが、VSYNCを待たないことによって速度の上限がなくなります(マシン性能の上限まで上がります)。
ただし、VSYNCを待たない場合には常に速度が速くなってしまいます。
もし通常モードと高速モードを切り替えるのならば、Game.cppの
if (Graphics->GetRefreshRate()==FPS || Elapsed>=1.0) {
という部分を、例えば、
if (HighSpeedMode || Elapsed>=1.0) {
として、通常モードではHighSpeedModeをfalse、高速モードではtrueにする方法があります。
こうすると、通常モードではタイマーによって速度の上限をおさえて、高速モードでは一切速度の上限をおさえない、という動作になります。
2007/04/25
Q.
ゲーム座標からスクリーン座標への変換方法を教えてください。
A.
本書のサンプルプログラムでは、ゲーム内の座標を(-50, -50)~(50, 50)の範囲で表しています。
例えば以下の式で、ゲーム座標をスクリーン座標に変換することができます。
ゲーム座標を(X, Y)、スクリーン座標を(SX, SY)とすると、
SX=(X+50)/100*Game->GetGraphics()->GetWidth();
SY=(Y+50)/100*Game->GetGraphics()->GetHeight();
なお、3Dの座標系はp.116で、3Dから2Dに座標系を変換する方法はp.317で解説しています。
2009/04/02
Q.
assert関数が「クラスサイズが最大サイズを超えた」というエラーを出します。
A.
Main.cppなどで、
MyShipList=new CTaskList(sizeof(CMyShip), 10);
のようにタスクリストを初期化している箇所があります。
第一引数のsizeof(CMyShip)がタスクの最大サイズです。この値を大きくすれば、assertのエラーは解消します。
この値は「sizeof(CMyShip)」のようにsizeofで指定することも、「200」のように数値で指定することもできます。タスクリストで確保するクラスの最大サイズ以上のサイズを指定してください。
詳細は本書のp.95のList3-16や、p.141のList4-14などをご参照ください。
2009/04/02
Q.
画像を回転させて表示したい。
A.
本書収録のDraw関数は回転を想定していないので、回転機能を持つDraw関数を新たに作る必要があります。回転行列を使えば実現できます。
『アクションゲームアルゴリズムマニアックス』か『パズルゲームアルゴリズムマニアックス』をもしお持ちでしたら、キャラクターを回転させるサンプルコードが入っていますので(CMover::Draw関数)、こちらをご参照ください。
2009/04/02
Q.
BGMが鳴りません。
A.
以下をご確認ください。
2009/04/02
Q.
画像の一部分だけを表示したい。
A.
CTextureクラスの以下のDraw関数を使います。
void Draw(
float x, float y, float dx, float dy,
float u, float v, float du, float dv,
D3DCOLOR diffuse
);
u, vがテクスチャ座標、du, dvがテクスチャ座標の差分となっています。
これらを例えば0, 0, 0.5, 0.5に設定すると、画像の左上1/4だけが表示されると思います。
2009/04/02
Q.
ステージを追加する方法は?
A.
ステージの追加については本書p.302~p.303をご参照ください。
1面ボスが終わった後に、2面が始まるようなスクリプトの例があります。
スクリプトを書けば、プログラム本体に手を入れなくてもステージの追加が可能です。
他のボスを出現させる場合には、本書Chapter09のようにボスのクラスを定義します。
2009/04/02
Q.
弾などを3Dモデルではなく2D画像で表示したい。
A.
弾を2Dで表示するには、本書p.152のCBulletクラスのDraw関数を書き換えればよいかと思います。
今は3Dモデルを描くようになっていますが、ここを2D画像を描くように変更します。
2D画像の描画については、p.32から解説しているCTextureクラスを使うとよいでしょう。
タイトル画面やフォントは2D(PNG画像)で描いているので、これらの処理を参考にしていただけましたら幸いです。
2009/04/02
Q.
LibUtilは何をするライブラリなのか。
A.
LibUtilはWin32 API周りの色々な処理をまとめたライブラリです。
本書のほか、ひぐぺん工房のゲームプログラミング書籍の多くで使用しています。
ライブラリはたびたびアップデートしているため、書籍ごとに細かな仕様は多少異なります。
ライブラリの概要は以下の通りです。
2009/11/09
Q.
タスクリストのメモリはいつ解放されるのか。
A.
タスクリストのコンストラクタ、
CTaskList::CTaskList(int max_task_size, int max_num_task)
では、
char* buf=new char[max_task_size*(max_num_task+2)];
のようにメモリ領域を確保しますが、CTaskList::~CTaskListは存在せず、確保した領域を開放する処理もありません。しかしメモリリークは起きず、メモリが正しく開放されているように動きます。
このサンプルでは以下の理由から、new char[]で確保した領域を明示的に解放する処理を省略しています。同様の理由で、他にもメモリの破棄を省略している部分があります。
2009/11/27
Q.
フォルダの構造を変えたら、ヘッダファイルがincludeできない。
A.
ShtGame、LibGame、LibUtilなどのフォルダ構造を変更したときには、include指示文を変更しなければならない可能性があります。
元のフォルダ構造は以下の通りです。例えばShtGameをMyGameに変更するなど、フォルダ名を変えただけならば、include指示文の修正は必要ありません。
ShtGame
Main.h
#include "..\LibGame\LibGame.h"
#include "..\LibUtil\LibUtil.h"
...
LibGame
LibGame.h
Texture.h
#include "..\LibUtil\Archive.h"
...
LibUtil
LibUtil.h
Archive.h
...
一方、フォルダの構造やファイルの配置を変更した場合には、include指示文の修正が必要です。例えば全てのファイルを同じフォルダに格納する場合には、以下のように修正します。
MyGame
Main.h
#include "LibGame.h"
#include "LibUtil.h"
LibGame.h
Texture.h
#include "Archive.h"
LibUtil.h
Archive.h
...
他のファイルについても同様に、フォルダ構造に応じてinclude指示文を変更する必要があります。
2010/03/19
Q.
フォルダの構造を変えたら、リンクエラーが出る。
A.
例えば、以下のようなリンクエラーが出ることがあります。
外部参照(Main.obj : error LNK2019: 未解決の外部シンボル ”public: __thiscall CGame::~CGame(void)”...が関数...で参照されました。
このエラーは「Main.obj(Main.cpp)でCGame::~CGame()(CGameクラスのデストラクタ)を呼び出しているにも関わらず、~CGame()が定義されていない」という意味です。
コンパイルエラーではなくリンクエラーなので、CGameクラスの定義には~CGame()の宣言が含まれていると思われます。おそらく、~CGame()の実体を定義していないか、~CGame()を定義したソースファイルをコンパイル対象に含めていないことが原因でしょう。~CGame()の実体を定義して、そのソースファイルをプロジェクトに含めれば、エラーは解消すると考えられます。
また、以下のようなリンクエラーが出ることもあります。
AnimMesh.obj : error LNK2019: 未解決の外部シンボル・・・
このエラーはAnimMesh.obj(AnimMesh.cpp)内で使用しているシンボル(変数や関数等)が定義されていないという意味です。シンボルが定義されているファイル(ライブラリやオブジェクトファイル)をリンクすれば解決します。未解決の外部シンボルが何なのかによって、リンクすべきファイルが変わります。原因としては、例えば以下のような事柄が考えられます。
2010/01/22
Q.
libjpegやlibpngは何に使っているのか。
A.
本書のサンプルに含まれるLibUtilライブラリでは、libjpegやlibpngを利用させて頂いております。libjpegはJPEG画像を扱うためのライブラリで、libpngはPNG画像を扱うためのライブラリです。
アプリケーションでDirectXを使用する場合と使用しない場合のために、以下のように画像を表示するコードを2種類用意しました。
2010/01/22
Q.
背景に画像を表示するには。
A.
LibGameライブラリのCTextureクラスを使います。本書ではPNG画像を使っていますが、JPEG画像やBMP画像も読み込むことができると思われます(D3DXCreateTextureFromFileExが対応している画像形式は読み込めます)。
表示方法はp.215~p.218にあるタイトル画像の表示と同様に、Draw関数を使います。背景に画像を表示する場合には、先に背景を描いてから、後で自機や敵などのキャラクターを重ねて描きます。
2010/04/12
Q.
座標系を変更するには。
A.
本書ではp.117のような座標系を採用しています。2Dではプレイヤーから見て、左から右にX軸、上から下にY軸が伸びています。3Dではプレイヤーから見て、左から右にX軸、下から上にZ軸、奥から手前にY軸が伸びています。2Dと3Dで座標系の扱いが異なるのは、2Dの座標を扱いやすくするためです。
座標系の違いは、描画の際に簡単な変換を行うことで吸収します。例えば弾については、次のように3Dモデルを描画します(Bullet.cpp)。2D座標の(X, Y)は、3D座標では(X, Z, -Y)になります。Zは重ね合わせの順番を制御するために使います(自機よりも弾を手前に表示するなど)。
Mesh->Draw(X, Z, -Y, 1, 1, 1, 0, Yaw, 0, TO_ZYX, 1, false);
もしも視点を変えたいときなど、3D座標の扱いを変更する場合には、座標の変換方法も変える必要があります。例えばプレイヤーから見て、Z軸が手前から奥に伸びるように配置するには、2D座標の(X, Y)が3D座標の(X, -Y, -Z)に変わります。また、回転に関しても調整する必要があります。モデルの作り方によっては、モデルを90度(D3DX_PI/2)回転させることにより、正しく見えるように調整する必要があるかもしれません。
Mesh->Draw(X, -Y, -Z, 1, 1, 1, D3DX_PI/2, 0, Yaw, TO_XYZ, 1, false);
なお、視点については以下のコードで設定しています(Main.cpp)。vec_fromは視点、vec_lookatは注視点、vec_upは画面の上方向を表すベクトルです。
D3DXMATRIX mat_view;
D3DXVECTOR3 vec_from=D3DXVECTOR3(0, 100, 0);
D3DXVECTOR3 vec_lookat=D3DXVECTOR3(0, 0, 0);
D3DXVECTOR3 vec_up=D3DXVECTOR3(0, 0, 1);
D3DXMatrixLookAtLH(&mat_view, &vec_from, &vec_lookat, &vec_up);
device->SetTransform(D3DTS_VIEW, &mat_view);
視点の設定については、『ゲームエフェクトマニアックス』や『3D格闘ゲームプログラミング』といった他の書籍でも扱っていますので、参考にして頂けましたら幸いです。
2011/01/26
Q.
同一のタスクリスト内で当たり判定処理を行うには。
A.
本書のサンプルではキャラクタの種類別にタスクリストを分けています。例えば、自機のタスクリスト、敵のタスクリスト、弾のタスクリスト、武器のタスクリストといった要領です。当たり判定処理は異なるタスクリスト間で行います。種類別にタスクリストが分かれているので、同一のタスクリスト内では当たり判定処理を行いません。
同一のタスクリスト内で当たり判定処理を行うこともできます。その際に注意するべきなのは次の点です。
2011/01/29
Q.
タスクに優先順位を追加するには。
A.
目的に応じていくつかの方法が考えられます。
一つの方法は、同一のタスクリスト内にあるタスクに対して、個別に優先順位を割り当てる方法です。この場合は、タスククラス(CTask)に優先順位を表す変数(Priorityなど)を追加します。必要に応じて、優先順位の取得や設定を行う関数も追加します。そして、タスクリスト(CTaskList)にタスクを追加する際に、タスクイテレータ(CTaskIter)を用いて順番にタスクを調べ、優先順位に対応する位置にタスクを挿入することによって、タスクリスト上でタスクが優先順位の高い順に並ぶようにします。あとはタスクリストの先頭から順にタスクを処理すれば、優先順位順にタスクを処理することができます。この方法はタスクごとに細かく優先順位を決められますが、タスクリストにタスクを追加する処理には手間がかかります。
もう一つの方法は、優先順位が異なる複数のタスクリストを用意する方法です。タスクの優先順位に応じて、対応するタスクリストにタスクを追加します。例えば、優先順位が高いタスクリスト、中程度のタスクリスト、低いタスクリストなどに分けておいて、優先順位が高いタスクリストのタスクから処理すればよいでしょう。この方法はタスクリストにタスクを追加する処理が軽いことが利点です。優先順位の段階があまり多いと、タスクリストの数が多くなってしまいますが、数段階ならばこの方法が適しているかもしれません。
2011/05/24
Q.
タスクの最大サイズを超えたというエラーが表示される。
A.
タスククラス(CTask)の派生クラス(CMover、CBulletなど)のサイズ(バイト数)が規定のサイズを超えると、このエラー(assert)が表示されます。例えばクラスに色々な機能を追加すると、このエラーが発生することがあります。エラーを解消するには、タスクリスト(CTaskList)を初期化する際にタスクのサイズを大きめに設定します。
例えば本書のサンプルでは、弾(CBullet)のタスクリストを以下のように設定しています。CTaskListコンストラクタの第1引数がタスクのサイズです。ここではCSplitBulletクラスのバイト数であるsizeof(CSplitBullet)を指定しています。CSplitBulletクラスは弾の中でも最大のクラスなので、このクラスに合わせてメモリを確保しています。
BulletList=new CTaskList(sizeof(CSplitBullet), 2000);
もしCSplitBulletクラスよりもバイト数が多いクラスがあるならば、そのクラスのサイズをsizeofで指定してみてください。あるいは、new CTaskList(300, 2000)のように、バイト数を直接指定することもできます。
2011/05/24
Q.
タスクの最大数を超えたというエラーが表示される。
A.
フリータスク数が最大タスク数を超えると、このエラー(assert)が発生します。同じタスクに対してdeleteを重複して呼び出したことなどが原因なので、deleteの重複呼び出しがないかどうか、プログラムを見直してみてください。
2011/11/15
Q.
CTexture(LPDIRECT3DDEVICE9 device, int w, int h)の使い方は。
A.
本書では使用していませんが、CTexture(LPDIRECT3DDEVICE9 device, int w, int h)は指定したサイズのテクスチャを作成します。主に作業用のテクスチャを作るために使います。このコンストラクタはD3DPOOL_DEFAULTオプションを指定してテクスチャを作成するため、フルスクリーン切り替え時などにDirect3Dデバイスをロストすると、テクスチャが失われることがあります。
対応策は、Direct3DデバイスをロストしたときにテクスチャをReleaseするとともに、デバイスをリセットする際にテクスチャを再び生成することです。CGameクラスのOnLostDevice関数とOnResetDevice関数をオーバーライドして、テクスチャのReleaseと生成のコードを記述する必要があります。
詳しくはDirect3Dデバイスのロストとリセット、D3DPOOL_DEFAULTやD3DPOOL_MANAGEDについて調べてみてください。
2017/10/10
Q.
CBigNumクラスで減算処理を行うには。
A.
BigNumのAdd関数は減算には対応していません。引数にマイナスの数値を指定しても、減算を行うことはできません。
そこで、減算を行うSub関数を作成してみました。修正点は下記です。
■BigNum.hに以下の宣言を追加します。
void Sub(int x);
■BigNum.cppに以下の定義を追加します。
void CBigNum::Sub(int x) {
for (int i=NumDigits-1; i>=0 && x>0; i--) {
int t=Digits[i]-'0'+10-x%10;
Digits[i]=t%10+'0';
x=x/10+1-t/10;
}
if (x>0) Set(0);
}
2009/5/31
Q.
本書を利用した作品を就職活動の自己PRに使いたい。
A.
プログラム内およびドキュメント等において、本書流用部分に関するプログラムやデータの著作権者(松浦健一郎・司ゆき/ひぐぺん工房)を明示して頂けましたら、ご利用頂いて構いません。
(例えば「ライブラリおよび基本プログラムに関して書籍『シューティングゲームプログラミング』(松浦健一郎・司ゆき/ひぐぺん工房)のプログラムを利用した」など)
2022/2/22
Q.
本書を利用してシューティング以外のゲームを作るには。
A.
本書のプログラムを利用して、シューティング以外のゲームを作ることも可能です。グラフィックス(3Dおよび2D)・入力・サウンドなどの処理を行うゲームライブラリについては、本書のChapter02で解説しています。キャラクタの移動処理や当たり判定処理などについては、本書で解説しているシューティングゲームと同じ手法が応用できます。各種のジャンルに特有のアルゴリズムについては、『シューティングゲームアルゴリズムマニアックス』、『アクションゲームアルゴリズムマニアックス』、『パズルゲームアルゴリズムマニアックス』で詳細に解説しています。