質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
Processing

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

Q&A

解決済

1回答

11964閲覧

Processingでの画像描画した際の処理落ちについて

geekarrrk

総合スコア12

Processing

Processingは、オープンソースプロジェクトによるCGのためのプログラミング言語です。Javaをベースにしており、グラフィック機能に特化しています。イメージの生成やアニメーションなど、視覚的なフィードバックを簡単に得ることが可能です。

0グッド

0クリップ

投稿2016/10/06 13:16

編集2016/10/08 04:44

###前提・実現したいこと
Processingでシューティングゲームを作っています。
手前と背景の多重スクロールを実装し、テスト用のrectメソッドを用いての矩形での描画から実際のゲーム画面で用いる背景画像をマップサイズの16×16枚で画像を描画したところ、処理が追いつかず大変に動作が重くなってしまいました。
解決策はありますでしょうか?
ちなみにゲーム画面はscaleメソッドで4倍表示しています。
3倍だと何とか動くのですが、やはり画面が表示が小さくなってしまうため4倍表示で描画したいのです。

byte[] arr; PImage[] img; for(int i=0; i<16; i++){ for(int j=0; j<16; j++){ fill(#ccddff); stroke(#aaccff); //rect(j*chip,i*chip,chip,chip); image(img[arr[j+(i*16)]],j*chip,i*chip); } }

※コメントアウトしてあるrectメソッドからimageメソッドへ
変更した時に動作が重くなりました。

###補足情報(言語/FW/ツール等のバージョンなど)
Processingでコーディングしています。
この様な画像の描画にあたって処理を軽くする方法などもございましたら、教えてください。

掲載にあたって一部コードを簡略化しています。

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

コードの全容がつかめないため憶測ですが

恐らく下記のようなコードを書いて
画像読込みをしているのだと思います

Processing

1//0.png , 1.png ,..., 49.png という画像をimgに読込んで使用する場合 2img = new PImage[50]; 3for(int i=0; i<50; i++){ 4 img[i] = loadImage(String.valueOf(i)+".png"); 5}

これがdraw()の中にあると
毎フレームごとにファイルを読込むため
当然重くなります

画像を読込むのを起動時だけにするためには
setup()中でimgの初期化を行います

また
PImage[] img;は
setup()やdraw()の外側で宣言します

次のようなPImageへのマスク適用も
draw()文の中で毎フレームごとに行うと重くなります

for(int i=0; i<50; i++){ //0_mask.png , 1_mask.png ,..., 49_mask.png という画像をimgにマスクとして適用する場合 PImage maskImg = loadImage(String.valueOf(i)+"_mask.png");//マスク用画像を読込み img[i].mask(maskImg);//読み込んだ画像をマスクとして割当 }

これもsetup()内で行うことで軽くなります

他にも setup()内で
size(123,123); → size(123,123,P2D);としてみる(レンダラーの指定ができます)
noSmooth();としてみる(アンチエイリアスをオフにします)
などで改善されるかもしれません

投稿2016/10/07 05:51

e-cube

総合スコア284

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

geekarrrk

2016/10/07 07:00

御丁寧に解説していただいて、ありがとうございます。 コードが膨大なので抜粋したのですが、質問するにあたって大事な部分が抜けておりました。 setup()メソッド内で 画像は256×256ピクセルの大きな画像を用意し、更にそれらを縦、横16ピクセル単位の合計256枚にgetメソッドで分割して別のPimage型配列に格納し、 別のbyte型配列データに基づいてPImage型配列からデータに該当するイメージを取り出し256枚を敷き詰めてゲーム描画を描画いています。 ```ここに言語を入力 PImage bigImage; PImage[] img = new PImage[256]; byte[] arr = new byte[256]; void setup(){ arr=loadBytes("data/map.dat"); bigImage = loadImage("bg.png"); for(int i=0; i<16; i++){ for(int j=0; j<16; j++){ img[j+(i*16)] = bigImage.get(16*j,16*i,16,16); } } } void draw(){ for(int i=0; i<16; i++){ for(int j=0; j<16; j++){ image(img[(arr[j+(i*16)]],j*chip,i*chip); } } } ``` sizeメソッドでP2Dを指定したところ、若干軽くはなったのですがまだ処理落ちします。 PImageのgetについても、draw()内で記述したことが以前にありその時は処理が重くなり、数分後に停止してしましました。 どうやらdrawメソッド内で記述した場合、毎フレームごとにgetしたタイミングでsetup()で作ったインスタンスとは別に新たにPImageのインスタンスが作られるようです。 今回はその点も考慮してsetup()でgetを記述しました。 少し質問とずれるのですが、画像を用いた2Dゲームについては最初に大きな画像を用意しておき、そこからチップサイズで切り出して描画するのが通常だと思うのですが 今回のコードのように実装するべきなのでしょうか? 他の実装方法があれば教えていただけないでしょうか? 全文を載せることが出来ないのでコードをアップしました。 以下のサイト、"シューティングゲーム"からコードをダウンロードできます。 http://www7b.biglobe.ne.jp/~portgames/ 投稿では画面サイズ16×16ですが実際は左右スクロールなど実装するため22×16で作成しております。 長文失礼しました。
geekarrrk

2016/10/07 07:11

操作方法について記述し忘れました。 [Z] ショット [X] 武器チェンジ [←→↑↓] 移動 [D] 表示サイズ変更 [R] リスタート [A] 敵の追加(Ctrl + ←→で敵の種類変更) [Ctrl + ↑↓] スクロールスピード調節 [SPACE] モード変更 P2D、noSmooth()を併用すると快適に動作しました。 有難うございます。 何かお気づきの点でもご指摘していただけると、ありがたいです。
e-cube

2016/10/07 11:09

>コードが膨大なので 本当に膨大で驚きました すごいです 偉業です あえてこちらから助言するとすれば 動作を見る限り マップの描画が毎フレームごとなのに対し マップデータの更新自体はもっと頻度が低いようです ですのでMapクラスには 「PGraphics」を使うともっといいのではないかと思います 「PGraphics」は言うなれば、中身に対し追加描画可能なPImageです レイヤーや画面キャッシュとして使うことができます //初期化(最初に作成されるのは透明な画像) PGraphics pg = createGraphics(横幅, 縦幅, P2Dなどのレンダラー指定); //描画 pg.beginDraw(); pg.image(img,x座標,y座標);//こうすると img(PImageオブジェクト)の内容がpgに描画される pg.endDraw(); //表示(画面にpgを貼り付けるイメージ) image(pg,x座標,y座標); MapクラスのプロパティにPGraphicsを持たせ マップ全体を「PGraphicsに」描画するメソッドを定義します これはdisplay()メソッドを少し改良するだけで作れるはずです この描画(再描画)メソッドを マップデータが更新される際(update()の最後?)に呼び出し 毎フレームごとに呼び出されるdisplay()メソッドでは PGraphicsを表示するだけにすると かなり処理の節約になると思います ただし座標指定とかは変わってしまうので注意が必要です >画像を用いた2Dゲームについては最初に大きな画像を用意しておき、そこからチップサイズで切り出して描画するのが通常だと思うのですが そうだと思います 実はPImageに get()メソッドという便利なのがあるとはつゆしらず 今まではそういうことをする時は PGraphicsに位置をずらして image()描画でなんとかしてました スルーしてください
geekarrrk

2016/10/07 13:09

ダウンロードしていただいた上にコードまで見ていただいて どうもありがとうございます。 処理が軽くなるようPGraphicsの実装方法まで考えていただいて恐縮です。 ただPGraphicsクラスは存在を知らなかったので、説明を読んだり 検索してなんとなく概念はわかったのですが実際のゲームに反映するのは 後日になりそうです。 OpenProcessingにポートフォリオを公開していらっしゃるんですね。 テトリスや3Dのものもあってすごいですね。ベクトルなどよくわからないので尊敬します。 問題があったり、シューティングが完成した時にはまた投稿しますね。 一人で頭をひねっても解決策が思い浮かばなかったので大変助かりました。 御丁寧にありがとうございました。
geekarrrk

2016/10/08 11:17

Pgraphicsで描画を行うように修正しました。 バラバラにした画像を再結合する方法を探していたので、正に知りたいことでした。 今回のPgraphicsやレンダラ―のP2Dを用いることで家庭用ゲーム並みの速度で動くようになりました。グラフィックも若干変えたのでそれっぽく見えます。 http://www7b.biglobe.ne.jp/~portgames/ ただP2Dを使うと実行後に一度ウィンドウをクリックしないとキー入力を受け付けません。今回はありがとうございました。
e-cube

2016/10/10 16:42

>バラバラにした画像を再結合する方法を探していたので お役に立てて何よりです 完成まで頑張ってください
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問