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

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

ただいまの
回答率

90.01%

花火を時間差であげる方法

解決済

回答 3

投稿

  • 評価
  • クリップ 0
  • VIEW 1,174

daichanman123

score 30

コード
public class MainActivity extends Activity implements Runnable{


     Handler mHandler;
     Thread thread;
     FrameLayout frameLayout;

     SampleView sv;

     ArrayList<Hanabi> list = new ArrayList<Hanabi>();
     Hanabi hanabi1 = new Hanabi(150.0);
     Hanabi hanabi2 = new Hanabi(120.0);

     int time = 0;    
     double mul = 0.15;

    @Override
    protected void onCreate(Bundle savedInstanceState){
        super.onCreate(savedInstanceState);

        frameLayout = new FrameLayout(this);
        setContentView(frameLayout);

        sv = new SampleView(this);

        list.add(hanabi1);
        list.add(hanabi2);
        sv.setHanabi(list);

        frameLayout.addView(sv);

        mHandler = new Handler();

        thread = new Thread(this);
        thread.start();
    }


     @Override
     public void run(){

         hanabi1.setX();
         hanabi2.setX();

         for(time = 0; time < 1000; time++){

             try{
                 Thread.sleep(50);
             }
             catch(InterruptedException e){
             }

             hanabi1.setY(time * mul);
             hanabi2.setY(time * mul);

             mHandler.post(new Runnable(){
                 @Override
                 public void run(){
                     sv.invalidate();
                 }
             });
         }
     }
}
コード
public class SampleView extends View{


    Paint paint = new Paint();
    ArrayList<Hanabi> hanabi;


    public SampleView(Context context) {
        super(context);
    }


    public void setHanabi(ArrayList<Hanabi> hanabi){
        this.hanabi = hanabi;
    }


    protected void onDraw(Canvas canvas){
        paint.setColor(Color.RED);
        paint.setStrokeWidth(10);
        canvas.drawPoint(hanabi.get(0).getX(), hanabi.get(0).getY(), paint);
        canvas.drawPoint(hanabi.get(1).getX(), hanabi.get(1).getY(), paint);
    }
}
コード
public class Hanabi{


    int x;
    int y;

    double V0x = 0.0;
    double V0y;

    double Vx = 0.0;
    double Vy;

    double G = 9.8*2;


    /*Hanabiクラスのコンストラクタ*/
    public Hanabi(double V0y){
        this.V0y = V0y;
    }


    public void setX(){
        this.x = (int)(Math.random()*700) + 50;
    }

    public void setY(double time){
        this.y = (int)(800 - (V0y*time - G*time*time/2));
    }

    public void setVy(double time){
        this.Vy = V0y - G*time;
    }


    public int getX(){
        return this.x;
    }

    public int getY(){
        return this.y;
    }

    public double getVy(){
        return this.Vy;
    }
}


前回の続きで同じような質問になりますがよろしくお願いします!
上のプログラムは花火の打ちあがりの部分だけのプログラムです。

Hanabiクラスを作り、xやyなどを持たせて、
Hanabi hanabi1 = new Hanabi(150.0);
Hanabi hanabi2 = new Hanabi(120.0);
のように2つインスタンス化?しました。
今、MainActivityクラスのrunメソッドで
hanabi1.setX();
hanabi2.setX();
hanabi1.setY(time * mul);
hanabi2.setY(time * mul);
のように2つ(hanabi1とhanabi2)を同じところに書いているのですが、これだと実行すると同時に花火が上がってしまいます。
hanabi2.setY(time * mul);のtimeを(time-10)*mulのように書き換えると、時間差で花火を上げることができたのですが、これだとあとで面倒なことになるので他の方法でしたいと思っています。
hanabi1に対してrunメソッドの動作を行って、t秒後にhanabi2に対してもrunメソッドの動作を行って、そのときの2つの位置を描画すればいいと思うのですが、プログラムをどのように書いたらいいのかがわかりません。
この考えが間違っているかもしれませんが・・

私のこの考えはどうでもいいんですけど、
花火を時間をあけて打ち上げるにはどのように修正したらいいのでしょうか?
よろしくお願いします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

+1

花火1つにつき1つスレッドを用意したらどうでしょう。

Thread hanabi1 =new Thread(new Runnable(){略});

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/13 14:40

    ですね。

    開始直後に花火を打ち上げるとするなら、打ち上げ開始時間t=0と考えて
    long diffTime = time; とできますよね?

    キャンセル

  • 2016/04/13 14:45

    t=0ならできますね

    キャンセル

  • 2016/04/13 14:59

    ありがとうございます。
    ということはHanabiクラスでは現在時間timeのときの座標や速度を持たせるということですかね?

    キャンセル

checkベストアンサー

0

今の状態からなら、各Hanabiに打ち上げ時刻を設定するのが簡単です。

hanabi2.setY(time * mul);のtimeを(time-10)*mulのように書き換えると、時間差で
花火を上げることができたのですが、これだとあとで面倒なことになるので
他の方法でしたいと思っています。 

この方法ですね。10=打ち上げ時刻だろうと思います。
これをHanabiにsetStartTime(10)のような感じで与えて(setHanabiみたいな感じです)、
getStartTime()のような方法で取得できるようにすると以下のようにできます。

hanabi1.setY((time - hanabi1.getStartTime()) * mul);
hanabi2.setY((time - hanabi2.getStartTime()) * mul);

setYに負の値が与えられることになるので、内部でガードした方が良いでしょう。
この方法の弱点としては、最初に打ち上げ時刻が決定している必要があるというところです。
目指す場所(プログラムの仕様)によっては、プログラムの構造を見直したほうが良いです。
この場合、例えばPineMatsuさんのような方法を検討することになると思います。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

具体的なプログラミングではなくて考え方だけですが、打ち上げの軌跡を決める処理をHanabiクラスの中に持って行ったほうがいいと思います。
クラスの外部からは点火だけ行い、点火されたら軌跡の設定はHanabiクラスの中で行うのです。
外部からは、軌跡を描かせるために一定周期で軌跡を描くメソッドを呼び出します。
時間差をつける場合は、時間差のパラメータをHanabiクラスに持たせ、その時間が経過するまでは最初に位置に留まるようにします。
実際の花火も、花火師が点火した後は花火任せのはずです。それと同じように考えたらどうでしょうか?

追記:
折角Hanabi をクラスオブジェクトにしているので、花火をもっとオブジェクトとして考えましょう。つまり、点火は自分ではできないが、点火された後は自分で設定されたパラメータ動くようにするわけです。
他の方が書かれているようにスレッドとして動かしてもいいかもしれません。(スレッド起動が点火になるわけです)
そうすれば、個々の花火に色々な性格を持たせることができます。打ち上げ速度やどこまで高く上がるかなどなど。
今のように位置を外部で決める形だと、花火の種類など全て外部で決める必要が出てきます。(どこで中の小玉が弾けだすかなど)

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/04/12 14:06

    Hanabiクラスで軌跡を決定というのはMainActivityクラスの
    for(time = 0; time < 1000; time++){
    try{
    Thread.sleep(50);
    }
    catch(InterruptedException e){
    }
    をHanabiクラスに移して毎時間ごとの位置を全て設定すればいいのでしょうか?

    キャンセル

  • 2016/04/12 17:03

    ざっくり言うとそういうことになります。
    軌跡を描く方法はいくつか考えられると思います。直線の式を組み込んで時間を引数に位置を決めたり、ポイントを幾つか保持しておいて各ポイントを直線補間するなどです。
    そういったXとYの座標を決める処理をHanabiクラスに組み込んでしまうということです。
    花火は時間経過とともに位置が変わるはずなので、時間経過に伴って位置が変わるような処理をHanabiクラスに組み込むわけです。
    まあ、実際の花火の動きに近づけるには、重力に逆らって打ち上げるわけなので、時間経過とともに上がる速度は落ちていくはずです。(こういう細かい処理は後からHanabiクラスを組み替えたりすればできると思うので、まずはそういうのを無視して一定時間で一定高さまで単位時間毎に移動するような処理でいいと思います。)
    イメージ的には、MainActivityが花火師の役割になるわけです。
    そうやって実際の花火の各機能をオブジェクトとしてプログラムしていけば、複雑なものも単機能の集まりとして記述することができるようになるはずです。
    うまく作れば、花火シミュレータ的なものを作るところまで行けると思います。

    キャンセル

  • 2016/04/12 17:29

    回答ありがとうございます。
    時間経過とともに上がる速度は落ちていくのはできています!
    MainActivityで花火を打ち上げるスタートの処理だけしてあとはHanabiクラスで処理するということですかね!

    今Hanabiクラスはセッターやゲッターである時間のy座標や速度を設定していますが、全ての時間のy座標や速度を設定するということですよね?

    public void setY(){
        for(int time = 0; time > 1000; time++){
            try{
                Thread.sleep(50);
    }
    catch(InterruptedException e){
    }

    double t = time * 0.15;
    this.y[time] = (float) (800 - (V0y*t - G*t*t/2));
    }
    }

    public void setVy(){
    for(int time = 0; time > 1000; time++){

    try{
    Thread.sleep(50);
    }
    catch(InterruptedException e){
    }

    double t = time * 0.15;
    this.Vy[time] = (float) (V0y - G*t);
    }
    }
    こういうことでいいのでしょうか?

    キャンセル

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

  • ただいまの回答率 90.01%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る