2008年02月26日

XMLを使ってみる

マップやキャラクターのデータを読み込むのに、今まではタブと改行で区切ったテキストファイル(作成は手打ち)を使ってきた。

だが、この方法だとちょっとしたミスでエラーが起こるし、読み込み時の処理も煩雑だ(正規表現やSplitを多用している)。

で。そうしたデータの読み書きにXMLを使うことにした。.NET Frameworkは当然XMLの使用を想定しているので、読み書きは非常にラクだ。読み書きに必要なデータをpublicで持ったクラスを使えば、System.Xml.Serialization.XmlSerializerで読み書きができる。データの視認性が高いので確認するのもラク。暗号化もできそうだしね。

これなら、データの増減や形式の変更があっても、最低限のコード変更ですむ。今までテキストファイルでやってきたのを書き換えるのが面倒だけど、しかたないか。

※ただ、この場合手打ちでデータを作るのは非常に面倒になるので、CSVかなんかから、このデータ読み書き用クラスに入れて、XML書きだしというのが現実的か。

参考:【C#】DOBON.NET .NET Tips - オブジェクトの内容をXMLファイルに保存、復元する
posted by ラボ長 at 05:45| Comment(1) | TrackBack(0) | プログラミング | このブログの読者になる | 更新情報をチェックする

2008年02月08日

開発に便利なツールたち

今回の開発でお世話になっているツールたちを紹介します。つか統合開発環境(Microsoft Visual C# 2005 Express Edition)やSDK(DirectX SDKやYaneSDK.NET)も含めて全部フリーって、凄い時代になったもんだ。

・ドット絵描きツール「EDGE
主に256色でのドット絵描きに必要な機能を多数備えた良ソフト。多機能だけど使い方は平易。アニメーションもでき、アニメーションデータを保存したファイルはテキストなので、コンバータを作ればそのままゲームに流用できる。PNGの読み書き可。
高機能版「EDGE2」もシェアウェアであり。

・マップエディタ「Platinum
マップエディタなんて作らないかんやろと思ってたら、こんな素晴らしいソフトがあるのね。マップチップを集めた画像を読み込んで、マウスで配置。レイヤーも重ねられる(透過色あり)し、出力形式も1枚絵のBMPのほか、チップの番号で示したCSV、独自のバイナリ形式(C++で読み込むサンプルコード付き)と、使いやすい。難をいうなら、PNGの読み書き、作業途中でのbit数の変更、特定レイヤのCSV出力ができないことか。

・バックアップツール「copix
lifeは、私の開発したソフトのなかではかなり大規模な部類に入るので、万が一にも消えたり破損したら泣きます。なので、バックアップツールを探してみて、圧縮して世代管理が出来てフリー、というのがこれしか無さそうだったのでこれに。圧縮にしても、わざわざ日付別のフォルダ作るのがちょっとなー、という感じですが、まあ便利。

・キャプチャソフト「Capture STAFF -Light-

普段、キャプチャソフトはあんまり使わなんですが、基本ドット絵で、DirectX使ったソフト開発となると、描画の確認に必要です。普通のPrintScreenじゃDirectXで描画したのが撮れないからね。さすがに定番だけあって便利です。
拡大とスクロールがもうちょっとやりやすいといいけど、まあ、用途外だろうなあ。

posted by ラボ長 at 10:44| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

背景描画をチップの配置にしてみたものの・・・

今まで、背景は大きな(512×512ピクセル程度)テクスチャ一枚で持ち、描画の際にテクスチャ座標を指定して切り出していたのだが、さすがにメモリの無駄使いだろうし、背景のアニメーションなんかをするのにも難しい、何より横着しすぎだろうということで、16×16ピクセルのマップチップを持ち、配置する事にした。

16×16ピクセルのチップを敷き詰めるのに、GDI+のDrawImageでは遅いだろうし、テクスチャ変換にも時間がかかるだろうから、それぞれのチップを1つづつテクスチャにし、1チップを1つの四角形に配置する事とした。

画面の大きさは256×224ピクセルで、スクロールのことも考えて17×15=255の四角形を配置し、適宜テクスチャを貼ってみた。

が。
遅い。

それまで余裕で60fpsを叩き出していたのに、50fpsくらいまで落ちる時もある。しかも、このあと背景だけでなく、前景やそれぞれのレイヤーを追加するつもりだったのだ。しかし、ためしにもう1枚同じ背景を重ねてみると・・・。

・・・えらい遅い。

なんと最大で30fpsまで落ちてしまった。これではつかいものにならない。うーむ、こまった。

どっかで、Direct3Dの描画はDraw〜という名前のメソッドを呼び出す回数をなるべく少なくするのが高速化のカギだときいた。今回は、頂点を共有しない四角形を500以上描画したのがまずかったのか。3Dバリバリのゲームにくらべれば圧倒的に少ないと思うんだけど、まあ、その場合でも60fpsは厳しいのか。

ということで、結局、背景は大きなテクスチャで持つ事にした。2枚重ねてみても60fps維持できるし。背景のアニメーションが必要ならキャラクターと同じ様な扱い(描画範囲内にあるときだけ描画)にすればよかろう。
posted by ラボ長 at 10:16| Comment(0) | TrackBack(0) | プログラミング | このブログの読者になる | 更新情報をチェックする

Direct3Dでテクスチャとポリゴンの色の合成方法を変更する

キャラクタを白っぽくするエフェクトを作ろうとして、キャラクタのテクスチャを貼っているポリゴンの頂点の色を変えてみたのだが、標準では真っ白(255,255,255,255)にしたときにテクスチャの色がそのまま出てくるようになっていて、それ以上白くする事はできない。

そこで、いろいろ調べてみたら、テクスチャとポリゴンの色の合成方法を変更する方法があった。

//テクスチャとポリゴンの色を乗算合成する(標準)
//deviceはDirect3Dデバイス
device.SetTextureStageState(0, TextureStageStates.ColorOperation,
(int)Microsoft.DirectX.Direct3D.TextureOperation.Modulate);

//テクスチャとポリゴンの色を加算合成する
device.SetTextureStageState(0, TextureStageStates.ColorOperation,
(int)Microsoft.DirectX.Direct3D.TextureOperation.Add);

これを、DrawPrimitivesなどの前に記述すれば合成方法が変わる。lifeでは、各キャラクターオブジェクトに合成方法をプロパティとして持たせ、Modulate以外なら描画前に変更、描画後Modulateに戻す、とした。

PenzSDK20080208.cs
posted by ラボ長 at 09:55| Comment(0) | TrackBack(0) | プログラミング | このブログの読者になる | 更新情報をチェックする

2008年02月05日

Direct3Dでテクスチャのロードを速くする

描画関係をDirec3Dでやるようになってすぐ、プログラムの起動が異様に遅くなった。調べてみるとBitmapからテクスチャを生成する際にえらく時間がかかっていた。うちの環境では512x512のテクスチャ生成するのに40秒以上かかる。Bitmapのコンストラクタや、Graphics.DrawImageでも一瞬で終わるのに・・・。

調べてみると、やっぱりTexture.FromBitmapはあまりにも遅いとの評判だった(内部的にはGDI+のGetPixel→SetPixelをやってるとか。あほか。)。で、じゃあどうやって速くすんねんということで・・・。

ビットマップからテクスチャーを作る-山に生きる
http://d.hatena.ne.jp/pmoky/20040811


↑を参考にさしてもらって、SurfaceからGraphicsを取得し、DrawImageで描画。おお!速い!けど、アルファ入りのフォーマット扱えないのは辛いなあ・・・。

ということで、同じ記事のNyaRuRu氏のコメントを参考に、Bitmap.LockBitsとTexture.LockRectangleを使って、データ丸写しという危ない橋を渡る事に・・・。

以下、Bitmapを元にテクスチャを生成するメソッド。

//テクスチャ読み込みメソッド
Texture LoadTexture(Bitmap src)
{

//Direct3Dのテクスチャの幅・高さは2の累乗でないといけないので、
//元となるBitmapが収まるテクスチャサイズを算出。
int h = 1;
int w = 1;
while (w < src.Width) { w *= 2; }
while (h < src.Height) { h *= 2; }
width = w;
height = h;

//サイズを考慮したBitmapに移す
Bitmap bmp = new Bitmap(w, h);
Graphics g = Graphics.FromImage(bmp);
g.Clear(Color.Transparent);
g.DrawImage(src, 0, 0);
g.Dispose();

//空のテクスチャ用意
Texture tex = new Texture(dev,w,h,0,Usage.Dynamic,Format.A8R8G8B8,Pool.Default);

//上記テクスチャをロック
//Bitmapのデータとタテヨコが逆になってるようなのでHeight、Widthの順
SurfaceDescription desc = tex.GetLevelDescription(0);
UInt32[,] buf = (UInt32[,])tex.LockRectangle(typeof(UInt32), 0,
LockFlags.None, desc.Height, desc.Width);

//元となるBitmapをロックしてbyteの配列に移す
BitmapData bmpdata = bmp.LockBits(new Rectangle(0,0,w , h),ImageLockMode.ReadWrite,PixelFormat.Format32bppArgb);
IntPtr ptr = bmpdata.Scan0;
byte[] temp = new byte[bmpdata.Width * bmpdata.Height * 4];
Marshal.Copy(ptr,temp,0,bmpdata.Width * bmpdata.Height * 4);
//データ取得できたのでBitmapアンロック
bmp.UnlockBits(bmpdata);

//取得したBitmapのデータをテクスチャに移す
for (int y = 0; y <= bmpdata.Height - 1; y++)
{
for (int x = 0; x <= bmpdata.Width - 1; x++)
{
//Byte×4をUInt32×1にしつつ、
//タテ・ヨコを逆にしてコピーしていく
buf[y,x] = (UInt32)temp[y * bmpdata.Width * 4 + x * 4]
+ (UInt32)temp[y * bmpdata.Width * 4 + x * 4 + 1] * 256
+ (UInt32)temp[y * bmpdata.Width * 4 + x * 4 + 2] * 65536
+ (UInt32)temp[y * bmpdata.Width * 4 + x * 4 + 3] * 256 * 65536;
}
}

//テクスチャをアンロック
tex.UnlockRectangle(0);

return tex;
}

例外処理とか一切無いので注意。
なお、昨日アップしたファイルでは、サイズの変更が片手落ちだったので、新しいのをアップしときます。

PenzSDK20080205.cs
posted by ラボ長 at 23:52| Comment(0) | TrackBack(0) | プログラミング | このブログの読者になる | 更新情報をチェックする

2008年02月04日

PenzSDK

DirectInput調べたり、FPSタイマー作ってみたりしたけど、やっぱりYaneSDKが使いやすかったので、結局以下のように。

画像・音まわり:DirectX9のManaged DirectX
入力とFPSタイマー:Yanesdk.NET

で、Managed DirectXは使いやすいようにクラス作って使ってます。
せっかくなのでSDKきどりで「PenzSDK」と命名。
構成は以下の通り

・PenzDraw
描画用クラス。主に2Dだが3Dも一部あつかう。
テクスチャ格納クラスPenzTextureと複数テクスチャ格納クラスPenzTuxturesを内包。
Bitmapからの(比較的)高速なテクスチャ生成(PenzTexture.LoadTexture)と、傾いた正方形でテクスチャの描画範囲を取得できる(PenzDraw.GetSquare)あたりが売り。

・PenzSound
音楽再生用クラス。このクラス自体はほとんど意味なかったりする。
BGM用としてストリーム再生可能なPenzStreamSoundPlayerと、効果音用として単純な再生機能を持つPenzSoundPlayerを内包。
PenzStreamSoundPlayerはループで戻る箇所をフレーム単位か秒(float)で指定できるので便利。

ほぼ「life」で使う機能しかないので、汎用性はかなり低いですが、参考にしたいという方もいるかもなので、アップしておきます。

PenzSDK.cs(2008/02/04版)

そのまま使う場合は、プロジェクトに追加して、使うクラスの冒頭に「using PenzSDK;」を追加して下さい。
今後もガシガシ変更予定なので、気が向いたらまたアップします。

posted by ラボ長 at 04:35| Comment(0) | TrackBack(0) | プログラミング | このブログの読者になる | 更新情報をチェックする

2008年02月03日

Direct3Dで2D描画する際のテクスチャずれ

理由はわからんですが。

Direct3Dでテクスチャの一部分を描画(正確には頂点のテクスチャ座標に0、1以外の数値を設定した)しようとすると、なんかズレる。

ネットで調べてみると「描画が0.5ドットずれる」という記述をよく見かける。試しに描画部分を0.5ドットづつ広げてみると、問題なく描画できる模様。

ようわからんなあ。
posted by ラボ長 at 20:55| Comment(0) | TrackBack(0) | プログラミング | このブログの読者になる | 更新情報をチェックする

参考資料

今までのところで参考にさしてもらった主なサイト様。

C# によるプログラミング入門
http://ufcpp.net/study/csharp/

入門、でも中身はしっかりしてる。

@IT:連載 改訂版 C#入門
http://www.atmarkit.co.jp/fdotnet/csharp_abc2/index/index.html

ほか、@ITの記事。
上記の入門より少し難しめ。リファレンス的に使用。

C#でゲームプログラム講座
http://www.clks.jp/csg/

Managed DirectXの使い方。Direct3Dによる2D描画は丁寧でとても助かった。DirectInputとFPSタイマーの作り方も参考に。

Managed DirectX
http://sorceryforce.com/programing/mdx/

Managed DirectXのDirect3Dによる3D描画について参考。わかりやすい。

C#でDirectSoundのストリーム再生 - WonderRabbitProject
http://wonderrabbitproject.or.tp/diarypro/archives/94.html

独力では絶対しなかったであろうストリーム再生。ちょっと手を加えて、任意の箇所へループで戻れるようにして使用。

s.h.log: ManagedDirectXでJoystickを使う
http://web.sfc.keio.ac.jp/~shokai/archives/2005/10/manageddirectxj.html

そのまま。でもまだちゃんと試してません。

なんか、昔に比べて開発環境も情報も多くてありがたいですな。
posted by ラボ長 at 08:01| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

life(仮)開発日誌 事始め

こんにちは。ペンギンラボのラボ長です。
このブログはペンギンラボ初のゲーム開発プロジェクト「life(仮)」の開発日誌です。1月初旬から開発を始めて、もう頭がパンクしそうなので、作業記録&備忘録として日誌を書く事にしました。

とりあえず、これまでの経緯。
(長いです。要はC# + Managed DirectXで開発することに落ち着いた、という話)



1月初旬、兄より「ゲーム開発するのにいいプログラミング言語は何か」と聞かれる。とりあえず使い慣れたVB.NETで、ちょっとしたデモを作ってみる。が、兄の構想は大きく、いっちょ本格的に作ってみるか!という事になる。



始めに作ったデモではGDI+を使って描画していたので、すぐに描画速度の限界が来た。YaneSDKの存在を知っていたので調べてみると、なかなか良さそうなので使ってみる事に。YaneSDK.NET自体C#で書かれているので、思い切ってC#に乗り換える。C#はおろかCもC++もほとんど触った事無かったが、VB.NETと殆ど変わらなかったので、ほとんど問題なし。



兄:ドット絵、企画、作曲
私:プログラミング、企画協力、作曲
という感じで作業がすすむ。



せっかく作曲したので、BGMとして流してみるも、ループがひどい。
ループで戻る箇所を指定できないのはもちろん、ループで戻る際のタイムラグが無視できない。むむむ。



YaneSDKのTexturesの扱いがどうも好きになれなかったこともあり、別のSDKがないか探す。Seleneというのが良さそうだったが、なんかめんどくさそうで挫折。結局、ソフトテルミンのコードを流用して、DirectSoundで音楽を鳴らしてみる。



DirectSoundでの音楽再生は充分満足できたので、これでOK。しかし、新たな問題が。「life」はスーパーファミコンみたいなグラフィックを意識しているので画面が小さい(256*224)。そのため、プレイ時にはタテヨコ2倍くらいで表示したいのだが、やってみるとどうもぼやっとしている(ニアレストネイバーで補間される)。ドット絵の魅力を活かすためにもっと単純に拡大してほしいのに・・・。



調べてみるとGlTexture.GlobalOption.Smooth = false;で単純に拡大(バイリニア補間)できるようになるみたい。でも、ならない。と、思ったら別のPCならできた。どうやらビデオカードのOpenGLへの対応具合によるらしい。むむむ。



どうもうまく拡大できないのが気に入らないので、DirectXでやってみようと思い立つ。DirectX9からはManaged DirectXつうのがあって、VB.NETやC#から簡単に使えるらしいのでやってみる。おお!たしかに簡単!テクスチャの補間方法も以下の文でバイリニア補間にできたので、描画まわりもDirectXに移行。
//deviceはDirect3Dデバイス
device.SamplerState[0].MagFilter = TextureFilter.Point;
device.SamplerState[0].MinFilter = TextureFilter.Point;



現在、DirectXを使ったコードに書き直し中&コード整理中。




細かい部分・再利用できそうな部分に関してはまた別の記事で。

posted by ラボ長 at 07:44| Comment(0) | TrackBack(0) | 日記 | このブログの読者になる | 更新情報をチェックする

広告


この広告は60日以上更新がないブログに表示がされております。

以下のいずれかの方法で非表示にすることが可能です。

・記事の投稿、編集をおこなう
・マイブログの【設定】 > 【広告設定】 より、「60日間更新が無い場合」 の 「広告を表示しない」にチェックを入れて保存する。