Windows プロフェッショナル ゲームプログラミング/秀和システム発行/やねうらお著 ISBN4-7980-0314-X フォローアップ('02/06/06) version 1.05('02/12/06)
買ってくださったみなさん、ありがとうございます。買ってくださったみなさん、(そして立ち読みでも)読んでくださったみなさんに敬意を表しまして、いくつかここでフォローアップをさせていただこうと思います。
まずは、errata(正誤表)から。ずいぶん読み返してたんですが、最後、急ぎで書き直した部分に、いくつか誤字・脱字がありました。ごめんなさいm(_ _)m 致命的な部分は、2箇所ぐらいしか無いです。そこ以外は前後関係からわかるはずです。
場所 | 内容 | コメント |
P.3 見出し L.1 |
数珠玉 ⇒ 珠玉 |
いきなり、じゅずだまってなんや?って思った人ごめんなさい。この部分、最後に編集の人が追加した部分で、私はノーチェックだったのです。 |
P.12 L.3 | あー、、 ⇒ あー、 | これ、誤りのつもりは無いですけど、たくさんご指摘をいただいたので、一応リストに載せておきます。 |
P.21 L4 | 「プリコンパイルヘッダファイル(pch)」を使用 ⇒「プリコンパイルヘッダファイル(pch)を使用」 |
タイプミス |
P.30 傍注 | 『CriticalSection』P.139 ⇒ 『CriticalSection』P.153 |
編集側のミス。 |
P.36 | マーク&スイープの説明に、参照カウンタ方式の文章が残っている | このセミナーの記事が参考になります |
P.40 L.2 | ファイルの読み込みエラーに失敗 ⇒ ファイルの読み込みに失敗 |
消し忘れ |
P.40 L.10 | ::CloseHandle(hFile); ⇒ ::CloseHandle(h); |
置換忘れ |
P.51 L.15 | 構築時に、UINT*のnewが ⇒ 構築時に、UINTのnewが |
消し忘れ |
P.51 実装2 | UINT* ⇒ UINT | 消し忘れ。実装2では obj オブジェクトを new してそれを共有するので、UINT を new する必要はない。 |
P.54 L.3 | *m_lpnCount ++; ⇒ (*m_lpnCount)++; |
優先順位をうっかり |
P.56 L.1 | ひとつ目の★に対するコメントが無い | ★の消し忘れ。編集側のミス。 |
P.60 傍注 | 傍注側の★ が抜けている | 編集側のミス。 |
P.62 list-13 | pHoge->*pFunc(3); ⇒ (pHoge->*pFunc)(3); |
コンパイルしてないのバレバレ.. |
P.62 list-14と P.63のlist-16 |
内容が同じだが? | 意図したものですが、このへん文章、もう少し整理したほうが良かったです。 |
P.75 傍注 | 傍注側の★ が抜けている | 編集側のミス。 |
P.75 下からL.2 | p2 = p.get_smart_ptr(3); ⇒ p2 = p1.get_smart_ptr(3); |
コンパイルしてないのバレバレ.. |
P.77 L.13 | 今回なら300ずつの ⇒ 今回なら毎日300円ずつの |
肝心のギャグの部分、脱字してたら笑うに笑えないっす(笑) |
P.97 L.24 | ::Create(CHoge::test,this,1,10,100)); ⇒ ::Create(&CHoge::test,this,1,10,100)); |
書き忘れ(上の行のには&がある) |
P.100 §2.24のL.5 | 現代の科学力をでは ⇒ 現代の科学力では | 消し忘れ。 |
P.104 脚注のL.1 | RTTIに関しては、第2章『RTTI』 ⇒ RTTIに関しては、§2.26『RTTI』 |
編集側の置換忘れ。 |
P.129 下からL.10 | いつもたくさん回ってみました ⇒ いつもよりたくさん回ってみました |
脱字 |
P.142 L.15 | そういう環境 ⇒ そうでない環境 |
このへん文章が読みにくい。もう少し整理すべきでした。 |
P.148 list-4 | 一つ目のif文の閉じ括弧が無い if( m_dwTimeCaps.wPeriodMin>=10){ この行の直前です(CDROMのサンプルにはついてました) |
編集側のミス。 |
P.155 脚注のL.1 | atomicとは、原子 ⇒ atomとは、原子 | 元原稿ではちゃんとatomになっている。編集側のミス。 |
P.159 L.8 | そのへんはすべてそれらにして ⇒ そのへんはすべてsingletonにして |
元原稿ではちゃんとこう書かれている。編集側が傍注を処理するときに元文章をいじってしまっている。 |
P.169 L2. | Threadクラス ⇒ CThreadクラス | 脱字 |
P.180 下からL.6 | FindeWindowで ⇒ FindWindowで | ドイツ語になってました(笑)>Finde |
P.181 L.6 | (D マズー ⇒ (゚д゚)マズー | DTPソフトで半角カナ文字が出ないので化けたそうな |
P.184 L.12 | std::mutimap ⇒ std::multimap |
誤字 |
P.189 下からL.6 | Windowsの内部的には ⇒ Windowsの内部では |
日本語が、やや変 |
P.192 L.2 | 第2章『functor』 ⇒ 2.32『functor』 |
置換忘れ。編集側のミス。 |
P.202 下からL.8 | マルチメディアは封印 ⇒ マルチメディアタイマは封印 |
脱字 |
P.213 L.18 | virtual BYTE* GetKeyData() const; ⇒ virtual const BYTE* GetKeyData() const; のほうが良い。 |
そりゃそうか.. |
P.220 L.3 | 第5章を ⇒ 第6章 | 勘違い |
P.225 L.9 | ゴルァ!(,Д,) ⇒ ゴルァ!(゚Д゚) |
DTPソフトで半角カナ文字が出ないので化けたそうな |
P.235 §3.26 L1. | 明日のジョー ⇒ あしたのジョー |
よくこんなん間違い見つけますなー。凄い! |
P.260 L.9 | チャッタリング ⇒ チャタリング |
表記のゆれ。間違いでは無いが、前後が「チャタリング」になっているのでそれで統一するべき。 |
P.265 L.11 | lock 〜 unlock 際に ⇒ lock 〜 unlock する際に |
脱字 |
P.272 L.10 | 書き込みカーソルその前方 ⇒書き込みカーソルの前方 |
消し忘れ |
P.282 下からL.8 | 一端 ⇒ 一旦 | 誤字 |
P.299 下からL.3 | それときは ⇒ そのときは | 誤字 |
P.309 一番下 | 読め込める ⇒ 読み込める | 誤字 |
P.310 脚注 | フォントサイズが大きい | 編集側のミス |
P.319 LL.2-3 |
よって、<U>サーフェースのポインタを取得して、直接書き換えたりしたいのであれば、DDBでは不可で、DirectDrawSurfaceを利用するしかありません。</U> ⇒ よって、アクセラレーションを期待したくて、かつ、サーフェースのポインタを取得して、直接書き換えたりしたいのであれば、DIBでは不可で、DirectDrawSurfaceを利用するしかありません。 |
ひどい誤植。私の編集中の文章が残っていた。 |
P.339 | 傍注2が重複している。 二つ目の傍注2.は傍注3.の誤り。 また、参照先も、§4.5(P.257〜)にすべき。 |
編集側のミス。 |
P.341 L.8 | CSeneControl ⇒ CSceneControl | 脱字。 |
P.353 | yanePackDxのところ 「yaneSDK3rdを使用できる」 ⇒「yaneSDK3rdで使用できる」 |
誤字。 |
P.353 | ygs2kのフォルダ表示が二つあるが、2つ目のygs2kは、 ygs2k\ ygs2k\ ygs2001\ とインデントを下げ忘れている。 |
編集側のミス。 |
P.374 索引 | 有限状態オートマン ⇒ 有限状態オートマトン |
編集側のミス。 |
裏表紙見返し | 既刊紹介の一番下。タイトルはOpenGLなのに、説明文はネットワーク構築になってます。 | ここまでミスるか!という感じ(笑) も〜しっかりしてよねー>編集 |
あと、いくつか質問が来ているので、それについて回答させていただきます。
Q1.
本文中、いたるところで893という定数が出てくるのですが、これは、ヤクザですか?(爆)
A1.
そうです(爆)
Q2.
P.324の13行目で、「affine変換」の捕捉に「拡大縮小回転」とありますが、これは正確では無く、「拡大縮小回転」の変換を表す変換は、「相似変換」であり、アフィン変換
= 「相似変換」+「せん断変形」 (※せん断変形:直角性は保たれないが平行性は保たれる変形です) まぁ、相似変換もアフィン変換のうちなので、アフィン変換の説明として「拡大縮小回転」という言葉が必ずしも不適切というわけではありませんが、読者に要らぬ誤解を招くような気もしたので、あえて指摘させていただきました。
A2.
確かにその通りです。言い訳がましくなりますが、P.328のaffine変換の傍注には「拡大縮小変換もこれに含まれる」と書いています。この傍注をご指摘のp.324に傍注として持ってこようと思っていたのですが、それを忘れてたようです(^^;
Q3.
P.41にある脚注の内部クラスの説明「内部クラスとは、定義されているスコープ内の変数にアクセス出来る」がわかりにくいのですが。
A3.
すみません。「内部クラスとは、そのクラスが定義されているのと同じスコープ内の変数にアクセス出来る」の意味です。
P.41の参考プログラムが、すべてを物語っているのですが、以下のように
int nOuter = 5; class InnerClass { void Out( ) { cout << nOuter; } } inner; inner.Out( ); // 5が表示される |
そのクラスが定義されているのと同じスコープにある
変数nOuterに対してアクセスできます。
リスナを書くときに、この機構が無いと非常に疲れます。
Q4.
マウスの表示非表示について。P190の20行目あたりから後です。マウスカーソルの内部的なカウンタの値についてなんですが、どーせ::ShowCursorの返り値で新しいカウンタの値が返ってくるんですから、
<マウス表示時>
while(0 < ::ShowCursor(TRUE));
<マウス非表示時>
while(0 >= ::ShowCursor(FALSE));
とでもすればいいんじゃないでしょうか。まぁ、この場合表示非表示のネストができなくなるという問題点はありますけどね。
マウスを表示しないシーン1からマウスを表示しないシーン2にうつり、その後シーン2からシーン1に戻ったとき、シーン2の最後でマウスの非表示を切るとシーン1なのにマウスが表示されてしまう……という感じでしょうか。
そのときだけ通常の::ShowCursorを使うということで(ダメじゃん)。あるいは、シーン2の内部パラメータとして元々の表示状態を保存しておき、シーンから抜けたときにそいつに復帰というのがいいかも知れません。
……もしかしたら、「その程度のことは自分で考えろ」って事だったのでしょうか。
A4.
whileで回って無理矢理表示させるというのは面白い発想ですね。なるほど。
マウスカーソルの表示、非表示の設定自体は、フルスクリーンモード(フルスクリーンモードでDirectDrawを用いて画面のFlippingを行なうのならば、カーソルはソフトウェアで描画しなければならない)であるかだとか、ソフトウェアマウスカーソルで描画する設定であるかなどによって、切り替えることになります。よって、マウスカーソルの表示/非表示等を管理するマネージャを用意して、それを通じて表示/非表示を切り替えるような設計にするので実際に、そのコードを使うかどうかはわかりませんが。
Q5.
P.214で
> var = 1 - var;
でflipさせている部分。
個人的には var ^= 1; という方が直感的に分りやすいと思ってるのですが、どんなもんなんでしょ?
もしくは var = !var; という方法もありますが、邪道でしょか?確実に
0/1 が保障されるという意味で安全性は高いと思うのですが...。
A5.
var ^= 1; は、var = 1 - var; よりテンポラリ変数がひとつ不要な分だけ良いコードだと思います。var
= !var;は直感的ですが、これ分岐が必要なので速度面では
var ^= 1;やvar = 1 - var; に劣りますね。そういう意味では、0 ⇔ 1のflipは、var ^=
1;のほうが良いですね。
Q6.
傍注で、ときどき「・・・に詳しい。」だとか、文章が不完全な状態で止まっていることがあるのですが、これは意図したものですか?
A6.
この傍注は、やねうらおが括弧表記で書いている文章があまりに多くて、それが編集者にとっては見苦しいと感じたようで、括弧の内側の文章を傍注として出してくださったのです。そのため、体言止めになっていたり、ぶっきらぼうな印象を受けたり、中途半端な文字になっていたりするのです。ある程度、校正作業のときになおしたのですが、直しきれずに残っていまして..(汗)
Q7.
やね本初版第2刷のP.39 下からL.5、§2.7 exception
(例外処理)にて
> しかし、そのときでも m_pSakura のデストラクタが呼び出されることは
> 保証されますので、 m_pSakura を auto_ptr
にしておけば、このリークは
> 防げます。
の箇所がありますが、この記述順序ですとリークを防ぐための条件順序が曖昧であるように思いました。
それは、
m_pSakura(が指すCSakuraオブジェクト)のデストラクタが呼び出されることが保証される条件はm_pSakuraにauto_ptrを
採用することにある、ということが優先条件として提示されていないためです。
そのため、例えば、
しかし、そのときでも m_pSakura を auto_ptr
にしておけば
m_pSakura のデストラクタが呼び出されることは保証されますので、
このリークは防げます。
というような方が原意に沿っているように感じました。
A7.
> m_pSakura(が指すCSakuraオブジェクト)のデストラクタ
この部分、m_pSakuraの指すオブジェクトのデストラクタではなくm_pSakura自体のデストラクタです。プリミティブデータタイプではデストラクタコードは存在しませんが、概念的には、存在すると考えたほうがわかりやすいです。そうすれば、あらゆるオブジェクトは、スコープアウトするときに、そのデストラクタが呼び出されると理解することが出来ます。
よって、m_pSakura自体のデストラクタで、このポインタが指すオブジェクトのデストラクタを呼び出すことを保証すれば良い⇒auto_ptrを使えば良い、という論理です>その部分
わかりにくい文章になっててスミマセン>原文
その他、技術的な情報。
ロベールさんより。
P.27 _CrtDumpMemoryLeaks よりは _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); の方がいいです。 理由は、静的なオブジェクトでメモリを確保していて、 そのメモリがデストラクタによって破棄されるような場合、 main/WinMain の最後に _CrtDumpMemoryLeaks を呼んでも まだ上記のメモリは開放されていないので それをメモリリークと報告してしまうからです。 _CrtSetDbgFlag でやった場合は全てのオブジェクトが破棄された後に チェックされるので、その心配はありません。 詳しい話は、手前味噌ですが http://www1.kcn.ne.jp/~robe/pf/pf008.html を参照してみて下さい。 と言っても、CMemoryState を使えば問題ないことなんですけど。 |
捕捉.マルチスレッドまわりのこととシリアライズに関しては、時間的な都合で書きたくて書けなかったことがいろいろあるのですが、それはまとめて記事にしてホームページのほうにアップします。あと、yaneSDK3rdのほうも、近々、正式公開版をホームページのほうにアップします。だもんで、許してくださいなm(_ _)m