掲示板

No title

  • 記事番号: 351
  • 投稿者: Kattiedrask
  • 投稿時間: 2017/12/23 (Sat) 07:06
<a href=></a>
<a href=></a>
<a href=></a>
<a href=></a>


<a href=></a>
<a href=></a>
<a href=></a>
<a href=></a>


<a href=></a>
<a href=></a>
<a href=></a>
<a href=></a>


<a href=></a>
<a href=></a>
<a href=></a>

DXRuby Wikiが表示されないよう...

  • 記事番号: 349
  • 投稿者: mieki256
  • 投稿時間: 2016/02/26 (Fri) 10:26
お世話になっております。mieki256です。

DXRuby Wikiが、ここ数日、
Internal Server Error を返し続けてるように見えるのですが…
気のせいでしょうか…?

Re: DXRuby Wikiが表示されない...

  • 記事番号: 350
  • 投稿者: mirichi
  • 投稿時間: 2016/02/28 (Sun) 23:18
はい、こちらでも確認しております。
OSDNがWebサーバの設定を変えたタイミングでそうなったような気は(タイミング的に)してるのですが、実際のところよくわからんとです。。。
PHP製の掲示板のほうは動いているのでRuby製のWikiだけの問題であり、つまり「アプリの問題だろ」って言われてしまえばそれまでというか。
動かないと実際困るので何か対策を考えるにしても、どうしたらいいものかと悩んでおります。
選択肢としてはGithubのWikiにするとか。そもそもリポジトリをGithubにしたいというのもあって。
何をするにしてもすぐにできるわけでもなく、緊急回避策的なものも思いつかず・・・。
ようするに困り果てている感じです。ふむー

バグ?報告

  • 記事番号: 346
  • 投稿者: はじめました太郎
  • 投稿時間: 2015/11/25 (Wed) 02:35
お世話になります、は太郎です。

2ケース報告させて頂きます。

1)フルスクリーンモードからウィンドウモードに戻すと、トップモストが残ります。
2)ウィンドウの外で mouse release イベントが正しく取得できません。

1)に関しては下記のコードで対応は可能でした。が、flagなどの前後関係はかなり適当です。
SetWindowPos(hWnd, HWND_NOTOPMOST, x, y, w, h, SWP_NOSIZE | SWP_SHOWWINDOW)

2)に関してはドラッグの話でして、GetKeyState使ってる故に取れていないって感じの話です。
ウィンドウ外でmouse release後、ウィンドウ領域内にカーソルが戻って初めてイベントがアプリ側に届きます。
別にエラーとかに繋がる話ではないのでいいのですが、正確なドラッグには必要かと思いました。
因みにHook使ってアプリ側でやろうとffi経由でアプローチしてみましたが流石に不毛かなと止めました。

添付のzipファイルに二つの再現ファイル(coding: utf-8)を梱包しました。
ここの所、立て続けで申し訳ありませんが、ご確認の程よろしくお願い致します。

環境は以下です。

Windows 7(x64) # <= 忘れてました。
Object::RUBY_PLATFORM # => i386-mingw32
Object::RUBY_VERSION # => 2.1.7
DXRuby::VERSION # => 1.4.2 および 1.5.19dev で検証

以上。

Re: バグ?報告

  • 記事番号: 347
  • 投稿者: mirichi
  • 投稿時間: 2015/11/25 (Wed) 22:34
きわどい指摘をありがとうございます。
1)は確かにNOTOPMOSTが必要ですね。普段使わないので気づきませんでした。
2)はウィンドウの外まで意識したことがほとんど無かったのでこれまた気づきませんでした。
マウスまわりの操作はWindowsアプリ的な話になってくるのでゲームとはまた違いますが、こういうのはウィンドウメッセージを使うようにしたほうがよさげですかね。

Re: バグ?報告

  • 記事番号: 348
  • 投稿者: はじめました太郎
  • 投稿時間: 2015/11/26 (Thu) 00:10
夜分遅くすいません。

2)に関してですが、ウィンドウメッセージを使って拾って頂けると助かります。

実装のイメージですが、
例えば、WM_LBUTTONDOWNの時にSetCapture(HWND)を行い、
WM_LBUTTONUPの時にReleaseCapture(VOID)してやれば、最小限で済むかと思われます。

DirectInputはドライバレベル故に早いですが、OSレベルのウィンドウの概念には弱いです。
フルスクリーン前提のゲームなら問題ないですが、大抵の場合、
Windowモードもサポートされてますので、結局、併用する形になるかと思います。

今時のPCゲームでフルスクリーン前提のゲームってのは中々ないのではないかと思います。
それにDXRuby開発版ではRenderTarget#image.regenerate_procがありますので、
従来より高速な描画が可能になってますので、ウィンドウモードも全然いけてると思います。

こんな感じの精度でこれからも何かしら報告を上げさせて頂く事があるかと思いますが、
日々忙しい事と存じますので、掲示板での回答含め、適当に対応して頂ければと思っております。

以上です。

DXRubyWSにおけるWindow.ox/oyと...

  • 記事番号: 335
  • 投稿者: はじめました太郎
  • 投稿時間: 2015/11/21 (Sat) 16:15
はじめまして、はじめました太郎と申します。DXRuby(&WS)を楽しく使わせて頂いております。

件の内容ですが、Window.ox/oy指定時にDXRubyWSにおけるcollisionが正しく機能していません。

理由は簡単で、Sprite#collisionがSprite#x/yからの相対という仕様に依存しているからです。

WSContainerBase#find_hit_object()の中で利用している@hit_cursorと同じように、
imageを持たないSpriteオブジェクトを用意し、これに対して判定を行ってやれば機能しますが、
正直これが「今後GUIも視野に入れた場合の」Spriteの設計上いいのか悪いのか、
という話にまで及びそうなので、一応の報告をさせて頂こうと思いました。

実は今、WSのソースを参考に自作ゲーに最適化させたものを作ってまして、
そこで色々と動かしてみた所、判明した次第です。以上です。

Re: DXRubyWSにおけるWindow.ox/...

  • 記事番号: 336
  • 投稿者: mirichi
  • 投稿時間: 2015/11/21 (Sat) 21:07
いらはりませ。報告ありがとうございます。

Spriteの衝突判定や描画の処理では、Sprite#targetに指定されているオブジェクトのox/oyを取得して座標を補正するようになっています。targetがnilの場合はWindowから取得します。
んで、WSでは最上位のWS.desktopからの相対座標を加算していって絶対座標を作るので、理屈としてはWindow.ox/oyの設定で誤動作することは無いと思ってはいるのですが、
なにぶんそのあたり(LightContainerまわり)は試行錯誤したところなので、たとえばWindow.ox/oyを設定すると2重に補正される、などといったバグが潜んでいたりするかもしれません。これはありそうですね。
おそらくですがDXRubyのSpriteの不具合ではなくWS側の問題でしょう。

一応、LightContainerのもっとシンプルな回答としてViewport機能を作れないかと考えてはいるのですが、これもまだ実装に取り掛かれる段階でもないので、現状ではimageを持たないSpriteを保持するなどといった回避策で行くか、原因を追究して直すか、と言う感じですが、回避するほうが現実的な気がします。
何かしら小さいコードで再現させられるものを提供していただければ調べてみます。

自作ゲー応援してます。公開されるならもれなく遊ばせて頂きます。

Re: DXRubyWSにおけるWindow.ox/...

  • 記事番号: 337
  • 投稿者: はじめました太郎
  • 投稿時間: 2015/11/22 (Sun) 00:31
早速の返信、恐縮です。

私が投稿した後に色々と試してみてたのですが、すいません根本的な問題のようです…

残念ながら、Sprite.checkおよびSprite#checkにおいてSprite#target.ox/oyが機能していない、という話です。
DXRubyWSは関係なかったですorz

返信いただいた内容のまさにここの仕様の話になります。
> Spriteの衝突判定や描画の処理では、Sprite#targetに指定されているオブジェクトのox/oyを取得して座標を補正するようになっています。

再現コード(coding: utf-8)を添付させて頂きました。
お忙しい事と存じますが、お試し頂ければ幸いです。

こちらの環境は以下です。

Object::RUBY_PLATFORM # => i386-mingw32
Object::RUBY_VERSION # => 2.1.7
DXRuby::VERSION # => 1.4.2 および 1.5.19dev で検証

何卒よろしくお願いいたします。以上。

Re: DXRubyWSにおけるWindow.ox/...

  • 記事番号: 338
  • 投稿者: はじめました太郎
  • 投稿時間: 2015/11/22 (Sun) 00:46
添付ファイルに問題がありましたので、再度アップさせて頂きました。

スレ汚し申し訳ないです。

Re: DXRubyWSにおけるWindow.ox/...

  • 記事番号: 339
  • 投稿者: mirichi
  • 投稿時間: 2015/11/22 (Sun) 08:37
現象確認しました。
大変ご迷惑をおかけしました。
ox/oyが衝突判定に反映されているというのは思い込みだったようです。。。
これは割と致命的な話なので対応を考えたいと思います。

Re: DXRubyWSにおけるWindow.ox/...

  • 記事番号: 340
  • 投稿者: はじめました太郎
  • 投稿時間: 2015/11/22 (Sun) 09:35
おはようございます、はじめました太郎です。
ほんとすいません、せっかくの日曜なのに宿題を作ってしまいまして…w

cのソースを適当に見た限り入ってない感じですし、collision.cとの兼ね合いも出てきそうですし、Viewport構想もあるようですし、慎重に検討される形になるのかなと認識しております。

Spriteを多層的に扱う時、平行移動は必須だと思いますので、対応を楽しみにしております。

回答遅れましたが、ゲームが出来ましたら、作者様にプレイして頂けるなら嬉しい限りです。頑張ります。

尚、別件で新たな質問がありまして新規スレッドを書かせて頂きました…申し訳ありませんがよろしくお願い致します。以上。

Re: DXRubyWSにおけるWindow.ox/...

  • 記事番号: 343
  • 投稿者: mirichi
  • 投稿時間: 2015/11/22 (Sun) 21:39
色々考えてみたのですが、結局のところ、
・Window.ox/oyを設定した場合、スクリーン座標と描画位置が食い違うことになる
・マウス座標の取得値は補正されない
・Spriteの描画位置は補正後の位置
というのが衝突判定ミスの原因であり、例えばマウスカーソルの位置に独自のカーソル画像をWindow.draw系メソッドで描画しようとすると、Window.ox/oyを設定した時点でOSにより描画されるカーソルの位置とズレる、というのと同じ話です。マウス判定用Spriteは見えていなくてもWindow.ox/oyの影響を受け、ズレた位置で判定されています。

判定時の補正が無い件については、Spriteの衝突判定はWindowやRenderTargetなどの描画対象が同じものであることが前提(これが違う場合ox/oyの設定値が違えば座標系が違うことになってしまう)なので、targetのox/oyは両Spriteで一致しているはずで、判定時にこれで補正する必要は無い、というのが補正していない理由となります。
RenderTargetに対して描画するSpriteは対象のRenderTargetそのものの描画位置を取得することができないので、判定時に補正したとしても画面上の見た目で当たっているかどうかを判別することにはなりません。

現状ではこの件に対してライブラリ側で対策する案はありませんが、もう少し大きい範囲でこの辺りを含めてうまいこと扱えるようにならないか、とか考えています。
とりあえず、Input.mouse_x/yで取得した値にWindow.ox/oyの値を加算してからマウス判定用Spriteの座標に設定することでうまくいくだろうと思いますので、そんな感じにしてみていただけますか。

多層構造のSpriteは現時点のDXRubyにそれを扱う機能が無い(RenderTargetの描画位置がわからない)というのもありなかなか難しい点で、WSで苦労したのは主にそのあたりとなっています。

この話はもうちょいしたらまとめてブログに上げようと思っています。

Re: DXRubyWSにおけるWindow.ox/...

  • 記事番号: 345
  • 投稿者: はじめました太郎
  • 投稿時間: 2015/11/23 (Mon) 11:49
回答ありがとうございます。
お時間を取らせてしまい申し訳有りませんでした。

ご説明を熟読して頭の中のモヤが完全に取れました。
以下って感じですね。

・mouse側のグローバル座標と、RenderTargetが持つ座標系が同じなのは、
 ox/oyのデフォルト値が0だから。
 ※Windowが裏で持つプライマリのRenderTargetも同様。

・Sprite.check系は、比較対象の全てのSpriteが同じ座標系である事を前提としている。
 比較対象の座標系が異なる場合、その補正はDXRuby側では行われない。
 補正の方法はInput.mouse_x/yの値にRenderTarget(Window含む)のox/oyを付加して行う。
 仮に複数の座標系間で衝突判定する場合は、座標系ごとに補正し判定を行う必要がある。
・故に多層的なSpriteを使った描画と衝突判定を利用する場合は、
 DXRubyWSのような枠組みが別途必要になる。

で、仮にDXRubyWSの実装例でこの件に対応する場合、

・RootがWindow固定
・Container#imageのRenderTargetはox/oyを使わない。
・Control#imageでRenderTargetを利用した場合でも、ox/oyを使わない。

といす形になる筈なので、

def find_hit_object(tx, ty)
 @hit_cursor.x, @hit_cursor.y = tx + Window.ox, ty + Window.oy
 @hit_cursor.check(@children.reverse)[0]
end
でいいのかもしれませんね。

mouse_event_dispatch()とget_focusable_control()でしか、find_hit_object()は利用しませんし、
ユーザーが独自にfind_hit_object()を利用する場合、補正が中に閉じてるので意識する必要もありませんし。

それにユーザーがon_mouse_push(tx, ty)内で独自の描画を行う場合、
引数tx/tyは補正されていないので、利用しやすい筈ですし。


とかく、こんな感じで対応していきたいと思います。

長くお付き合い頂きましてありがとうございました。以上です。

DXRubyのロゴのライセンスに関し...

  • 記事番号: 341
  • 投稿者: はじめました太郎
  • 投稿時間: 2015/11/22 (Sun) 09:36
DXRubyをインストールし成功した際にロゴを使ったウィンドウが立ち上がりますが、
ここで使われているロゴのライセンスはどのようになっておりますでしょうか?

ライブラリそのものやサンプルコードのライセンスは見かけるのですが、ロゴに関しては見付けられませんでした。

自作ゲーでDXRubyを利用している事を表記するに当たって、このロゴを利用させて頂きたいと考えております故、教えて頂けると助かります。ロゴ画像の改変等含めご回答願います。

以上。

Re: DXRubyのロゴのライセンスに...

  • 記事番号: 342
  • 投稿者: mirichi
  • 投稿時間: 2015/11/22 (Sun) 12:10
すみません、そこまで気が回りませんでした。
ロゴ画像に関してはDXRuby本体と同じライセンスと聞いていますのでzlibライセンスでいいと思います。今度書いておきます。
改変に関してもご自由にどうぞ〜。

Re: DXRubyのロゴのライセンスに...

  • 記事番号: 344
  • 投稿者: はじめました太郎
  • 投稿時間: 2015/11/23 (Mon) 10:52
回答ありがとうございます。
zlib(/libpng)ライセンスという事ですね、承知しました。

ロゴ画像はmirichi様作、という感じでは無さそうなのですね。勘違いしておりました。
大切にロゴを使わせていただきます。以上。

フルスクリーン時の挙動について...

  • 記事番号: 332
  • 投稿者: toshiro
  • 投稿時間: 2015/09/15 (Tue) 18:30
はじめまして。
DXRuby(1.4.2)にてゲームプログラミングを学習中の者です。

フルスクリーン時の挙動についていくつか気になる点がありましたのでご相談させてください。

1.グラフィックボードのドライバ側で垂直同期をオフにしているとFPSが異常に高くなる
2.CPUの使用率が100%近くなる
3.フルスクリーンからの復帰時にほかのアプリケーションのウィンドウ位置がずれる

こちらの環境固有の問題かもしれないので一応ほかのDirectXラッパーライブラリ(DXライブラリなど)でも
確認してみたのですが、上記の問題はいずれも起こりませんでした。

お手数ですが、対応策等がありましたらお教えいただけないでしょうか?

Re: フルスクリーン時の挙動につ...

  • 記事番号: 333
  • 投稿者: mirichi
  • 投稿時間: 2015/09/15 (Tue) 18:52
いらはりませ。
フルスクリーンは作者本人が全く使わないため、いまいちサポートが薄い感じになってしまっています。すみません。
とりあえず、フルスクリーン時には垂直同期信号を必ず見るようにしてしまっているので、それをドライバでオフにすると動作は安定しません。
フルスクリーンでは垂直同期周波数をプログラム側から指定することができるので同期するようにしてあったのですが、オフにできるとなるとちょっと事情が違うので対策を考えないとダメそうですね。
とはいえオフになっていることを検出する手段もなさそうなので困った感じです。個人的にはフルスクリーンでティアリングが発生するとものすごく目立つのでできる限り同期させたいところです。
また、垂直同期オフ時はフルパワーで動くことになるのでCPU使用率が100%になります。
他のアプリケーションの位置がずれる件はちょっとわからないのですが、他のライブラリで発生しないとなると何かしら対策があるのだろうと思うので調べてみます。
なお、これらの現象についてはRubyプログラム側からの対策手段は無いと思います。あえてひとつ挙げるならフルスクリーンを使わないこと、でしょうか。。。

Re: フルスクリーン時の挙動につ...

  • 記事番号: 334
  • 投稿者: toshiro
  • 投稿時間: 2015/09/16 (Wed) 18:08
さっそくのご返事ありがとうございました。

> フルスクリーンでは垂直同期周波数をプログラム側から指定することができるので同期するようにしてあったのですが、オフにできるとなるとちょっと事情が違うので対策を考えないとダメそうですね。
ゲームによっては、ドライバ側の設定にかかわらずプログラム側で垂直同期のオンオフを
指定できるようになっているものもあるようです。
オンにすると明らかにティアリングが減少するので、実際にはオフになっている
ということもないと思います。
(もちろんDXRubyと同じようにドライバ側でオフになっているとプログラム側で
オンにしても有効にならないものもありました)

> また、垂直同期オフ時はフルパワーで動くことになるのでCPU使用率が100%になります。
すみませんこれについてはグラフの読み方を間違えておりまして実際には70%ぐらいでした。
またこの現象は垂直同期のオンオフに関係なく起こるようです。
大げさ&まぎらわしい書き方をしてしまい申し訳ありません。
(なおウィンドウモードではCPU使用率1桁ぐらいのプログラムで確認しました)

> 他のアプリケーションの位置がずれる件はちょっとわからないのですが、他のライブラリで発生しないとなると何かしら対策があるのだろうと思うので調べてみます。
参考までに私が調べたかぎりでは
・ずれない→DXライブラリ、Luna、HSP+HGIMG3
・ずれる→StarRuby、Pygame
という感じでした。

> あえてひとつ挙げるならフルスクリーンを使わないこと、でしょうか。。。
確かに最近の2Dゲームはウィンドウモードや仮想フルスクリーンが主流ですから
フルスクリーンにこだわるのは時代遅れなのかなあという気もしています……。
ただ選択肢の一つとして残っていてほしいなあとは思います。

メモリについて

  • 記事番号: 326
  • 投稿者: ahogappa
  • 投稿時間: 2015/09/01 (Tue) 01:21
こんにちは DXRubyをいつも愛用させてもらっています

現在 弾幕シューティングを製作していて弾を大量に生成、削除します
削除する際にSprite#vanish Sprite.cleanなど使っているのですがしばらくするとパフォーマンスが下がってしまいます GC.start等試しているのですがメモリが解放されなかったのでパフォーマンスが良くはなりませんでした
このようなメモリの解放についてはruby側からは解決できるのでしょうか

Re: メモリについて

  • 記事番号: 327
  • 投稿者: mirichi
  • 投稿時間: 2015/09/01 (Tue) 20:12
いらはりませ。
パフォーマンス低下の原因がメモリの解放であると断定する根拠は何でしょうか?(タスクマネージャで見てると増えていくとか)
一応、手元でSpriteの大量生成とSprite#vanish、Sprite.cleanによる解放でメモリリークについて確認してみましたが、それっぽい現象は発生しませんでした。

基本的に、メモリの圧迫それそのもので目に見えてパフォーマンスが落ちるということは、いまどきのPCならギガバイト単位で消費していないとまず無いと思っています。
なので、ありえそうな現象としては、オブジェクト管理用配列の中に何かしら残っていて配列のサイズが極端に大きくなっているとか、Spriteへの参照がどこかに残っていて解放されずに残り続けてGCの負荷が増えているなどといったあたりです。
とりあえずは管理用の配列のサイズを表示するなどして確認するなどしてみて頂けますでしょうか。

Re: メモリについて

  • 記事番号: 328
  • 投稿者: ahogappa
  • 投稿時間: 2015/09/01 (Tue) 20:58
お早い返信ありがとうございます
確かにメモリによってのパフォーマンスの低下は断定はできていませんがタスクマネージャで確認すると使用メモリが減ることなく増え続けてしまっています(最終的には1GBを超えた)
配列内も確認していますが目立ったサイズの肥大は見られませんでした

記述のミスだと思ったので実行ファイルを添付しようと思ったのですが画像等入ってる関係でサイズが大きく画像を抜いた.rbファイルのみですが確認いただけないでしょうか
念のため実行環境は
OS:Windows7(BootCamp)
CPU:2 GHz Intel Core i7
メモリ:8 GB 1333 MHz DDR3
グラフィックス:Intel HD Graphics 3000 512 MB

Re: メモリについて

  • 記事番号: 329
  • 投稿者: mirichi
  • 投稿時間: 2015/09/01 (Tue) 21:35
適当な画像を設定して動かしてみました。
まず、Layer.rbのself.all_updateメソッドの中にコメントアウトされている@@update_object.flatten.sizeですが、これを有効にすると出力される数字はどんどん増えていくのが見れます。
先ほど書いた「オブジェクト管理用配列の中に何かしら残っていて配列のサイズが極端に大きくなっている」というのはこれの事です。
つまり、画面から出たオブジェクトが消えずにずっと移動&描画処理され続けているため、急速にパフォーマンスが落ちていくわけです。
修正点ですが、
Bullet.rbのupdateメソッド内にあるif、
if BASE_MIN_X > self.x || BASE_MIN_Y > self.y || BASE_MAX_X < self.x || BASE_MAX_Y < self.y
end
の中にself.vanishと書いてあげることで対策することができます。
画面から出たオブジェクトは自分で自分をvanishして、あとでSprite#cleanで配列から除去されるという仕掛けになります。

ちなみにオブジェクトの消し忘れによるパフォーマンス低下の現象は、俺自身何かしら作ってるときによくやります。うまい対策があるといいんですが思いつかないんですよね。

Re: メモリについて

  • 記事番号: 330
  • 投稿者: ahogappa
  • 投稿時間: 2015/09/01 (Tue) 23:03
先に返信されてしまいました
画面外の消去処理の忘れに気づきこちらは修正しました
消去されるのを確認して直ったと思ったのですが
タスクマネージャからメモリを確認するとやはり増え続けていくようなんです
おなじオブジェクト数を毎フレーム更新、描画しているはずなのに徐々に処理落ちしていくのはどうしたらよいでしょうか
追記:気のせいだと思ってずっと動かしていましたが10000cntを超えるとだいぶ遅くなってしまいました 実行環境差なのでしょうか
追記2:どうやら自前で作ったLayerクラスの<<メソッド当たりが悪さしてるみたいで、このクラスを使わないで作り直したら上手くできました ひとまずはこれで作りたいと思います お時間を割いて頂いたのに申し訳ございません…

Re: メモリについて

  • 記事番号: 331
  • 投稿者: mirichi
  • 投稿時間: 2015/09/02 (Wed) 21:28
あー、出力される数字が増えなくなったので油断してしまったようです。すみません。
もいちど調べてみたところ、Layerクラスの<<メソッド内で、@@all_layers_object、@@draw_object[@draw_index]、@@update_object[@draw_index]、@objectの4つの配列にオブジェクトを追加しているのに、self.cleanメソッド内では@@update_objectしかcleanしていない、というのが原因のようです。
これらを全部Sprite.cleanしてやればすべての参照が消えるのでvanishしたSpriteは解放されます。

簡易初心者かくとうゲーム

  • 記事番号: 324
  • 投稿者: ハヤブサ.MX
  • 投稿時間: 2015/08/13 (Thu) 17:27
初心者です 格闘ゲームプログラムを作りましたが、衝突判定が難しく、敵を動かすのが難しくて よくわからなくなってしまいました。 プログラムも載せておきます。プログラムをみた方はどこをどうすればいいのか教えていただけたらうれしいです

Re: 簡易初心者かくとうゲーム

  • 記事番号: 325
  • 投稿者: mirichi
  • 投稿時間: 2015/08/13 (Thu) 22:34
いらはりませ。
格闘ゲームはなかなか難しそうですね。
ところでプログラムなんですが、なんか違うっぽいものがアップロードされてましたので、確認してみてください。

描画処理の改善法

  • 記事番号: 317
  • 投稿者: noanoa07
  • 投稿時間: 2015/05/30 (Sat) 21:53
noanoa07 と申します。

以下のようなコードを書いたところ描画処理が重くなってしまい、改善法がないだろうかと悩んでいます。

かなり変則的な書き方になっているのは、教育用(or 自分の勉強用)にRuby/ DXRuby の便利な機能を使わず、なるべくプリミティブな命令だけコードを書こうとしているためです。(Imageクラスはドットを作るだけで、Spriteクラスも使わない。)

というのは、「プログラムはこうして作られる―プログラマの頭の中をのぞいてみよう」(平山尚著)を読んで、著者独自のプログラミング言語 Sunaba にならって、DXRubyでブロック崩しを実装しようと思ったからです。

なお、ブロック崩しのコードは mirichi さんの 松江Ruby会議05 でのコードを参考にしています。

Window.discard を挟むと良いかと試してもみたのですが、特に変わりはありませんでした。
もしよろしければ、アドバイスをお願いいたします。

-------------------------------------------------
require 'dxruby'

dot = Image.new(1, 1, C_WHITE)
red = Image.new(1, 1, C_RED)

def rect(x, y, width, height, dot)
h = 0
while h <= height
w = 0
while w <= width
Window.draw(x + w, y + h, dot)

w = w + 1
end
h = h + 1
end
end

dx = 4
dy = -4
ball_x = 300
ball_y = 400

Window.loop do
rect(0, 0, 20, 480, dot)
rect(0, 0, 640, 20, dot)
rect(620, 0, 20, 480, dot)

x = Input.mouse_pos_x
rect(x, 460, 100, 20, dot)

ball_x = ball_x + dx
ball_y = ball_y + dy
rect(ball_x, ball_y, 20, 20, red)
end
-------------------------------------------------

Re: 描画処理の改善法

  • 記事番号: 319
  • 投稿者: veryvery3
  • 投稿時間: 2015/05/31 (Sun) 01:51
プリミティブな命令がどの範囲までかによりますが、
Window.draw_box_fillでもOKでしたら下記のような
コードでいかがでしょうか?

--------------------------------------------
require 'dxruby'

def rect(x, y, width, height, c)
Window.draw_box_fill(x, y, x + width, y + height, c)
end

dx = 4
dy = -4
ball_x = 300
ball_y = 400

Window.loop do
rect(0, 0, 20, 480, C_WHITE)
rect(0, 0, 640, 20, C_WHITE)
rect(620, 0, 20, 480, C_WHITE)

x = Input.mouse_pos_x
rect(x, 460, 100, 20, C_WHITE)

ball_x = ball_x + dx
ball_y = ball_y + dy
rect(ball_x, ball_y, 20, 20, C_RED)
end
--------------------------------------------

Re: 描画処理の改善法

  • 記事番号: 321
  • 投稿者: noanoa07
  • 投稿時間: 2015/05/31 (Sun) 11:27
veryvery3さん

ありがとうございます。
これなら実用的なスピードで描画されますね。

ただ、考えていたのは;
1.点(ドット)を表示する
2.点で四角を描く
3.四角を操作する(バーを描く)
4.四角を複数描く(壁を描く)
5.複数描く部分を関数にまとめる
6.ボールを動かす
7.壁との衝突判定をする
8.ブロックを描く
9.ブロックとの衝突判定(衝突したら消す)をする
10.ブロック崩しの完成

というような流れの初学者用の授業にと考えていました。

なので、四角を描くコードを途中で置き換えなくてはいけなくなるのが悩む点です。

Re: 描画処理の改善法

  • 記事番号: 322
  • 投稿者: mirichi
  • 投稿時間: 2015/05/31 (Sun) 11:49
なるほど・・・。
1ピクセルのImageを大量に描画すると非常に遅いのは初期の頃からありまして、例えばサンプルのdot.rbではウィンドウサイズのImageを作ってそこに点を描画する方法で速度を稼いでいます。
やってみたら思った以上に遅かったのでその対策ですね。

ですので、先に回答されているように四角を点の集合でなくまとめて描くか、以下のようにImageを作って描画するかのどちらかが対策になるかと思います。
require 'dxruby'

$screen = Image.new(640, 480)

def rect(x, y, width, height, color)
h = 0
while h <= height
w = 0
while w <= width
$screen[x + w, y + h] = color
w = w + 1
end
h = h + 1
end
end

dx = 4
dy = -4
ball_x = 300
ball_y = 400

Window.loop do
$screen.clear

rect(0, 0, 20, 480, C_WHITE)
rect(0, 0, 640, 20, C_WHITE)
rect(620, 0, 20, 480, C_WHITE)

x = Input.mouse_pos_x
rect(x, 460, 100, 20, C_WHITE)

ball_x = ball_x + dx
ball_y = ball_y + dy
rect(ball_x, ball_y, 20, 20, C_RED)

Window.draw(0, 0, $screen)
end

Re: 描画処理の改善法

  • 記事番号: 323
  • 投稿者: noanoa07
  • 投稿時間: 2015/05/31 (Sun) 22:14
mirichiさん
回答ありがとうございます。

「ウィンドウサイズのImageを作ってそこに点を描画する」というのは思いつきませんでした。

dot.rb も見てみました。こんなこともできるんですね!
びっくりしました!!

参考にさせて頂きます。

Windowモジュールで点や円の描画

  • 記事番号: 318
  • 投稿者: saru
  • 投稿時間: 2015/05/31 (Sun) 01:32
DXRubyで簡単な物理モデルを表現しようとしています。

点、線、四角、円などの基本的な描画をおこなう場合、
線や四角であれば Window.draw_lineや Window.draw_box_fillで
Windowに直接描画できますが、点や円については
いったん Imageクラスのインスタンスを用意して
そこに描画しなければならないように思われます。

そこで、例えば円と四角を合わせたような図形を描画する際、
汎用的に処理をおこなうために Windowと同じサイズの
Imageをキャンバスに見立てて、そこに任意の図形を
描画するというのは妥当な方法でしょうか?

Imageに描画してからさらにそれを Window.drawで画面表示
することになるので、なにか効率が悪いようにも思えるのですが...

Window.draw_circleや Window.draw_pointなどのメソッドがない理由なども、あわせてご教示いただけると幸いです。

Re: Windowモジュールで点や円の...

  • 記事番号: 320
  • 投稿者: mirichi
  • 投稿時間: 2015/05/31 (Sun) 11:17
いらはりませ。
点の直接描画は全く想定外でした。用途的な面で。
一応、線や四角を1ピクセル指定(始点と終点を同じにする)で描画すれば描けるかとは思います。
ちなみにこの機能を作ったとしても、内部的には上記と同じことをするだけになります。

円についてですが、これが無いのはWindow.draw_なんちゃら系の直接描画が「ポリゴンを描画している」からです。
ポリゴンは三角形ベースなので円が描画できないのです。
四角は三角形を2つ、線はそれを1ピクセル幅にしたもので描画しています。
円の描画は一時期検討していたのですが、結局内部的にはImageを作ってImage#draw_circleとかで絵を描いてWindow.drawで画面に描画してImage#delayed_disposeするのと同じことをまとめてやるだけで、効率的になるわけでもないので、やめときました。

ということで、円のサイズや色を動的に変えながら描画する用途であれば、Shaderを使うか、画面サイズのImageに描くのがよいと思います。
あ、内部でShaderを使う円描画機能を作ればいいのかw
ちょと考えてみます。
Next>>
*.rb, *.zip のみ可 (〜300KB)
- ShuttleBoard -