2012年6月20日水曜日

Rust 0.2's undocumented function argument prefixes

Maybe someone will find this from google...

around line 1400 of src/libsyntax/print/pprust.rs:

fn mode_to_str(m: ast::mode) -> str {
    alt m {
      ast::expl(ast::by_mutbl_ref) { "&" }
      ast::expl(ast::by_move) { "-" }
      ast::expl(ast::by_ref) { "&&" }
      ast::expl(ast::by_val) { "++" }
      ast::expl(ast::by_copy) { "+" }
      ast::infer(_) { "" }
    }
}

"&&", "++" are not documented yet in both the tutorial and the reference.
"&&" seems like just an immutable version of "&".
"++" will be not useful in most cases -- it is guaranteed to rust compiler choices the better way between by-value and by-reference passing. However this might be useful when we want to declare C-interface functions, which must always use by-value passing.

#############################

Rust言語(ver.0.2, 06/20時点でのgit最新版)です。
関数の引数名のところに、よく意味不明なプレフィックスがついていたので気になって調べてみました。
"&", "-", "+"については公式のチュートリアルに解説があります(なぜかリファレンスには載ってない?)。
"&&"と"++"については、チュートリアルにも載ってなかったのでソースコードから掘り出してみたところ上記のようなソースコードを発見しました。
名前から察するに、
"&&": ただの"&"のconst版 (C++のconst&みたいなの)、強制的に参照渡し
"++": 強制的に値渡し
基本的にRustではコンパイラが勝手に参照渡しと値渡しのうち効率のいい方を使ってくれるはずなのであまり出番がなさそうですが、C言語へのインターフェース関数を書きたい時には強制値渡しの"++"を常時使っておいたほうが安全かもしれません。

2009年10月21日水曜日

boost-build(+bjam)でコンパイラ依存のコンパイラスイッチを渡すとき

最近はビルドにsconsよりbjam+boost-buildの方を使っています。
最新コンパイラへの対応状況がいいのと、debug/releaseビルドの.objファイルが別ディレクトリに保存される(互いに上書きされない)ので切り替えが楽な点などを評価しています。若干ドキュメントが少ないのが問題ですね。 特にboost-build v2は個別moduleに関するドキュメントが皆無で困ります。

最近ビルド時に特定のコンパイラのみフラグをつけたい(例えばMSVCで特定の警告を消すなど)という事態があり、軽く悩んだので後続の人がいるのか知りませんがそんな人のための覚書。普段<cflags>/wd4819のようにしてフラグを指定しますが、これをgccなど他のコンパイラでは付加させないようにするには、<toolset>msvc:<cflags>/wd4819 のように、toolsetの値によって条件付きのフラグにしてしまえばいいようです。

もっと大きな差分、たとえばコンパイラごとにビルドルールの種類とかまで変えたい場合は、たぶんbjam側のドキュメントを読む必要がありそうな気がしていなくもないような気がしている気配。

2009年6月16日火曜日

OpenGL3.0、GLSL1.3の超超入門

こちらのブログが超超参考になります。 超超参考にしました。
http://monsho.blog63.fc2.com/?q=OpenGL

お日柄もよろしく、OpenGLもいつの間にかメジャーバージョンが3になりまして、仕様書をよく読んでみると1.5ぐらいの頃とはまるで違う関数名に驚きまくりの日々を送る今日この頃です。 皆様いかがお過ごしでしょうか。

少し取り乱しました。 今さっき三角形ポリゴンがやっとこさ表示できたので、ちょっとテンションがおかしくなってます。 以下、大まかなポリゴン表示までの最低限の流れと、注意点などを記述していきます。 対象としては、ちょっとぐらいならOpenGLを触ったことのある人、近年のシェーダによる3Dグラフィックス描画モデルを大体理解している人、あたりを想定しています。

OpenGL3.0の怖いところは、旧来の例えばglVertexなどの『とりあえず表示できるか試してみようや』系の関数などがまるごとDeprecated扱いされている点です。 実際の所はただDeprecatedと言われているだけで、使おうと思えば使えるのですが、この記事の主旨としてはそういったDeprecatedな関数を使わない方向で行きます。
そしてもう一つ怖いところは、これはDirect3D10でも同様なのですが、固定機能が削除されたことにより、シェーダを書かないことにはどうにもならないということです。 新しいAPIを習得するのに加え、新しい言語まで……ということで、かなーりハードルが高くなっています。
GLUTによるウィンドウの表示部分は全く変更する必要がないのが、まぁ救いと言えば救いでしょうか。

さて、まずはライブラリのインストールから始まります。 私事ですが、最近日替わりでOSを入れ替えるようにしていて、偶数日はWindows Vista、奇数日はUbuntu 9.04(Linux)と、まぁ比較的チキンなOSの選択ではあるのですがとにかくWindows環境とLinux環境を交互に使っています。 なので、ここでは両環境でのインストール周りの問題について記述します。

まずWindowsですが、OpenGLの開発をやったことのある皆様ならご存じの通り、PlatformSDKのGL/gl.hはバージョン1.1のまま停滞しています。 そのため、GLEWというライブラリを導入する必要があります。 OpenGL3.0の機能を使うためには、GLEW 1.5.1以上のバージョンが必要です。 多分、これのインストールについては困ることはほとんどないと思います。 glewInit()関数を適当なタイミングで呼び出すことさえ忘れなければ、すぐにでもOpenGL3.0の機能が使えます。 もしも実行時に0x00000000を呼び出した系のエラーが出た場合は、glewInit()の呼び出しタイミングを変えてみましょう。

で、Linuxなのですが、ややこしいことにUbuntu 9.04で入っているGLEWは1.5.0のためOpenGL3.0が使えません。しかし、デフォルトで入っているGL/gl.hが3.0のため、Ubuntu 9.04ではむしろGLEWを使う必要がありません(もちろん、拡張機能を使いたい場合は除く)。 ざっと調べてみたところ、次期Ubuntuの9.10ではGLEW1.5.1のパッケージが期待できるようです。 どーしてもUbuntu 9.04でGLEW1.5.1を使いたい人は、Makefileの改行コードをCRLF->LFに変換し、make時に見つからないと文句を言われたlibなんとかをapt-getで導入してください。 多分コンパイルが通るはずです。

それとインストールとは少し違いますが、OpenGL3.0とGLSL1.3の仕様書は手元に置いておきましょう。 適当にググれば公式っぽい所から落とせるはずです(英語が苦手な人は、Specificationの文字を頼りに!)。

さて、やっとコードを書き書きする作業に入ります。 まず、ウィンドウの表示まではGLUTに任せてしまいましょう。 GLUTの扱いに関しては、日本語の資料がWeb上に十分すぎるほど転がっているのでここでは割愛します。

ここから本番です。 大まかに、ポリゴンを表示するまでのステップは、
  • 頂点データの準備
  • シェーダコードを書く
  • シェーダをコンパイルするコードを書く
  • 頂点データをシェーダにAttachする
  • フレームごとに描画をする
という5段階に分かれます。

まず、頂点データの準備から行きましょう。 ここは比較的簡単で、適当にstructを自分で定義してやれば済む話です。 今回は簡単なポリゴン板の表示ということで、struct内には座標と色ぐらいがあれば十分でしょう。

struct vertex {
GLfloat pos[3]; // [3]でも[4]でも、何なら[2]でも大丈夫です
GLfloat color[4];
};


次に、シェーダコードを書きます。 ここでシェーダ言語の詳説をするのはとてもめんどくさいので、詳しい仕様は仕様書見ろ! ということで、最小限のコードだけ書いてみます。

頂点シェーダ

===
#version 130

in vec4 pos;
in vec4 color;

out vec4 gl_Position;
out vec4 vo_color;

void main(void) {
gl_Position = pos;
vo_color = color;
}
===


フラグメントシェーダ

===
#version 130

in vec4 vo_color;

out vec4 fragment_color;

void main(void) {
fragment_color = vo_color;
}
===


まず、一番最初に#version 130と書いてバージョンを指定してやる必要があるみたいです。 その後は、ほとんどCの構文と同じになります(void mainが気持ち悪いですが)。

シェーダへの入出力は、グローバル空間にinまたはout修飾子をつけた変数を宣言することにより定義されます。 大事なことは、
  • gl_Positionは頂点シェーダの出力として予約されている名前で、頂点の座標を示す
  • 他の名前は、頂点シェーダ→フラグメントシェーダへと渡され、それぞれの出力と入力で同じ名前でなければならない
  • フラグメントシェーダの一番最初の出力が、最終的な出力色になる
あたりでしょうか。

次に、シェーダをコンパイルします。 シェーダ周りのOpenGLのデータ構造は2つあって、ShaderとProgramというものです。 Shaderは先程書いたシェーダコード一つ一つに対応し、Programは頂点シェーダ→(ジオメトリシェーダ)→フラグメントシェーダの流れに対応します。 Shader∈Programということですね。
頂点シェーダとフラグメントシェーダの作成手順はだいたい同じで、こんな感じになります。
  • CreateShader(GL_VERTEX_SHADER)でシェーダを作成する
  • ShaderSource(shader, count, string, length)でシェーダにソースコードを読み込ませる(ちなみに、複数の文字列を渡せるようになっていますが、全部連結されます。 サイズの判らないファイルから読み込んだりするときに便利)
  • CompileShader(shader)でコンパイルする
で、これをProgramにまとめるわけです。
  • CreateProgram()でProgramを作成する
  • AttatchShader(program, shader)を何回か呼び出して、シェーダを関連づける
  • LinkProgram(program)で、シェーダ間のデータ転送がちゃんとできてるか確認する
  • UseProgram(program)で、Programが描画時に使われるようにする
と、これでProgramの作成は終わりです。

次のステップは、頂点データをProgramにアタッチする作業です。 先程のリンクがうまくいっていれば、頂点シェーダでin修飾子をつけて書いたグローバル変数が、Programへの入力として認識されているはずです。 ハマりやすいポイントなのですが、最適化の結果としてProgramへの入力が実際の頂点シェーダのコードより減っている可能性があります。 使われていない入力、0.0が掛けられている入力などは、無かったことにされてしまっているので注意しましょう。

関数の呼び出し順としては、次のようになります。
  • (任意)GetProgramiv(program, GL_ACTIVE_ATTRIBUTES, params)で、入力のデータ数を取得する
  • GetAttribLocation(program, name)で、nameという名前の入力に対応する番号を取得する
  • EnableVertexAttribArray(index)で、この番号の入力をEnable状態にする
  • VertexAttribPointer(index, size, type, normalized, stride, pointer)で、頂点データの配列をある入力番号にバインドする
strideを適切に指定し、offsetofマクロをうまいこと使えば、Direct3Dでやっているような頂点1つごとに構造体としてメモリ上にまとまっているような形式でも、ちゃんと渡すことができます。

最後のステップとして、フレームごとに(GLUTなら、glutDisplayFuncに登録した関数の呼び出しごとに)DrawArraysを呼び出して(頂点インデックスを用いない場合……用いる場合はDrawElements系を使いましょう)、Flushしてやれば完璧です。 一つだけ私が引っかかった罠を書いておきますと、DrawArraysの第三引数countは頂点の数で、決して決してプリミティブの数ではありません。 Direct3D10のID3D10Device::Draw関数でも全く同じ罠に盛大に引っかかったような記憶があります。

OpenGLはデフォルトではカリングはしない設定になっており、またzカリングも[0.0, 1.0]の範囲に入れておけばまぁ安全でしょう。 OpenGLの関数はエラー値を返さず、いちいちGetErrorでエラーを確認する必要がありますので、適当にマクロ化なり関数化しておくと便利です。 また、シェーダのコンパイル・リンク時にはさらに詳細なエラーメッセージが得られるので、GetShaderInfoLog関数で得られるエラーメッセージをちゃんと表示しておくようにするとデバッグが早いです。

2008年11月23日日曜日

アーケード版 RAMBO(ランボー) 攻略情報まとめ

アーケードで稼働中、ガンシューティングのRAMBO初心者向け攻略記事です。

参考スレ: 2ch アーケード板 【怒りを】RAMBO【解き放て】
http://jfk.2ch.net/test/read.cgi/arc/1221994290

大体攻略情報は上のスレで出尽くしているのでそこからの借用という形になるのですが、dat落ちしたときのためにここでワンコインクリアぐらいまでに必要になる攻略情報をまとめておきます。
私自身あまり上手くないのと、スレであまり話題が出ていないため、スコアアタックに関する情報は取り扱いません。

【未クリアの人のために】
初見ではあまり多くのことは覚えられないでしょうし、書きすぎるのも興醒めだと思うので、最小限必要なことだけを記述しておきます。

■ゲームシステム
  • 敵の弱点は頭ではなく武器。 固い兵も一撃で倒せ、面クリア後の査定に関わってくるので重要。
  • ゲーム中でも説明されるが、銃口付近にあるボタン(HOD4で言う手榴弾ボタン)を押すと怒りモードが発動し、怒りゲージの残量に応じた時間だけ継続する。 発動中は自動リロード、攻撃力倍増。 このとき怒りゲージがMAXの状態だと、発動中ずっと完全無敵になれる。
  • 各ステージクリア後の査定結果によって、ライフが増加することがある。 評価要素はスコア、命中率、勲章数。
  • 敵の攻撃によってはライフ2つ分のダメージを食らうことがある。 ロケラン持ちのマッチョ兵は最優先で倒すこと!
■各面最重要暗記情報
  • 1面ボスのヘリは1人プレイだと非常にシビアなので、最初から怒りを発動していこう。 途中でダメージを食らっても、次のシーンで発動する怒りゲージが溜まったとポジティブに考えるべし。
  • 2面ボスの機関銃も1人プレイだと非常にシビア。 攻撃が3+2回あるが、どちらも怒りを発動するべき。
  • 3面、階段登った直後のシーンにライフ+2がある。 3人いる敵を早まって全滅させなければ、回収は全く難しくないので落ち着いていこう。
  • 4面ボスは後半に2ダメージ攻撃を連発してくる。 岩×2の直後に来る早撃ちの左→右の順を暗記し、その後の主砲攻撃×2のために前半は怒りを使わないで温存しておくこと。
  • 5面はボスよりも道中の方が難しい。 早め早めに怒りを発動すること。 シーン切り替えの関係上、怒りを発動してもゲージが残りやすい。
【ワンコインクリアを目指す人のために】
私自身シューティングをあまりやるわけではないのですが、このゲームのワンコインクリアはわりと簡単な部類に入ると思います。 回復できる場所が多く、ダメージを受けやすい場所を怒り無敵で回避できるので、多少覚えさえすればすぐにワンコインでクリアできるようになると思います。

■1面
1・2面はダメージポイントが多い割に回復アイテムが少なく、ワンコインクリア最大の難関と言ってしまってもいいと思います。 逆にここを突破できれば、あとは5面次第ということになります。
  • 全体的に敵車両が多く出てくるので、兵士よりもまず車両に撃ち込んで命中率を稼ぐこと。 1面終了後のボーナスライフはとても大事。
  • 「お前たちはやりすぎたのだ」と言われたら怒りを発動するとごりごり倒せて楽しい。 直後に怒りMAXになるので遠慮なく。
  • 増援到着後のシーンの次、画面中央にある箱に回復アイテム。 判りやすいが、最初にいる3人の敵を倒してしまうと通り過ぎる車の影に一瞬隠れたりとか敵の攻撃が激しくなったりとかするので、きちんと順序立てた方がいいかも。
  • 次のシーン、画面左から右に走るジープ上のマッチョ兵が鬼門。 頑張って武器狙いで瞬殺しよう。
  • ボス最初の攻撃は怒りを発動しないと厳しい。 ちなみに怒りを発動すると自分のプレイサイドがエフェクトで非常に見辛くなるので、自分と反対側から撃っていくといい。
  • 機関銃兵と手榴弾は楽なはず。 割愛。
  • 次のロープ兵も難しめ。 画面左下から出現するのだが、出現直後はなぜか妙に柔らかいのでこの時を狙って撃ち込むこと。 逆に、敵が画面下ぐらいまで移動したときに2人以上残っているようだと高確率でダメージを受ける。
  • 次の岩は最難関。 直前のロープ兵でダメージを受けているなら、怒りゲージが半分溜まっているはずなので最初から発動。 そうでなくても少しぐらいは溜まっているはずなので、リロードの代わりに怒りを発動してとにかく撃ち込み続ける。 壊せたらラッキーぐらいの感覚で。
  • 最後の弓は楽勝でしょう。

■2面
やはり回復アイテムが少ない割にダメージを受けやすい箇所が多いので難しいです。 このステージからは狙撃などの成功すれば勲章、失敗すれば敵増援のようなパターンが随所に出てきますが、ワンコインクリアの観点からは勲章の方が面クリア後の査定で圧倒的に高得点なので、わざと失敗する必要は全くありません。
  • 開始後しばらくは敵グループの中にやや固い指揮官が1人混じっており、それを倒すと赤兵以外の攻撃が中断される。 しかしそれが必要になるほどシビアな場面がなく、また赤兵は止まってくれないので、優先して狙う必要は全くない。 ちなみにずっと放置しているとちゃんと攻撃してくる。
  • 森に向かって左に移動しながら敵を次々と倒すシーンの次、画面右の箱に回復アイテム。 最初に見えている赤兵を倒したら、あとは余裕綽々回収できる。 時間が経つとカメラアングルの関係上茂みの影に隠れて見えなくなるが、撃てば普通に回収できる。
  • ナイフ、狙撃×2。 ナイフはきちんと赤丸を撃つ必要がある。 狙撃は難しくないだろう。
  • 水場に向かう。 見下ろしアングルで積荷前にいる敵を数人倒した後、振り向いた先にいるロケラン兵からダメージを食らいやすい。 振り向いたら何も考えずに画面中央に連射。
  • 積荷越しの戦闘、最後の最後で積荷の後ろを隠れながら走り抜ける兵士が難しい。 出るタイミングを覚えてしまえば、あらかじめ画面右の空間に連射しておくことで安定して倒せる。 参考までに筆者のやり方では、5人ほど倒した後画面左に赤兵が出現したらそれを無視して画面右の空間に連射、倒せたら赤兵を急いで攻撃。
  • 敵ボートとの戦闘。 1回目の機関銃は3機あり、最初から怒りを発動してしまうと最後の機関銃の頃には怒りが切れてしまう。 1機目の機関銃はオマケの敵兵もおらず耐久力も比較的低いので、ぎりぎりまで怒りの発動は我慢して普通に撃ち込むべき。 筆者は攻撃ゲージが10時の方向になった頃に発動している。
  • ボート上の兵士との戦闘。 一般兵の他にロケラン兵と手榴弾兵がいるが、もちろんロケラン兵を最優先で倒す。 手榴弾は投擲された後も着弾まで1秒程度の余裕があるので、どんどん後回しにしてしまって構わない。
  • 機関銃2回目。 溜まっている怒りゲージの量と相談しながら、適当なタイミングで怒り発動。 怒りを使えばそれほど難しくはない。
  • 川岸到着後、敵兵多数×3セット。 3セット目最後にロケラン兵が2人現れるが、目標が小さく撃ち込むのが難しいため怒り発動を推奨。
  • 爆弾投下、ハイパー連打タイム。 各自のやりやすいように。 筆者は親指で痙攣打法。
  • ガチムチレスリング。 赤丸2回→ムービー→赤丸3回→連打の順。 赤丸の位置は毎回固定なので、暗記してしまおう。 ユーシン軍曹の頭→脇腹→ムービー→(向かって)右肘、右肘、左肘の順。 連打は先の連打に比べれば遙かに楽勝。

■3面
ここから4面ボス前まではライフを貯める場所です。 ダメージポイントがほとんどないので楽勝でしょう。 クリア後の評価で命中率が非常に低くなりやすいので、道中数台ある車にきちんと撃ち込むことを意識しましょう。
  • 狙撃×3。 何故か1回目と3回目が非常に外れやすい。 この2つだけがシビアなのか、判定がずれているだけなのかは謎。
  • 着陸まで。 実は弾無限。 見えた敵を普通に倒していれば、着陸時に勲章を貰える。
  • 着陸後、しばらくの間難しいところはない。 ドラム缶・箱は比較的シビアなシーンに多いので無視しても可。 車は全て楽なシーンや移動中に現れるのでちゃんと壊すこと。
  • 階段を見上げ(この時敵が出るときと出ないときがある)、登った直後のシーンにライフ2回復アイテム。 敵が3人出てくるが、左の二人を倒し、画面左にあるドラム缶を破壊し、残った一人を倒すという手順を落ち着いて踏めば大丈夫。 右の敵は最初から攻撃ゲージが溜まっているので焦りがちだが、溜まる速度がものすごく遅いので安心。
  • またしばらくの間楽勝ムード。 最初の狙撃で1回目の攻撃を失敗している場合のみ、坂上のゲートを見上げるシーンが難しくなるので怒りを使ってしまってもいい。
  • ほぼ最後、見下ろし視点のシーンだけは少し難しい。 手前側にいる二人を急いで倒す必要があるのと、グラサン兵が立ち上がったら直ぐに倒さないと攻撃される点に注意。 怒りを使ってもいい。
  • ボスのヘリ戦。 やはり弾無限。まずはランダム配置の赤丸×2。 時間的な余裕はかなりあるので、適当に撃たないように。
  • 機関銃破壊。 4つあるうちの2つ破壊すればいい。 どちら側を狙っても、怒りを発動するまでもなく壊せるはず。
  • ミサイル破壊。難しくないと思う。
  • 再びランダム赤丸×2。 これも受付時間はそこそこあるので落ち着いて。
  • 岩落とし。 十分通常弾で破壊できる範囲だが、どうせこの後しばらく怒りは使わないので安全のために怒りを使ってしまってもいい。
  • またまたミサイル破壊。 同じく楽勝。
  • 最後は弓の代わりにロケラン。 やたらと急かされるが実は時間は非常に余裕がある。 出現位置は毎回ランダムなので、早まって撃たないこと。

■4面
3面と違い、ライフを貯めるには多少技術が必要になります。 まぁボス以外はそんなに難しくないので、なんとかなるでしょう。
  • 最初はメタルギアごっこ、もしくはビシバシチャンプ。 敵兵の振り向きパターンはいくつかのパターン中からランダムで選出されるが、開始直後のコンマ数秒のみ通行可能だったり、受付時間が異様に短いパターンがあったりするので、運の要素も大きい。 ここを失敗すると次のイベントも含め計6つも勲章をロスしてしまうので、できるだけ成功させたいところ。
  • 成功すれば、次は理由の説明もなく何故か戦車の下に潜り込む。 赤い判定ラインと、戦車のキャタピラの接地面が重なった瞬間にボタンを押そう。
  • 上記二つのイベントを失敗すると敵に発見される。 初見殺しの難しさはないが、普通に難しめの戦闘なので気合いを入れていこう。
  • 潜入後もメタルギアごっこは続く。 画面上の赤いゲージが最大になってしまってもそれほどきつくなるわけではないが、やはり勲章は貰えなくなるので慎重にいきたい。 敵雑魚兵は全て一発で、またマッチョ兵も一発ずつ腕狙いで撃っていくといい。
  • この潜入中、角を曲がって奥行きのある通路を見るシーンで回復アイテム。 画面奥にある箱なのだが、小さい上に耐久力があるので連射しないと回収できない。 そのシーンに現れる敵兵は全て攻撃が非常に遅いので、敵のゲージが溜まるまでは撃たないで時間を稼ごう。
  • 火炎放射器男戦。 画面の左、右、下の三カ所からランダムに赤丸が3連続で出現する。 受付時間は長めなので、ゆっくり撃てばいい。
  • 基地爆破後、脱出までは勲章入りの箱が多数出現する。 箱が見えたら即撃つぐらいの気持ちでいい。
  • 脱出後半、階段上の手榴弾兵を倒した後、上階の兵を見上げながら移動するシーンに入る。 左側を見上げながら移動するシーンの次、右側を見上げながら移動するシーンの開始直後に、画面右のドラム缶にライフ+2のアイテムがある。 ドラム缶はすぐに見えなくなってしまう上、画面中央にはゲージの溜まりが早いマッチョ兵がいるのでここは要暗記。 ライフが満タンならライフは無視していいが、一つでもライフが減っているならマッチョ兵(1ダメージ)に攻撃される危険を冒してでも取りに行くべき。
  • 最後の最後、周囲の敵を一掃した後に左に振り向くと火炎放射男がいる。 攻撃が早いので画面中央を撃ちっぱなしにしておくといい。
  • 戦車戦。 まずは機銃×2の破壊。 機銃1つあたり1マガジンで十分に壊せるので、無駄なリロードをしないようにしよう。 戦車の機動の関係上、右を先に狙った方が撃ちやすい。
  • 岩×4が2セット。 岩の耐久力は今までと違って非常に低く、5,6発程度で壊せる。 リロードをしてしまうと特に2セット目は厳しいので、1マガジンで無駄撃ちせずに壊そう。
  • ほぼ予告無しの赤丸射撃。 画面左→右の順。 2ダメージなのでちゃんと暗記すること。
  • 2ダメージの主砲攻撃×2。 1発目のゲージが3/4溜まったあたりで怒りを発動すると、ちょうど両方とも阻止できるかも。 2発目は戦車の機動の関係上撃ち込みづらいので、不安なら1発目はギリギリまで引きつけて怒り無敵でスルーするのも手。
  • またもやラストは弓。 まぁ余裕。

■5面
道中は普通に難しいです。 HOLD YOUR FIRE状態になると怒り発動中でも強制的に中断(ゲージが残る)になるため、攻撃がきつくなる各シーンの後半に怒りを発動してしかもゲージを次のシーンに残す、というテクニックを使えば被弾を大幅に減らすことができるでしょう。 あと、最終面なので命中率とか勲章とかどうでもいいです。 ライフもないので、箱は無視しても(最初の一個だけ怒りMAXが入ってたりしますが)いいでしょう。
  • 開始直後、マッチョが3人いるが左のマッチョはしばらく攻撃をしてこない。 右から倒す。
  • 画面右の車と奥からひたすら兵が沸いてくる。 このとき画面右に意識が行きがちだが、画面左から数回攻撃の早い敵兵が沸いてくるのでちゃんと画面全体を見ないといけない。
  • しばらくドライブ。 併走車上のマッチョ兵が何回か出てくるが、うまく急所に当てられないようだったら遠慮なく怒りを使ってしまっていい。
  • 敵増援後。 トラックからゲージが半分溜まった敵兵が次々と降りてくるシーンの後半から、本格的に辛くなってくる。 まずいと思った時に怒りを発動し、次のシーンと併せて無理矢理突破してしまおう。
  • ボス。 最初は赤丸射撃。 戦車の時と同様に、左→右で固定。 右のマーカーは右の本当に端の方に出る。
  • 機銃×4。 怒りを発動しなくても十分間に合うと思うが、無理そうなら使ってしまってもいい。 内側の機銃の方が溜まりが早かったりするので、3,4個目を破壊するときは少し意識してみよう。
  • ミサイル×4が2回。 どちらも3面より難しく、どちらかと言えば2回目の方が難しい。 ちなみに怒りを使える場面はこれが最後なので、余っていたら使ってしまおう。
  • 弓。 いつものように簡単。
  • 砲撃のようなもの。 敵ヘリが画面中央に近づくと濃い緑の四角が現れるので、それが見えた瞬間に撃ってしまえばいい。
と、ここまででクリアです。 ワンコインでクリアーできれば、称号RAMBOもすぐに入手できるでしょう。 がんばってください。

2008年10月10日金曜日

sconsのバグ in vc8, vc9

だいぶ前にバグレポートを出したのですが、
1.0.1でも未だに直っていないようなのでここに書いておきます。

VC8およびVC9でコンパイルをしようとすると、インクルード・ライブラリ・実行ファイルのパスが正しくcl.exeに渡されません。
解決方法は、sconsのインストール先(たいていはpythonのインストールディレクトリの下のどこかのはずです)から見て、/Tools/msvc.pyの223行目(あたり)、
var_name = environment_var_map.get(property_name)

var_name = environment_var_map.get(property_name.value)
に書き換えるだけです。

英語圏でも困っている人が多いようなので以下適当な英語訳 見なかったことにしてください

scons has a bug on platform VC8 and VC9, it cannot detect the paths thosespecified from VC's IDE configuration. (Tools -> Option -> Project and Solution, I only have Japanese edition so menu name might differ, but you would be able to guess what I want to say!)
All you need to do to fix this bug is to append six characters to (Scons-Root)/Tools/msvc.py: line 223,
var_name = environment_var_map.get(property_name)
to
var_name = environment_var_map.get(property_name.value)
Then you can enjoy hi-customizable brilliant make system, scons.

2008年10月2日木曜日

boost::python、embedding(埋め込み)

あまりにも本家のドキュメントが少なく、また日本語で検索してもほとんどひっかかりません。
また、真面目にやろうとするとboost::pythonとPythonについて熟知しなくてはならないようで、
これは意外と手間のかかる作業かもしれません。

一般にboost::pythonは『PythonからC++のコードを呼び出す』という文脈で使われることが多いようですが、
その逆、『C++からPythonを呼び出す』ことも当然サポートしています。
一番簡単な例、要するにC++からPythonで書かれた関数を呼び出して値を返してもらう、
ということのやり方は本家のドキュメントにあるので(それしかないとも言う)、ここでは書きません。
しかし埋め込みを実用的なものにするには、もっと多くの機能が必要で、
それらはboost::python上で実装されているにも関わらずほとんどドキュメントが(英語ですら)ありません。

やりたいことその1は、C++から呼び出したPython上のコードで、
C++で書かれたクラスやenumを使いたい、というような場合です。
embeddingでなければ、これはBOOST_PYTHON_MODULEを使えば難なくできることなのですが、
embeddingでのやり方は今のところドキュメントに記述されていません。

結論から言えば、非embedding時の方法にもう二手間加えることで、
embedding時もこれは容易に可能になります。
手間一つ目は、BOOST_PYTHON_STATIC_LIBを#defineすること。
手間二つ目は、Py_Initialize()する前に、PyImport_AppendInittabでモジュールを登録することです。

後者は少しだけ追加説明が必要でしょうか。
BOOST_PYTHON_MODULE(name)は、init##name()という関数を定義しています。
これをPyImport_AppendInittab関数に渡してやることにより、
はじめてPythonスクリプト内でimportできるようになります。
  int PyImport_AppendInittab( char *name, void (*initfunc)(void)) 


その2に続く?