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

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

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

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

Q&A

解決済

1回答

1990閲覧

花火プログラム スレッド

nakamura-

総合スコア48

Java

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

0グッド

0クリップ

投稿2016/04/22 02:37

コード public class MainActivity extends Activity{ private FrameLayout frameLayout; CanvasView canvasview; Hanabi hanabi1 = new Hanabi(((Math.random()*600) + 50), ((Math.random()*50) + 150), 2000); Hanabi hanabi2 = new Hanabi(((Math.random()*600) + 50), ((Math.random()*50) + 150), 5000); @Override protected void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); frameLayout = new FrameLayout(this); frameLayout.setBackgroundColor(Color.BLACK); setContentView(frameLayout); canvasview = new CanvasView(this); frameLayout.addView(canvasview); /*hanabi1について*/ canvasview.setHanabi1(hanabi1); hanabi1.setCanvasView(canvasview); hanabi1.start(); /*hanabi2について*/ /*canvasview.setHanabi2(hanabi2); hanabi2.setCanvasView(canvasview); hanabi2.start();*/ } }
コード public class CanvasView extends View{ Paint paint = new Paint(); Hanabi hanabi1; Hanabi hanabi2; int select = 1; //描画切り替え public CanvasView(Context context){ super(context); } public void setHanabi1(Hanabi hanabi) { this.hanabi1 = hanabi; } public void setHanabi2(Hanabi hanabi) { this.hanabi2 = hanabi; } protected void onDraw(Canvas canvas){ if(select == 1){ paint.setStrokeWidth(5); canvas.drawPoint((float)hanabi1.X, (float)hanabi1.Y, paint); //canvas.drawPoint((float)hanabi2.X, (float)hanabi2.Y, paint); } else if(select == 2){ paint.setStrokeWidth(2); for(int i = 0; i < 1000; i++){ canvas.drawPoint((float)hanabi1.X2[i], (float)hanabi1.Y2[i], paint); } /*for(int i = 0; i < 1000; i++){ canvas.drawPoint((float)hanabi2.X2[i], (float)hanabi2.Y2[i], paint); }*/ } } }
コード public class Hanabi extends Thread{ private Handler handler = new Handler(); CanvasView canvasview; double G = 9.8*2; //重力加速度 double t; //経過時間(0.1秒毎) int time; //発射時刻 /*打ち上がり段階で使う定数*/ double X0; //初期のX座標 double Y0 = 1000; //初期のY座標(1000で固定) double X; //時刻t時のX座標 double Y; //時刻t時のY座標 double V0x = 0; //初速度のX成分(0で固定) double V0y; //初速度のY成分 double Vx; //時刻t時の速度のX成分 double Vy; //時刻t時の速度のY成分 /*爆発段階で使う定数*/ int hanabiball = 1000; //花火が分散する数 double angle[] = new double[hanabiball]; //発射する角度 double X02[] = new double[hanabiball]; //初期のX座標 double Y02[] = new double[hanabiball]; //初期のY座標 double X2[] = new double[hanabiball]; //時刻t時のX座標 double Y2[] = new double[hanabiball]; //時刻t時のY座標 double V02[] = new double[hanabiball]; //V0x2とV0y2の合成 double V0x2[] = new double[hanabiball]; //初速度のX成分 double V0y2[] = new double[hanabiball]; //初速度のY成分 double Vx2[] = new double[hanabiball]; //時刻t時の速度のX成分 double Vy2[] = new double[hanabiball]; //時刻t時の速度のY成分 /*Hanabiクラスのコンストラクタ*/ public Hanabi(double X0, double V0y, int time){ /*共通*/ this.time = time; /*打ち上がり段階*/ this.X0 = X0; this.V0y = V0y; X = X0; Vx = V0x; /*爆発段階*/ for(int i = 0; i < hanabiball; i++){ angle[i] = Math.random()*360; //全方向(0~360°) V02[i] = Math.random()*50; V0x2[i] = V02[i]*Math.cos(angle[i]*(Math.PI/180)); V0y2[i] = V02[i]*Math.sin(angle[i]*(Math.PI/180)); } } /*runメソッド*/ public void run(){ Y = 5000; //最初枠外に置いて隠しておく try{ Thread.sleep(time); //発射する時間を設定 } catch(InterruptedException e){ } /*打ち上がり段階*/ for(int T = 0; T < 1000 ; T++){ t = T * 0.15; Vy = (V0y - G*t); Y = (Y0 - (V0y*t - G*t*t/2)); try{ Thread.sleep(50); } catch(InterruptedException e){ } canvasview.paint.setColor(Color.WHITE); canvasview.paint.setAlpha(240-(3*T)); viewStart(); if(Vy < 0.2){ canvasview.select = 2; break; } } /*爆発段階*/ Arrays.fill(X02, X); Arrays.fill(Y02, Y); for(int T = 0; T < 30; T++){ t = T * 0.15; for(int i = 0; i < hanabiball; i++){ Vx2[i] = V0x2[i]; Vy2[i] = (V0y2[i] - G*t); X2[i] = (X02[i] + (Vx2[i]*t)); Y2[i] = (Y02[i] - (V0y2[i]*t - G*t*t/2)); } try{ Thread.sleep(50); } catch(InterruptedException e){ } canvasview.paint.setColor(Color.RED); canvasview.paint.setAlpha(240-(8*T)); viewStart(); } } public void viewStart(){ handler.post(new Runnable() { @Override public void run(){ canvasview.invalidate(); } }); } public void setCanvasView(CanvasView canvasview) { this.canvasview = canvasview; } }

上のプログラムは花火を描いたのもです。
インスタンス?hanabi1とhanabi2を作り花火が2発だけ上がるようになっています。

今上のプログラムはhanabi2の方をコメントアウトしているのでhanabi1しか打ちあがりません。
この状態で実行するとHanabiクラスに書かれている通り、打ち上がり段階は白色でだんだん透明になっていき、爆発段階も赤色でだんだん透明になっていきます。
色も打ち上がり段階と爆発段階で白と赤ではっきり分かれています。
「canvasview.paint.setColor(Color.WHITE);
canvasview.paint.setAlpha(240-(3T));

canvasview.paint.setColor(Color.RED);
canvasview.paint.setAlpha(240-(8
T));の部分」

次にコメントアウトを戻してhanabi2を追加して実行すると、花火自体はきちんと描画されているのですが、爆発するときに白色と赤色が混ざったり、透明になっていくのも急に明るくなったり変な動きをします。

調べると2つのスレッドで同じオブジェクトを使用したらダメらしく、今回CanvasView canvasview;同じオブジェクトを使用しているから変な動きをしたのかと思ったのですが、原因はこれなのでしょうか?
またどのように対処したらいいのでしょうか?
よろしくお願いします。

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

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

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

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

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

guest

回答1

0

ベストアンサー

原因は、その通りです。

対処としては、
CanvasViewが持っているPaintの変数をHanabiクラスに持たせて、
描画時にそれぞれのインスタンスにあるPaintの変数を使用したらいいだけです。

どこにPaint変数を持たせるかだけ、

Java

1public class CanvasView extends View{ 2 3 // こいつは、花火の描画に使わない 4 // Paint paint = new Paint(); 5 Hanabi hanabi1; 6 Hanabi hanabi2; 7 int select = 1; //描画切り替え 8 9// 省略 10}

Java

1public class Hanabi extends Thread{ 2 3 private Handler handler = new Handler(); 4 CanvasView canvasview; 5 6 // インスタンスごとに管理する!! 7 Paint paint = new Paint(); 8 9// 省略 10}

処理のほうは自分で適当に修正してください。

ほとんどの変数が、
パッケージプライベートになっているのが気になりますが、
この話はまた別の機会でしょうかね・・・

投稿2016/04/22 03:18

abs123

総合スコア1280

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

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

nakamura-

2016/04/22 04:19

回答ありがとうございます。 インスタンスごとにPaintを管理すればよかったんですね! ですが2つのスレッドは同じCanvasViewクラスのオブジェクトを使っていると思うのですが、CanvasViewクラスについては何もしなくていいのでしょうか? それとも、CanvasViewクラスの中のものでHanabiクラスで使われているのがPaintだけだからPaintをHanabiクラスに移してインスタンスごとに管理させたのですか? パッケージプライベートになっているのが気になりますが、 とありますが変数なにかまずかったですかね?
dsuzuki

2016/04/22 04:38

変数[int select]で打ち上げ時と爆発時を分けていますが、これも、hanabi1とhanabi2で異なる値が必要ですよね。(hanabi1爆破中に、hanabi2打ち上げとか) これもそれぞれのインスタンスで管理した方がいいです。
abs123

2016/04/22 06:58

>CanvasViewクラスについては何もしなくていいのでしょうか? →何もしなくても大丈夫です。 CanvasViewのpaintを操作している処理を除いてしまえば、 後は、handler使って全部UIスレッドに処理をさせている invalidate()の実行に使用しているだけになるため、 2つのスレッドから、という問題は解決できています。 >CanvasViewクラスの中のものでHanabiクラスで使われているのがPaintだけだからPaintをHanabiクラスに移してインスタンスごとに管理させたのですか? →YES? (実際あんまり考えてなかったので何ともいえません、そういった理由もありますし、 そもそもHanabiクラスで色を管理したほうがよさげだなと思ってたのもあります。 言うならば、このほうがしっくりきたって感じです。) パッケージプライベートの件については、「カプセル化」で検索してみてください。
nakamura-

2016/04/25 02:13

dsuzuki さん そうですね! int selectもインスタンスで管理したいと思います! ありがとうございます。 abs123 回答ありがとうございます^^ 確かに色はHanabiクラスで管理した方がいいかもですね! ありがとうございました! またカプセル化勉強します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問