Posts Tagged ‘ バグつぶし

RenderTarget2D.GetTexture()は同じアドレスを返す

RenderTarget2D.GetTexture()した結果を配列や二つの変数に代入し、あとからそのRenderTarget2Dをいじくり回すと両者が同じになるということについてです。

何のこっちゃさっぱりって人は、こちらのサンプルをどうぞ。XNA3.0で作成しています。

操作方法
左シフト->レンダリングターゲットからテクスチャを取得し左側のテクスチャに代入する。
右シフト->レンダリングターゲットからテクスチャを取得し右側のテクスチャに代入する。
そうするとソース上では片方しか描き換えてないのに、 両方書き換わってしまう。

私は最初これと同じようなことをしていて、この現象に出合い混乱して乱数クラスが狂ったのかと思いました。でもデバッガで追ってくと そうじゃなかったですね。ちゃんと乱数になってましたし、代入してるのも変数一つでした。で、ふと思いついたのが「ポインタ」って言葉。もしGetTexture()で取得できるオブジェクトのアドレスが同じならつじつまが通る…!

確かめてみようと思ってunsafeコード書いてみましたが、どうやら値型のアドレスは取得できても参照型のアドレスは取得できないようで、断念。

で、どうするか。下のような感じでディープコピーしてやればOKです。

GraphicsDevice.SetRenderTarget(0, null);
Texture2D newTex = new Texture2D(GraphicsDevice, tex1.Width, tex1.Height);
Color[] data = new Color[tex1.Width * tex1.Height];
target.GetTexture().GetData(data);
newTex.SetData(data);
tex1 = newTex;

ただひとつ問題なのがこの記事で検証されているようにXBOX360上ではGetData()/SetData()がパフォーマンスにかなり影響を与えるようです。特にGetData()が。今のところこれに対する対策は見つかってません…。描画処理をGPU上で全部やって最終的にテクスチャをもらうということぐらいしか思いつきません。ただそれだとfxファイルを書かなければならないですし、SpriteBatchなどで複雑な描画をしていた場合はとGPUには不向きかと。

うが~~~~!!!
XBOXでゲーム作りたいです…。

2009-12-16 01:18:49追記。

簡単な話でしたね。GetTexture()する数だけRenderTarget2Dを作ればいいんですね。
なぜ気がつかなかった!???


疲れてきてるな流石に…

手のひらツールのバグ修正

以前から気になっていた、手のひらツールを使っているときに全くマウスを動かさなくても画面がブルブル振動するバグを修正しました。

無理やり修正するために5で乗算して除算していたのが(つまり5ピクセル単位で移動するってこと)ピクセル単位になったのでスムーズです。
やっぱり分からないバグも時間がたてばわかるようになるものですね。

続きを読む

無理矢理バグフィックス

もうなんだか高速で描画すると線が途中で途切れる問題を放っておきたくない気分になったので無理矢理解決しました。

バグをよく観察するとなぜかみんな更新範囲を周囲1タイルづつ増やせば解決しそうでした。なのであんまり納得できませんが、ファインダーの大きさだけ更新範囲にを増やすことによって解決しました。
パレッドで選択したチップが一つだけなら更新範囲にほとんどの場合は無駄はないのですが、グループで選択した状態(ドラッグでチップを選択)だと更新範囲に無駄ができます。

追記に修正後の動画を載せときます。

続きを読む

フローティング領域の移動を完成

そこまでできたら貼り付け完成させろよ!ってぐらい中途半端ですが、テストが近いので自粛中と言うことでご理解願います。

いまだに、マップに描画するときに高速で描画すると線が途中で途切れますがこのフローティング領域を移動するときは高速に移動しても処理落ちで移動できなくなるということはおきません。時間があったらぜひこれをヒントに修正してみたいなぁと思ってます。

bool xok = (nowMouse.X / CHIP_SIZE >= pasete_point.X / CHIP_SIZE - 1 &&
nowMouse.X / CHIP_SIZE <= (pasete_point.X + clipboard.Widht * CHIP_SIZE - 1) / CHIP_SIZE) ||
(nowMouse.X / CHIP_SIZE >= pasete_point.X / CHIP_SIZE &&
nowMouse.X / CHIP_SIZE <= (pasete_point.X + clipboard.Widht * CHIP_SIZE) / CHIP_SIZE);

bool yok = (nowMouse.Y / CHIP_SIZE >= pasete_point.Y / CHIP_SIZE - 1 &&
nowMouse.Y / CHIP_SIZE <= (pasete_point.Y + clipboard.Height * CHIP_SIZE) / CHIP_SIZE - 1) ||
(nowMouse.Y / CHIP_SIZE >= pasete_point.Y / CHIP_SIZE &&
 nowMouse.Y / CHIP_SIZE <= (pasete_point.Y + clipboard.Height * CHIP_SIZE) / CHIP_SIZE);

if(!isPermitMoveFloatArea)
    isPermitMoveFloatArea = xok && yok;

if (isPermitMoveFloatArea)
{
    //貼り付ける領域を移動
    pasete_point.X += (nowMouse.X / CHIP_SIZE - lastMouse.X / CHIP_SIZE) * CHIP_SIZE;
    pasete_point.Y += (nowMouse.Y / CHIP_SIZE - lastMouse.Y / CHIP_SIZE) * CHIP_SIZE;
}

これをマウスが動いたときに実行するだけ。条件式が若干複雑なだけでとくにむずかしいことはないけど、できたときなんかうれしかった。あとは、マウスボタンがUPした時点でisPermitMoveFloatArea=false;にするだけです。


2009-12-01 ひっそりと追記。

テストが近いので一応「自粛」という形で触れないでいましたが、コピペを完成させました。

あとは、オートタイルの更新禁止かな。



続きを読む

虫つぶし

やっぱり、ブログだもん。twitterでもつぶやくけどバグつぶししたらこっちにも書こう。

今日つぶしたバグはマップを新規作成すると、一度マウスがコントロールに入って出ていかない限りタブの切り替え部分でもマウス操作ができてしまうというもの。原因は少しでも急激にマウスを動かしたときに処理落ちでマップがきれいに、描けないことを防ごうとしてTimerをつかって入力を受け付けたことによるもので、コンストラクタで問答無用にTimer.Enable=true;にしていたからでした。

対策として、MapEditorクラスにpublicでstaticなActiveEditorというGUIDとインスタンスごとにわけたGUIDフィールドを作成しました。そしてコンストラクタでActiveEditorとインスタンスごとにわけたGUIDが等しいかを比較してタイマーの有効・無効を決めるようにしました。ActiveEditorはMainFormにいじらせてます。


あんまりpublicでstaticな変数は作りたくないのですが、ほかの方法も思いつかず。