Archive for 6月, 2010

Oblivion日記 その1

いやぁ~、空気がうまい!
あ、ゲーム内の話だけれども。。。
ちょいと画質調整をしつつ、景観を撮ってみました。



もう眺めが良すぎてサイコ~。

とか言ってたら、アイテムが貯まって貯まってつらくなってきた。
スキル設定を大幅にミスったため、未だレベル2・・・。
で、Imperial Cityのボロ屋を買うことにしたんだけど、ど~にもお金が足りません、と。
あのボロ屋が2000もするなんておかしい!
あの商店街のババァ、いつかぶった切ってやる:P





け、調子の良いババァだぜ。
と言うわけで、一応家を買うことに。
てか、めちゃくちゃスクリーンショット撮ったのに、保存されていないものがある。。
外部のスクリーンショット京アプリが全部動かないし・・・。
Steam版だけ?
まぁ、いっか?





「何者だ?」とか言われても、しがないダークエルフですよとしか言いようがない。

で、コロールにも着いた。

そして愛しのは虫類系アイドル ダ・ルマにも遭遇。

まぁ、既にさらわれているわけですが。。。

とりあえずそんな感じ。
帝都の商店問題も解決したんだけど、スクリーンショットが途切れ途切れで載せる気無くした。。。

そんなかんじ。

Post to Twitter

, ,

No Comments

Visual CのGUIアプリで「出力」ウィンドウへデバッグメッセージを出す

俺、PHPerの頃からの癖で、デバッグメッセージをどうしても出したくなる。
コマンドライン上では普通にprintfではき出せば良いんだけど、GUIとなるとそこに出すのもちょいと面倒だし、メッセージボックスなんてやった日には、メッセージボックスの嵐となる可能性さえ秘めているのは自明。
で、Visual Studioでデバッグすると出力ウィンドウがあります、と。
これを使いたい。
答えを書いちゃうとwindows.hにある、OutputDebugStringA( *str )と言う関数で実現可能です、と。
と言うわけで、dprintfを自作。

// debug.h
bool dprintf( const char *str, ...);
// debug.cpp
#include <windows.h>
#include <stdio.h>
#include <stdarg.h>
#define _DEBUG_OUT_BUFF_SIZE_ 128
bool dprintf( const char *str, ...)
{
char debugOutBuff[ _DEBUG_OUT_BUFF_SIZE_ ];
va_list ap;
va_start( ap, str );
if ( !vsprintf_s( debugOutBuff, _DEBUG_OUT_BUFF_SIZE_, str, ap ) ) {
OutputDebugStringA( "dprintf error." );
return false;
}
OutputDebugStringA( debugOutBuff );
return true;
}

dprintfで「出力」ウィンドウへ出力したところ

まぁ、クソみたいな関数だけど、一応メモ。
使い方はまぁ、printfと同じだと思ってもらえれば。
あと、OutputDebugStringではなく、何故OutputDebugStringAを使っているかというと、「出力」ウィンドウがShift_JISだったからと言う。。。
少なくとも俺の持ってるVisual Studio 2008 Professionalはそうなってた。
OutputDebugStringを指定しておくとプロジェクトがUnicodeを使うように指定されていると、コンパイル時にOutputDebugStringWと言うUnicode版に書き換わってしまって都合が悪いかなぁ、と。
VC2010の「出力」ウィンドウがUnicodeになってるんだったらifdef使うなり拡張はするかも。

そんだけ。

んが、「続・dprintf」に続く。

Microsoft Visual Studio 2010 Professional アカデミック

Microsoft Visual Studio 2010 Professional アカデミック

定価:¥ 13,824

Amazon価格:¥ 97,600

カテゴリ:DVD-ROM

発売日:2010-06-18



プログラミングWindows第5版〈上〉Win32 APIを扱う開発者のための決定版! (Microsoft Programming Series)

著者/訳者:チャールズ ペゾルド

出版社:アスキー( 2000-10 )

定価:¥ 5,378

単行本 ( 790 ページ )

ISBN-10 : 4756136001

ISBN-13 : 9784756136008



プログラミングWindows第5版〈下〉Win32 APIを扱う開発者のための決定版! (Microsoft Programming Series)

著者/訳者:チャールズ ペゾルド

出版社:アスキー( 2000-10 )

定価:¥ 5,616

単行本 ( 739 ページ )

ISBN-10 : 475613601X

ISBN-13 : 9784756136015


Post to Twitter

, , , , ,

No Comments

メモリのアラインメントを確認する

そもそもの話。
なぜ「ゲームプログラマになる前に覚えておきたい技術(以下「セガ本」)」を読んでる途中で「C言語ポインタ完全制覇(以下「ポインタ本」)」を読むことになったか?
それは、セガ本にデータ型のサイズで割りきれるアドレスでデータを読み込まないと、x86系(いわゆるIntel、AMD系)以外のCPUではクラッシュし、x86でもデータを2回読むことになってパフォーマンスが落ちる、と書いてあったから。
で、パッと見て理解できないでいたら、時を同じくしてポインタ本が届き、目次にアラインメントの記述が。
と言うわけで、ポインタ本を読み進めてみた次第。

そこで思ったのが、この本、本当に為になる。
俺みたいなCの見習いの肩もみの家の便所掃除みたいな人間にはいろいろ発見が多すぎて驚く。
例えば

#include <stdio.h>
int main()
{
int i;
char s[] = "abcdefghij";
for ( i = 0; i < sizeof( s ) - 1; ++i ) {
printf( "%d:%c\n", i, i[s] );
}
}

なんてコード。
実行するとこう。

McLaren% gcc -o pointer_test pointer_test.c
McLaren% ./pointer_test
0:a
1:b
2:c
3:d
4:e
5:f
6:g
7:h
8:i
9:j

9行目のi[s]はs[i]の間違いと思いがちだけど、”これでも”問題ない。
出来るか出来ないかの話であって、常識的にこの書き方をして良いかは別の話(そしてもちろんダメ)。
この表記はコンパイル時に

printf( "%d:%c\n", i, *( i + s ) );

と変換しているだけ。
確かにポインタ+数値でそのポインタの型の分だけ先へ進む機能がある。
とまぁ、なかなか興味深い。

さてさて本題。
ようやくアラインメントが書いてあるページまでたどり着いた。
どうやら現代のコンパイラはかなりその辺りも配慮しているらしく、次に置かれるデータがそのデータ型で割り切れない場合、”詰め物”をしてくれるんだとか。
実際コードにして試してみまふ。

// alignment_check.c
#include <stdio.h>
typedef struct {
char ch;
double dn;
short sn;
int nu;
} MyStruct;
int main()
{
MyStruct hoge;
unsigned long gap1, gap2, gap3;
printf( "sizeof char\t%lu\n", sizeof( char ) );
printf( "sizeof double\t%lu\n", sizeof( double ) );
printf( "sizeof short\t%lu\n", sizeof( short ) );
printf( "sizeof int\t%lu\n\n", sizeof( int ) );
printf( "sizeof MyStruct\t%lu\n\n", sizeof( MyStruct ) );
printf( "\t&hoge's hexadecimal memory address.\n" );
printf( "\tname\t\ttype\t\taddress\t\tsize\n" );
printf( "\t&hoge\t\tMyStruct\t%p\t%4lu\n", &hoge, sizeof( hoge ) );
printf( "\t&hoge.ch\tchar\t\t%p\t%4lu\n", &hoge.ch, sizeof( hoge.ch ) );
gap1 = (unsigned long)&hoge.dn -
( (unsigned long)&hoge.ch + sizeof( hoge.ch ) );
printf( "gap1:%lu\n", gap1 );
printf( "\t&hoge.dn\tdouble\t\t%p\t%4lu\n", &hoge.dn, sizeof( hoge.dn ) );
gap2 = (unsigned long)&hoge.sn -
( (unsigned long)&hoge.dn + sizeof( hoge.dn ) );
printf( "gap2:%lu\n", gap2 );
printf( "\t&hoge.sn\tshort\t\t%p\t%4lu\n", &hoge.sn, sizeof( hoge.sn ) );
gap3 = (unsigned long)&hoge.nu -
( (unsigned long)&hoge.sn + sizeof( hoge.sn ) );
printf( "gap3:%lu\n", gap3 );
printf( "\t&hoge.nu\tint\t\t%p\t%4lu\n\n", &hoge.nu, sizeof( hoge.nu ) );
printf( "char + gap1 + double + gap2 + short + gap3 + int = %lu\n\n",
sizeof( char ) + gap1 +
sizeof( double ) + gap2 +
sizeof( short ) + gap3 +
sizeof( int ) );
printf( "&hoge's decimal memory address (with alighnment gap size).\n" );
printf( "\tname\t\ttype\t\taddress\t\tsize\n" );
printf( "\t&hoge\t\tMyStruct\t%ll\t%4lu\n", &hoge, sizeof( hoge ) );
printf( "\t&hoge.ch\tchar\t\t%lu\t%4lu\n", &hoge.ch, sizeof( hoge.ch ) );
printf( "gap1:%lu\n", gap1 );
printf( "\t&hoge.dn\tdouble\t\t%lu\t%4lu\n", &hoge.dn, sizeof( hoge.dn ) );
printf( "gap2:%lu\n", gap2 );
printf( "\t&hoge.sn\tshort\t\t%lu\t%4lu\n", &hoge.sn, sizeof( hoge.sn ) );
printf( "gap3:%lu\n", gap3 );
printf( "\t&hoge.nu\tint\t\t%lu\t%4lu\n", &hoge.nu, sizeof( hoge.nu ) );
return 0;
}

まぁ、こんだけ親切に情報盛ったから、アドレス表記だけで良いとは思ったけど、一応アドレスを10進数にしたやつも記載。
(つっても、64ビット環境においてunsigned long程度でアドレス表示して間に合わない気がするけど、ギャップを目視することが目的だから、あえてこのまま。
あれ?ラップトップのMacでgcc動かしたときって64ビット扱い?
・・・ま、今回は気にしないことに。
どうせテストだし。。。
まともに64ビットアドレス書いてたら、京単位らしいから・・・ね。)

で、結果。

McLaren% gcc -o alignment_check alignment_check.c
alignment_check.c: In function ‘main’:
alignment_check.c:48: warning: format ‘%lu’ expects type ‘long unsigned int’, but argument 2 has type ‘struct MyStruct *’
alignment_check.c:49: warning: format ‘%lu’ expects type ‘long unsigned int’, but argument 2 has type ‘char *’
alignment_check.c:52: warning: format ‘%lu’ expects type ‘long unsigned int’, but argument 2 has type ‘double *’
alignment_check.c:55: warning: format ‘%lu’ expects type ‘long unsigned int’, but argument 2 has type ‘short int *’
alignment_check.c:58: warning: format ‘%lu’ expects type ‘long unsigned int’, but argument 2 has type ‘int *’
McLaren% ./alignment_check
sizeof char     1
sizeof double   8
sizeof short    2
sizeof int      4
sizeof MyStruct 24
&hoge's hexadecimal memory address.
name            type            address         size
&hoge           MyStruct        0x7fff5fbfef10    24
&hoge.ch        char            0x7fff5fbfef10     1
gap1:7
&hoge.dn        double          0x7fff5fbfef18     8
gap2:0
&hoge.sn        short           0x7fff5fbfef20     2
gap3:2
&hoge.nu        int             0x7fff5fbfef24     4
char + gap1 + double + gap2 + short + gap3 + int = 24
&hoge's decimal memory address (with alighnment gap size).
name            type            address         size
&hoge           MyStruct        140734799802128   24
&hoge.ch        char            140734799802128    1
gap1:7
&hoge.dn        double          140734799802136    8
gap2:0
&hoge.sn        short           140734799802144    2
gap3:2
&hoge.nu        int             140734799802148    4

こんな塩梅。
ワーニングは全部アドレスを無理矢理10進数で出したため。
「ポインタ本」と同じように構造体で確認した。
こうすれば普通の処理系では間に別の変数を入れたりする余地はあるまい:-)
で、確かにアドレスを次のメンバ変数のサイズで割り切れない場合、ギャップが出ている。
なるほど、こうすればどのCPUでもスマートに動くというわけですかい。
勉強になった。

C言語ポインタ完全制覇 (標準プログラマーズライブラリ)

著者/訳者:前橋 和弥

出版社:技術評論社( 2001-01 )

定価:¥ 2,462

Amazon価格:¥ 2,462

単行本 ( 323 ページ )

ISBN-10 : 4774111422

ISBN-13 : 9784774111421



ゲームプログラマになる前に覚えておきたい技術

著者/訳者:平山 尚

出版社:秀和システム( 2008-11-14 )

定価:¥ 4,860

Amazon価格:¥ 4,860

単行本 ( 872 ページ )

ISBN-10 : 4798021180

ISBN-13 : 9784798021188


Post to Twitter

, , , ,

No Comments

スタックオーバーフローをテスト

最近、「C言語ポインタ完全制覇 (標準プログラマーズライブラリ)」という本を読んでる。
タイトルの通り、C言語の、それもポインタだけに的を絞った本。
これがなかなかどうして面白くて、文字も大きいのですらすら進んでしまう。
ただ、簡単かと言われれば全く違って、興味深くて考えさせられるような話題ばかり。

ようやく100ページまで進んだ。
そしたらセキュリティーホールの温床になると言うスタックオーバーフローをテストしようという楽しいコードが書いてあった。
で、試したくなるじゃないですか。
若干情報多めに書いて写経してみたのが下記。

// stack_overflow_test.c
#include <stdio.h>
void hello()
{
static int i = 0;
fprintf( stderr, "stderr:\tHello xD\n" );
printf( "\tNo.%d Hello:P\n", i++ );
}
void func()
{
void        *buf[10];
static int  i;
printf( "buf\t%p\n*buf\t%p\n&i\t%p\n&hello\t%p\n\n", buf, *buf, &i, &hello );
for ( i = 0; i < 16; ++i ) {
buf[i] = hello;
printf( "buf[%d]\t%p\n", i, &buf[i] );
}
printf( "\n\tEnd of func()\n\n" );
}
int main()
{
int buf[1000];
printf( "Start\n\n" );
func();
printf( "End\n\n" );
return 0;
}

で、実行するとこう。

% gcc -o stack_overflow_test stack_overflow_test.c
% ./stack_overflow_test
Start
buf     0x7fff5fbfdf20
*buf    0x100000eee
&i      0x10000108c
&hello  0x100000d1c
buf[0]  0x7fff5fbfdf20
buf[1]  0x7fff5fbfdf28
buf[2]  0x7fff5fbfdf30
buf[3]  0x7fff5fbfdf38
buf[4]  0x7fff5fbfdf40
buf[5]  0x7fff5fbfdf48
buf[6]  0x7fff5fbfdf50
buf[7]  0x7fff5fbfdf58
buf[8]  0x7fff5fbfdf60
buf[9]  0x7fff5fbfdf68
buf[10] 0x7fff5fbfdf70
buf[11] 0x7fff5fbfdf78
buf[12] 0x7fff5fbfdf80
buf[13] 0x7fff5fbfdf88
buf[14] 0x7fff5fbfdf90
buf[15] 0x7fff5fbfdf98
End of func()
zsh: segmentation fault  ./stack_overflow_test

あれ~?
hello()が実行されてない・・・??
と言うわけで、落ちる前に一度hello()を呼んでみた。

#include <stdio.h>
void hello()
{
static int i = 0;
fprintf( stderr, "stderr:\tHello xD\n" );
printf( "\tNo.%d Hello:P\n", i++ );
}
void func()
{
void        *buf[10];
static int  i;
printf( "buf\t%p\n*buf\t%p\n&i\t%p\n&hello\t%p\n\n", buf, *buf, &i, &hello );
hello();
for ( i = 0; i < 16; ++i ) {
buf[i] = hello;
printf( "buf[%d]\t%p\n", i, &buf[i] );
}
printf( "\n\tEnd of func()\n\n" );
}
int main()
{
int buf[1000];
printf( "Start\n\n" );
func();
printf( "End\n\n" );
return 0;
}

するとこうなる。

% gcc -o stack_overflow_test stack_overflow_test.c
Start
buf     0x7fff5fbfdf20
*buf    0x100000eee
&i      0x10000108c
&hello  0x100000d10
stderr: Hello xD
No.0 Hello:P
buf[0]  0x7fff5fbfdf20
buf[1]  0x7fff5fbfdf28
buf[2]  0x7fff5fbfdf30
buf[3]  0x7fff5fbfdf38
buf[4]  0x7fff5fbfdf40
buf[5]  0x7fff5fbfdf48
buf[6]  0x7fff5fbfdf50
buf[7]  0x7fff5fbfdf58
buf[8]  0x7fff5fbfdf60
buf[9]  0x7fff5fbfdf68
buf[10] 0x7fff5fbfdf70
buf[11] 0x7fff5fbfdf78
buf[12] 0x7fff5fbfdf80
buf[13] 0x7fff5fbfdf88
buf[14] 0x7fff5fbfdf90
buf[15] 0x7fff5fbfdf98
End of func()
stderr: Hello xD
No.1 Hello:P
stderr: Hello xD
No.2 Hello:P
stderr: Hello xD
No.3 Hello:P
stderr: Hello xD
No.4 Hello:P
stderr: Hello xD
No.5 Hello:P
zsh: segmentation fault  ./stack_overflow_test

これでしっかり動いた。
5回勝手(不正)に実行されちょる。

本の説明によるとメモリの状態は下記のような感じとなるらしい。
–ここ移行に別の変数が追加されていく–
buf[0] 0x7fff5fbfdf20
buf[1] 0x7fff5fbfdf28
buf[2] 0x7fff5fbfdf30
buf[3] 0x7fff5fbfdf38
buf[4] 0x7fff5fbfdf40
buf[5] 0x7fff5fbfdf48
buf[6] 0x7fff5fbfdf50
buf[7] 0x7fff5fbfdf58
buf[8] 0x7fff5fbfdf60
buf[9] 0x7fff5fbfdf68
==他の自動変数==
==関数終了時に戻るアドレス情報など==
==その他の領域==

考察:buf[10]~buf[15]までの6個分余分に配列があると仮定して上がいてます、と(・・アレ?5回しか実行されてない??)。
自動変数を食い破り、呼び出し元の関数情報を破壊して行きます、と。
あ、わかった。。。
funcに自動変数iがあるから1回少ないんだ。
funcをこう変えた。

void func()
{
void        *buf[10];
static int  i;
int a, b, c, d, e; // 追加
printf( "buf\t%p\n*buf\t%p\n&i\t%p\n&hello\t%p\n\n", buf, *buf, &i, &hello );
hello();
for ( i = 0; i < 15; ++i ) {
buf[i] = hello;
printf( "buf[%d]\t%p\n", i, &buf[i] );
}
printf( "\n\tEnd of func()\n\n" );
}

結果はこう。
(ちなみに、ちょっとプログラムいじっちゃったからアドレスと表記が若干違う。。)

Start
&func   0x100000d3f
buf     0x7fff5fbfeea0
*buf    0xffffffffffffffff
&i      0x10000108c
&hello  0x100000cf8
stderr: Hello xD
No.0 Hello:P
buf[0]  0x7fff5fbfeea0
buf[1]  0x7fff5fbfeea8
buf[2]  0x7fff5fbfeeb0
buf[3]  0x7fff5fbfeeb8
buf[4]  0x7fff5fbfeec0
buf[5]  0x7fff5fbfeec8
buf[6]  0x7fff5fbfeed0
buf[7]  0x7fff5fbfeed8
buf[8]  0x7fff5fbfeee0
buf[9]  0x7fff5fbfeee8
buf[10] 0x7fff5fbfeef0
buf[11] 0x7fff5fbfeef8
buf[12] 0x7fff5fbfef00
buf[13] 0x7fff5fbfef08
buf[14] 0x7fff5fbfef10
End of func()
End
zsh: segmentation fault  ./stack_overflow_test

ほら、実行されない。
ただ不思議なことに、

int a;

だけにした場合と、

int a, b, c, d;

までにした場合、

Start
&func   0x100000d3f
buf     0x7fff5fbfeeb0
*buf    0x7365745f776f6c66
&i      0x10000108c
&hello  0x100000cf8
stderr: Hello xD
No.0 Hello:P
buf[0]  0x7fff5fbfeeb0
buf[1]  0x7fff5fbfeeb8
buf[2]  0x7fff5fbfeec0
buf[3]  0x7fff5fbfeec8
buf[4]  0x7fff5fbfeed0
buf[5]  0x7fff5fbfeed8
buf[6]  0x7fff5fbfeee0
buf[7]  0x7fff5fbfeee8
buf[8]  0x7fff5fbfeef0
buf[9]  0x7fff5fbfeef8
buf[10] 0x7fff5fbfef00
buf[11] 0x7fff5fbfef08
buf[12] 0x7fff5fbfef10
buf[13] 0x7fff5fbfef18
buf[14] 0x7fff5fbfef20
End of func()
stderr: Hello xD
No.1 Hello:P
stderr: Hello xD
No.2 Hello:P

となる。
エラーは起きない。
けど変。

結論:戻り先アドレスまで上がいたら、そこにある情報を実行しちゃいました、的な感じの認識。

まぁ、何にせよ、バッファが溢れないように注意しないといつか痛い目見ますよ、と。
精進します。

C言語ポインタ完全制覇 (標準プログラマーズライブラリ)

著者/訳者:前橋 和弥

出版社:技術評論社( 2001-01 )

定価:¥ 2,462

Amazon価格:¥ 2,462

単行本 ( 323 ページ )

ISBN-10 : 4774111422

ISBN-13 : 9784774111421


Post to Twitter

, , , ,

No Comments

今さらPC版のOblivionをはじめる、の巻

洋ゲーファンには欠かせないPCゲーム配信ソフトSteam。
第一弾ソフトのHalf-Life2が欲しくてアカウントは持っているわけ。
とは言え、それ以降特に欲しいソフトもなく、Half-Life2のエピソードばら売りに反感を覚え、そして何よりデスクトップPCがショボ過ぎたために塩漬け状態に。

そんなある日、開発目的のためにグラフィックスボードを入れようと思い立って入れてみたら、Half-Life2もフルオプションで普通に動くし、意外と行けることがわかった。
で、ですよ。
PS3で久々にはまったゲームThe Elder Scrolls IV:Oblivionがあると聞いて早速アクセス。
が、日本アカウントからだと何故か買えないという悲しいお知らせ。
いろいろ調べてブラウザ上から米国アカウントとしてカートに入る。
(http://store.steampowered.com/?cc=us←ここから「oblivion」で検索。)
今度は日本アカウントとしてアクセスしてさらにログインをします、と。
(http://store.steampowered.com/?cc=jp←この画面から右上のログインを押してログイン。アカウント持ってない人はそこで普通に登録して下さい。クレジットカード使うので、変なアカウントだとカードごと止められるかもしれないので、本当に普通に登録して下さいw)
そしてWeb上でお会計を済ませてSteamを起動してダウンロードしたら、なんとなんと、無事に買えました!とさ。
しかも、大特価で大体$24.99。
全部入りのGame of the Year Editionと呼ばれるセットで、パッケージ版には含まれていないDLC(ダウンロード・コンテンツ)込み。
Amazonとかで頼むよりも安い。
しかも即日DL。。

スゴイ時代になりました。
でもねぇ、趣味に充てる時間を削ってまで勉強するため仕事も辞めたのに、これで良いのかと・・・。
Oblivion、マジでやりまくってたんですよ。。。
Xbox360のコントローラーを設定したりもしたけど、やっぱりPC版はキーボード・マウスでやるように出来ているから、結局あきらめることに。
どうせFPSモードでしか遊んでなかったから、大して問題ないんだけどね。

さてさて、肝心のゲーム画面はと言うと、4年前のゲームとは思えない!の一言に尽きる。
逆に今のゲームはもっとすごいんだろうけど、本当に出来が良い。
まぁ、設定に追われてチュートリアルを終わったくらいしかやってないんだけど、それでもPS3より断然綺麗。
360は・・・ちょっとかわいそうに見える。。。
そんくらい綺麗。
と言うわけで、いくつかスクリーンショットでも。

始まり始まり~。


巨大なネズミの死骸。。。


ユリエル・セプティム皇帝


曲者共と交戦中のブレイズ


先へと急ぐご一行


曲者共の屍


甲冑を着た曲者がブレイズに倒され、甲冑の魔法が解ける瞬間


志村!後ろ!


志村・・もとい、皇帝・・・。


シャバは遠いのぅ。


やっとシャバへ。月(?)が異常にでかい。


さて、冒険しますか。

Post to Twitter

, , ,

2 Comments

c++でのファイル読み込みテスト

ゲームプログラマになる前に覚えておきたい技術」を読んでいて、C++のファイル読み込みをやっていた。
Cの時でさえ、そんなにファイルいじったりしていなかったので、ちょっと自分でも書いてみる。
まぁ、写経的なコードになっちゃうんだけれども。

main.cpp

#include <iostream>
using namespace std;
bool readFile( char** buff, int* size, const char* filename );
int main()
{
char *fBuff = 0;
int fSize = 0;
if ( readFile( &fBuff, &fSize, "test_dat.txt" ) ) {
cout.write( fBuff, fSize );
}
delete[] fBuff;
return 0;
}

fileRead.cpp

#include <fstream>
using namespace std;
bool readFile( char** buff, int* size, const char* filename )
{
// 初期化
*buff = 0;
*size = 0;
// ファイルストリームをインスタンス化しつつストリームオープン
ifstream ifs( filename, ios::binary );
// 失敗
if ( !ifs ) { return false; }
ifs.seekg( 0, ifstream::end ); // ファイルストリームを最後まで移動
// 現在の読み込み位置(詰まるところサイズ)を取得
// tellg()はpos_type型を返すので、実体はintでも一応キャスト
*size = static_cast< int >( ifs.tellg() );
ifs.seekg( 0, ifstream::beg );	// ファイルストリームを先頭へ
// メモリ確保
*buff = new char [ *size ];
// ファイルの内容をメモリに読み込む
ifs.read( *buff, *size );
return true;
}

test_dat.txt

Hello.
And say goodbye.

で、結果。

% g++ -o test main.cpp fileRead.cpp
% ./test
Hello.
And say goodbye.

ちなみに、

delete[] *fBuff;

とても、

delete[] &fBuff;

としても怒られた。
ダブルポインタは大本の変数名だけ指定すれば良いんですかい?
メモリリークとかしないのか?
この前紹介した「OpenGLで作るiPhone SDKゲームプログラミング」では

ParticleSystem::~ParticleSystem()
{
int i;
for (i = 0; i < this->amount; ++i) {
delete this->particle[i];
}
delete this->particle;
}

なんてコードがあったから、面倒くさいけど個別に解放しないとリークしちゃうのかと思った。
そうか、その配列内でさらにnewしているから個別に解放しているのか。
そうじゃない場合はそのまま解放して良い、と。
ポインタをもっとよく勉強せねば。。。

そんだけ。

Post to Twitter

, , ,

No Comments

iPhone 4の予約の予約・・・。

うちの近所にあるソフトバンクモバイルのショップ、普段はガラガラなんです。
でも、やっぱ今日は結構人がいて・・・。

こんな感じ。
で、中ではオッサンの怒号が飛び交いつつ、何とか予約の予約が出来ました、と。
とりあえず、サーバがビジーらしく、1人に30分近く時間がかかってしまっているとのこと。
仕方がないから後日やりましょう、と言うことらしい。

店員さん曰く、18日までが初期出荷分と言う話があります、と。
でもって、店にどれくらい割り振られるかは未定です、と。
ただ、全国一斉に始まっています、と。
まぁ、どうなるかわからんけど、とりあえず予約してきますわ。

そんだけ。

Post to Twitter

, , ,

No Comments

dateコマンドを英語で出しつつmkdir

まぁ、小ネタなんだけれども、cygwinでもmacでもちょっとした作業はコマンドラインでやってしまいたいもの。
で、IDEで開発していて「アレ?このコード動くのかな?」と言う時、突然試したくなるのが人の性。
だもんで、忘れないように「年/英語表記月頭三文字_日付/」と言うディレクトリを掘っていたりする。
例えば「~/source/2010/Jun_15」と言った具合。
今まではこれいちいち月の省略形を思い出しつつ日付を見て作成していたと言うものスゴイUNIXらしくないことしてたわけ。

そもそもの原因は

% mkdir `date +"%b_%d"`

が上手く動いてくれなかったことに起因したりする。
その原因はLANGが日本語になっていたから。

% echo $LANG
ja_JP.UTF-8

と言うわけで、一瞬だけLANGをenにすればいいらしい、と。
なので、こんなのを書いてみた。

#!/bin/sh
export LANG=en
mkdir `date +"%b_%d"`

引数とってどこに作るかを設定しても良いかもしれないなぁ、なんて思ったり。
PHPで仕事はしていたけど、PerlやShellは書いたこと無かったりする俺でした。
猛省。

そんだけ。

Post to Twitter

,

No Comments

「OpenGLで作るiPhone SDKゲームプログラミング」が面白かった

OpenGLで作るiPhone SDKゲームプログラミング

著者/訳者:横江 宗太(株式会社パンカク)

出版社:インプレスジャパン( 2009-12-18 )

定価:¥ 3,024

単行本 ( 352 ページ )

ISBN-10 : 4844328085

ISBN-13 : 9784844328087


一言で言うと、この本がとても面白かった。
内容は非常にストレートで、「iPhone向けに簡単なレースゲームを作る」という趣旨の本。
1章がOpenGL ES 1.0を使った2Dの取り扱い。画面への描画。
2章がその応用で「はえたたきゲーム」を作る。

はえたたきゲーム


3章が”パーティクルシステム”と呼ばれる煙などの表現に使われる演出の実装。

パーティクルシステム


4章が「2Dレースゲーム」を作る。

2Dレースゲーム


5章が”衝突判定”の実装。

衝突判定の実装と画面調整


6章が全ての章を応用して「3Dレースゲーム」を作る。

3Dレースゲーム

まず、Objective-CとC++の知識が最低限求められる。
あと、最終章の3Dレースゲームと言ってもそれほどのものを期待してはいけない。
ただ、ゲームの骨組みを組む方法や、画面描画と操作の連携などを学ぶことが出来る。
俺みたいな脳たりんには丁度良い内容となった。

基本的なゲームロジックはC++で実装されているため、そのままではつまらないのでObjective-Cで実装することにした。
これがC++のコードとの対比が出来てなかなか面白かった。
実際問題、C++を前提に書いてあるので付け焼き刃な俺のObjective-C知識ではなかなか無駄な処理が出まくっているのはわかっているのだけれども、それでもやって良かったと思う。
書店で見かけたら、ちょっと目を通してみるのもいいかもしれない。
これだけでゲームは作れないけど、本当に良いきっかけを作ってくれると思う。

ちなみに、上記のゲーム画像はアセットこそお借りしたものの、ソースコードは写経+Objective-Cで書き直したものをiPhone 3G上で実際に動かしたもののスクリーンショット。
一応この程度のものは出来る。

また、Windows用になってしまうけれど、この本の冒頭に書いてある参考文献である「ゲームプログラマになる前に覚えておきたい技術」をこの本の次に読むといい気がしてきた。
実は「ゲームプログラマになる前に~」も持ってはいるものの、なかなか読み進められないでいた。
けど、今回の「OpenGLで作る~」を読んでからなんとなく進められるようになってきた。
基本的に本に書かれているコードは執筆時のいずれかの段階のコードなので、実は動かないものも多いけど、ソースコードに当たれば問題ないレベル。
徐々にステップアップして行くには良いかなぁ、と自分に言い聞かせつつ読み進めてまふ。
参考までに。

ゲームプログラマになる前に覚えておきたい技術

著者/訳者:平山 尚

出版社:秀和システム( 2008-11-14 )

定価:¥ 4,860

Amazon価格:¥ 4,860

単行本 ( 872 ページ )

ISBN-10 : 4798021180

ISBN-13 : 9784798021188


そんだけ。

Post to Twitter

, , , , ,

No Comments