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

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

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

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

Q&A

解決済

2回答

2565閲覧

トリプルバッファ?

nakamura-

総合スコア48

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Android

Androidは、Google社が開発したスマートフォンやタブレットなど携帯端末向けのプラットフォームです。 カーネル・ミドルウェア・ユーザーインターフェイス・ウェブブラウザ・電話帳などのアプリケーションやソフトウェアをひとつにまとめて構成。 カーネル・ライブラリ・ランタイムはほとんどがC言語/C++、アプリケーションなどはJavaSEのサブセットとAndroid環境で書かれています。

0グッド

1クリップ

投稿2016/06/10 02:05

編集2016/06/10 02:31

前回質問させていただいたカクカクする動きを直す方法としてSurfaceViewというものがありましたが、
SurfaceViewを使ってもまだカクカクする場合はどうすればいいのでしょうか?

トリプルバッファリングというのがあるのかと思い調べてみましたがそれらしいのはありませんでした。
SurfaceView以上にカクカクを改善する方法はあるのでしょうか?
それともSurfaceViewでカクカクするならプログラムを軽くするように改善するしかないのでしょうか?

よろしくお願いします。

追記
前回の質問
カクカクな動きを改善する方法
リンク内容

桜の花びらが舞っているプログラム

コード public class MainActivity extends Activity{ int sakuraCount = 50; //表示する桜の枚数 Sakura sakura[] = new Sakura[sakuraCount]; CanvasView canvasview; /** * メインメソッド */ @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); canvasview = new CanvasView(this); setContentView(canvasview); sakuraCreate(); } /** * 桜インスタンス化・スレッド開始メソッド */ public void sakuraCreate(){ Random rnd = new Random(); for(int i = 0; i < sakuraCount; i++){ sakura[i] = new Sakura( (Math.random() * 800) - 100, 0, rnd.nextInt(11) + 5, rnd.nextInt(100)*100, Math.random() /*+ 1*/); /*このクラスのcanvasviewがSakuraクラスのものと同値であると示す*/ sakura[i].setCanvasView(canvasview); sakura[i].start(); } /*このクラスのsakuraCountとSakuraがCanvasViewクラスのものと同値であると示す*/ canvasview.setSakuraCountAndSakura(sakuraCount, sakura); } }
コード public class CanvasView extends SurfaceView implements SurfaceHolder.Callback, Runnable{ int sakuraCount; Sakura sakura[] = new Sakura[sakuraCount]; SurfaceHolder sHolder; Thread thread; boolean trueOrFalse; /** * CanvasViewクラスのコンストラクタ */ public CanvasView(Context context){ super(context); sHolder = getHolder(); sHolder.addCallback(this); } /** * sakuraCountとsakura[]同値メソッド */ public void setSakuraCountAndSakura(int sakuraCount, Sakura sakura[]){ this.sakuraCount = sakuraCount; this.sakura =sakura; } /** * SurfaceViewが生成されたときに呼ばれるメソッド */ @Override public void surfaceCreated(SurfaceHolder sHolder){ trueOrFalse = true; thread = new Thread(this); } /** * SurfaceViewの状態が変更されたときと * 生成されたときも呼ばれるメソッド */ @Override public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){ thread.start(); } /** * SurfaceViewが破棄されるときに呼ばれるメソッド */ @Override public void surfaceDestroyed(SurfaceHolder holder){ trueOrFalse = false; while(thread != null && thread.isAlive()){ thread = null; }; } /** * run(描画)メソッド */ public void run(){ while (trueOrFalse == true){ Canvas canvas = sHolder.lockCanvas(); if(canvas != null){ canvas.drawColor(Color.WHITE); Path path = new Path(); for(int i = 0; i < sakuraCount; i++){ path.moveTo(sakura[i].Screen_vData[0][0], sakura[i].Screen_vData[0][1]); path.quadTo(sakura[i].Screen_cData[0][0], sakura[i].Screen_cData[0][1], sakura[i].Screen_vData[1][0], sakura[i].Screen_vData[1][1]); path.quadTo(sakura[i].Screen_cData[1][0], sakura[i].Screen_cData[1][1], sakura[i].Screen_vData[0][0], sakura[i].Screen_vData[0][1]); canvas.drawPath(path, sakura[i].paint); } } //Canvasのロックを解除する sHolder.unlockCanvasAndPost(canvas); } } }
コード public class Sakura extends Thread{ CanvasView canvasview; Paint paint = new Paint(); //Paintクラスをインスタンスごとに管理 int Vertex_data[][] = { { 1, 1, 0}, //点P0 { -1, -1, 0} }; //点P1 //頂点データ float Screen_vData[][] = new float[2][3]; //表示頂点データ int Control_data[][] = { {-1, 1, 0}, //点P0から点P1 { 1, -1, 0} }; //点P1から点P0 //曲線描くときのコントロールデータ float Screen_cData[][] = new float[2][3]; //表示コントロールデータ double pointX; //表示位置のx座標 double pointY; //表示位置のy座標 int scale; //描画倍数 int time; //開始時間 double distanceY; //移動距離 double phi; //x軸周りの回転角 double theta; //y軸周りの回転角 int select; //左右判定 Random rnd = new Random(); /*Sakuraクラスのコンストラクタ*/ public Sakura( double pointX, double pointY, int scale, int time, double distanceY){ this.pointX = pointX; this.pointY = pointY; this.scale = scale; this.time = time; this.distanceY = distanceY; phi = 0; theta = 0; //左右どちらに動くか判定 select = rnd.nextInt(2) + 1; paint.setColor(Color.MAGENTA ); //色設定 paint.setStrokeWidth(1); //線の太さ設定 paint.setAntiAlias(true); //滑らかに書く paint.setStyle(Paint.Style.FILL); //塗りつぶし } /*runメソッド・時間繰り返し処理(startメソッドの後に呼び出される)*/ public void run(){ //開始時間設定 try{ Thread.sleep(time); } catch(InterruptedException e){ } for(int i = 0; i < 100000; i++){ try{ Thread.sleep(5); } catch(InterruptedException e){ } if(select == 1){ pointX += (Math.random() * 1); } else{ pointX -= (Math.random() * 1); } phi += Math.PI / (rnd.nextInt(101) + 30); //角度変更処理 theta += Math.PI / (rnd.nextInt(101) + 30); //角度変更処理 pointY += distanceY; //落下処理 setRotPosition(); } } /*回転後、座標を更新するメソッド*/ public void setRotPosition(){ //回転後の頂点座標 for(int i = 0; i < Vertex_data.length; i++){ double rvx = Vertex_data[i][0] * Math.cos(theta) + Vertex_data[i][2] * Math.sin(theta); double rvy = Vertex_data[i][0] * Math.sin(phi) * Math.sin(theta) + Vertex_data[i][1] * Math.cos(phi) - Vertex_data[i][2] * Math.cos(phi) * Math.cos(theta); double rvz = - Vertex_data[i][0] * Math.cos(phi) * Math.sin(theta) + Vertex_data[i][1] * Math.sin(phi) + Vertex_data[i][2] * Math.cos(phi) * Math.cos(theta); Screen_vData[i][0] = (float)(pointX + (rvx * scale)); Screen_vData[i][1] = (float)(pointY - (rvy * scale)); Screen_vData[i][2] = (float)(rvz * scale); } //回転後のコントロールデータ for(int i = 0; i < Control_data.length; i++){ double rcx = Control_data[i][0] * Math.cos(theta) + Control_data[i][2] * Math.sin(theta); double rcy = Control_data[i][0] * Math.sin(phi) * Math.sin(theta) + Control_data[i][1] * Math.cos(phi) - Control_data[i][2] * Math.cos(phi) * Math.cos(theta); double rcz = - Control_data[i][0] * Math.cos(phi) * Math.sin(theta) + Control_data[i][1] * Math.sin(phi) + Control_data[i][2] * Math.cos(phi) * Math.cos(theta); Screen_cData[i][0] = (float)(pointX + (rcx * scale)); Screen_cData[i][1] = (float)(pointY - (rcy * scale)); Screen_cData[i][2] = (float)(rcz * scale); } } /*canvasview同値メソッド*/ public void setCanvasView(CanvasView canvasview) { this.canvasview = canvasview; } }

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

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

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

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

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

masaya_ohashi

2016/06/10 02:07

前回の質問へのリンクを貼っておくと、回答者がわざわざ探さなくてすみますよ。
nakamura-

2016/06/10 02:16

ご指摘ありがとうございす。 質問に載せておきました。
guest

回答2

0

ベストアンサー

ダブルバッファリングという技術は、カクカクを改善するための技術ではなく、「まだ描いてる途中の絵」が画面に出ないようにするための技術です。
例えば黒板に絵を描いていくと、見ている人は絵が描き換わっていくところを目撃してしまいますが、ホワイトボードの裏面に描いてひっくり返す、を繰り返せば、見ている人はキレイな状態の絵だけを見ることができますよね?これがダブルバッファリングの仕組みです。
ちなみにトリプルバッファリングという技術も存在しますが、おそらく問題解決にはならないです。

SurfaceViewで速度が改善された理由はダブルバッファリングうんぬんではなく、SurfaceViewが開発者が自分で描画プログラムを描くことに特化しているからです。そして、それでカクカクするということは描画処理、及びアルゴリズムに問題が有るといえます。

コードが書かれていないため、どこが悪いとは指摘できませんが…


以下追記
###コード改善のアドバイス
まずぱっとみ、Threadを作りすぎだと思います。設計としては、Sakura自身をスレッドにするのではなく、Sakuraの配列を管理するスレッドを作りましょう。簡素に書きますので、エラーとかあったらご容赦を。

Java

1// CanvasView 2public void run(){ 3 // Sakura管理スレッドここから 4 Thread sakuraManageThread = new Thread(new Runnable() { 5 public void run() { 6 while(true) { 7 try{ 8 Thread.sleep(5); 9 } 10 catch(InterruptedException e){ 11 throw new RuntimeException(e); 12 } 13 for(int i=0;i<sakuraCount;i++) { 14 Sakura s = sakura[i]; 15 s.update(); 16 } 17 } 18 } 19 }); 20 sakuraManageThread.start(); 21 // ここまで 22 while (trueOrFalse == true){ 23 //省略 24 } 25} 26 27// Sakura 28// Thread継承をやめ、runのかわりに下記に置き換える 29public void update() { 30 if(select == 1){ 31 pointX += (Math.random() * 1); 32 } 33 else{ 34 pointX -= (Math.random() * 1); 35 } 36 37 phi += Math.PI / (rnd.nextInt(101) + 30); //角度変更処理 38 theta += Math.PI / (rnd.nextInt(101) + 30); //角度変更処理 39 pointY += distanceY; //落下処理 40 41 setRotPosition(); 42} 43// Thread継承をやめたので、MainActivityでstartを呼んでいる箇所も削除

こうすることでむやみにThreadを500個増やすようなことがなくなります。
これで動作が改善するか確かめてみてください。

投稿2016/06/10 02:13

編集2016/06/10 03:04
masaya_ohashi

総合スコア9206

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

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

nakamura-

2016/06/10 02:34 編集

回答ありがとうございます。 わかりやすい解説ありがとうございます。 ではバッファを増やしても?カクカクは直らないんですね。 やはりプログラムに問題があるようですね。 よろしければプログラムを載せておきますので悪いところがあれば指摘お願いいたします。 追記 プログラム載せておきました。 桜の枚数(sakuraCount)が50枚のときはカクカクしませんが、500枚にするとカクカクします。
nakamura-

2016/06/10 08:46 編集

プログラムまでありがとうございます。 上のプログラムを参考に修正したのですが、このプログラムでは花びら10枚にすると10枚同時に落ちてきました。 Sakuraクラスをスレッドにしていた場合はそれぞれのスレッドに時間差を持たしていたのでランダムに落ちてきていたのですが、ご指摘いただいたSakuraの配列を管理するスレッドでも時間差をもたせれるのでしょうか? 追記 一応初期値のy座標をずらしておくと時間差があるようにはできました。
masaya_ohashi

2016/06/10 09:20

他に時間差を作る手法としては、MainActivityでいっぺんにSakuraのインスタンスを作るのではなく、sakuraManageThreadのrunの中で、少しずつnewしていく等の方法が考えられます。y座標を最初からずらしておくというのも、よいやり方だと思います。
nakamura-

2016/06/14 08:35

回答ありがとうございます! そういうやり方もあるんですね! インスタンスの方でも時間差できました。 ありがとうございました!!
guest

0

思いついたことを・・・

・同じ計算を何度も行っている
Math.sin(theta)、Math.cos(theta)、Math.sin(phi)、Math.cos(phi)これらの値は、
theta、phiの値が変化しない限り、同じ値になるはずです。
setRotPosition()メソッドの中で、theta、phiの値が変更されることはないと思うので、
setRotPosition()メソッドの頭で、前もって計算、変数に保持しておき、
その後のループ処理中に、変数の値を使用するようにしたほうが良いと思います。

・桜の花びら1枚につき1つのスレッドを作成しているのは大丈夫か?
スレッド内部の処理を詳しく知っているわけではないのですが、
さすがに500のスレッドを同時に制御させるのは厳しいのではないでしょうか?

・端末の性能
そもそも物理的に限界を超えている可能性

投稿2016/06/10 03:20

編集2016/06/10 03:22
abs123

総合スコア1280

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

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

nakamura-

2016/06/10 08:37

回答ありがとうございます。 確かに無駄な計算が多いですね笑 スレッドも多いのはダメみたいですね。 ご指摘ありがとうございました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問