2016-05-15 13 views
7

SHORT概要Androidのない同期

forループと遅延が、私は活動のゲームを持っています。ユーザーは、画像をクリックします。

First level of game

Second level of game

ユーザーがクリックすると、正しいものを選択するために5秒を持っています。 5秒後、正しい画像ビューが注意を引くために異なって表示され、5秒後に再び次のレベルが表示されます。

ユーザーは5秒間待たずにクリックできるので、クリックするとすぐに次のレベルに移動する必要があります。

私は動的にビューとイメージビューを作成しています。 Imageviewsはローカルデータベースsqliteからバイトとして送られています。

私のメソッドは、oncreateメソッドの中に作成しています。私はforループとwhileループを使用します。各反復はゲームのレベルです。各レベルには、イメージビューとイメージビューの数が異なります。

5 + 5秒の遅延のために、私はハンドラ、スレッド、countdowntimersを使用しなければなりませんでした。それぞれが問題を引き起こしました。

ハンドラを使用しているときに、ユーザーが5秒前にクリックしたときに、現在のセッションを終了できませんでした。

これが正しいかどうかわかりません。

あなたは下の私のコードを見ることができます:LONG説明とCODES

タイマー:

nCreate() { 
      for (int i = 0; i < 2; i++) { 
       handler.postDelayed(new Runnable() { 
        public void run() { 

         imageAnswer.setImageBitmap(bmp); 

         imageAnswer.setId(R.id.imgAnswer); 
         //adding image to screen 
         finalRLayout.removeAllViews(); 
         finalRLayout.addView(imageAnswer, rLayParams); 

         //starting timer, if no answer in 5 seconds, run again timer 
         startTimer(); 

         //clicklisterner 
         imageAnswer.setOnClickListener(new View.OnClickListener() { 
          @Override 
          public void onClick(View view) { 
           //if clicks true, cancel timer and go to next iteration of for loop 
           if (view == findViewById(R.id.imgAnswer)) { 
            Log.d(TAG, "clicked"); 
            //PUT IN CODE HERE TO GET NEXT IMAGE 
            cancelTimer(); 

           } else { //if not true, run again timer for last chance 
            Log.d(TAG, "nonclick"); 
            cancelTimer(); 
            startTimer(); 

           } 
          } 
         }); 
        } 
       }, 2000 * i); 


      } //for end 

     } //oncreate end 

    //start timer function 
    void startTimer() { 
     cTimer = new CountDownTimer(5000, 1000) { 
      public void onTick(long millisUntilFinished) { 
       Log.d(TAG, "ontick"); 
      } 
      public void onFinish() { 
       Log.d(TAG, "timer onfinish"); 
      } 
     }; 
     cTimer.start(); 
    } 


    //cancel timer 
    void cancelTimer() { 
     Log.d(TAG, "canceltimer"); 
     if (cTimer != null) 
      cTimer.cancel(); 
    } 

3異なるスレッド操作をしかし、うまくいきませんでした。そのうちの1人が画面を黒い画面にしました。他の2人はループの進行を阻止しなかった。あなたがゲームを実装するために、より専門的なものを使用する必要があり、ゲーム開発のために

runnable version 






    for (int i = 0; i< 20 ; i++) { 
      Log.d(TAG, "for i2="+ i); 
      final int finalI = i; 
      final RelativeLayout finalRLayout = rLayout; 



      final Runnable r=new Runnable() { 

       @Override 
       public void run() { 
        Log.d(TAG, "for finali2="+ finalI); 
        TrainingObject trainingObject = new TrainingObject(); 
        trainingObject = trainingObjectList.get(finalI); 
        objectCount = 2; 
//test icin 
        Log.d(TAG,"testicin trainingobjectid: "+trainingObject.getTrainingobjectID()); 
        object = dbHandler.getObjectObject(trainingObject.getTrainingobjectAnswer()); 




        RelativeLayout.LayoutParams rLayParams = new RelativeLayout.LayoutParams(140,140); 

        rLayParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT); 
        rLayParams.addRule(RelativeLayout.CENTER_IN_PARENT); 

        imgBytes = object.getObjectImageBlob(); 
        bmp = BitmapFactory.decodeByteArray(imgBytes, 0, imgBytes.length); 

        imageAnswer.setImageBitmap(bmp); 
        imageAnswer.setTag(trainingObject.getTrainingobjectAnswer()); 
        imageAnswer.setId(R.id.imgAnswer); 
        finalRLayout.removeAllViews(); 
        finalRLayout.addView(imageAnswer,rLayParams); 

       } 
      }; 
      Log.d(TAG, "3000i2 sonrasi"); 

      handler.postDelayed(r, 6000 * i); 
      imageAnswer.setOnClickListener(new View.OnClickListener() { 
       @Override 
       public void onClick(View view) { 
        if (view == findViewById(R.id.imgAnswer)) { 
         Log.d(TAG, "clicked");handler.removeCallbacks(r); handler.postDelayed(r, 0); 
         //PUT IN CODE HERE TO GET NEXT IMAGE 

        } 
        else{ 
         Log.d(TAG, "nonclick"); 
         handler.removeCallbacks(r); handler.postDelayed(r, 6000); 

        } 
       } 
      }); 

     }//for end 
+2

この質問をボトムアップで読むことになっていますか? – fiipi

+2

これは問題ではありません。 – Simas

+0

あなたは[AlarmManager](https://developer.android.com/reference/android/app/AlarmManager.html)を使ってみましたか –

答えて

2

は、私はあなたがそれはあなたから学ぶことができる様々なオプションを備えた2Dおよび3Dゲームへの基礎を持っているこの本Beginning Android Games 2nd Editionを読むことをお勧めします。 今、あなたのコードのために私はあなたが外部のスレッドで時間を追跡し、それはあなたがメインのゲーム活動 例に実装するインターフェイスへのコールバックを送信するためにお勧め:

TimeThread.java

import android.util.Log; 

public class TimeThread implements Runnable { 
    Thread thread = null; 

    TimeTickListener listener; 
    volatile boolean running = false; 

    public TimeThread(TimeTickListener listener) { 
     this.listener = listener; 

    } 

    public void resume() { 

     thread = new Thread(this); 
     running = true; 
     if (thread != null) 
      thread.start(); 
    } 

    @Override 
    public void run() { 

     while (running) { 
      // sending callbacks to the mainActivity 
      listener.onTimeTick(); 

     } 
    } 

    public void pause() { 
     running = false; 
     while (true) { 
      try { 
       thread.join(); 
       Log.v("my", "joined "); 
       break; 
      } catch (InterruptedException e) { 
       Log.v("my", "not joined cause : " + e.getMessage()); 

      } 

     } 

    } 

} 

我々が使用するインターフェイス:

public interface TimeTickListener { 
public void onTimeTick(); 
} 

、ここではmainActivityがどのように見えるべきであるものの一例です

MainActivity。Javaの

public class MainActivity extends Activity implements TimeTickListener { 

    long startTime = System.nanoTime(); 
    // the interface method that we implemented 
    @Override 
    public void onTimeTick() { 
     // keep trace of the time untill it sums up to 1 sec then do an action 
     // in your situation you can make it to count 5 sec 
     // and make your action here 
     if ((System.nanoTime() - startTime)/1000000000 >= 1) { 

      totalTime += 1; 

      // this handler is because you should change the textView from its 
      // original thread 
      // and it is not allowed to be edited from another thread 
      // in your case you should change the imageViews like this in the main thread 
      mainHandler.post(new Runnable() { 

       @Override 
       public void run() { 
        text.setText(totalTime + " seconds passed "); 
       } 
      }); 

      startTime = System.nanoTime(); 

//   and this is how to terminate the thread manually (optional) 
      if (totalTime >= 10) { 

       timeThread.pause(); 
      } 

     } 

    } 

    Handler mainHandler; 
    TextView text; 
    float totalTime = 0; 
    TimeThread timeThread; 
    TimeTickListener listener; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     text = new TextView(this); 
     text.setText("wait..."); 
     setContentView(text); 
// initializing the handler with the main activity looper 
     mainHandler = new Handler(getMainLooper()); 
//getting our implemented listener to pass it to the timeThread for the callbacks 
     listener = (TimeTickListener) this; 
     timeThread = new TimeThread(listener); 
     // resume method will launch the thread and make it start calling the interface method (onTimeTick) 
     timeThread.resume(); 

    } 

    @Override 
    protected void onPause() {  

//  don't forget to pause the thread here 
     timeThread.pause(); 
     super.onPause(); 
    } 
} 

このコードは、時間が正確で非常によく同期され、テストされ、大きな成功を収めて行われています。

しかし、それは2番目のスレッドのwhileループが非常に多くの利点を持ち、アプリケーションを正しく制御できるようになるため、少し複雑でリソースが少し消費されます。

この回答は時間トレーススレッドを処理する方法とアクションを行う方法ですが、ゲームロジックに問題がある場合や、そのような場合にユーザーにイメージを隠して表示することが困難な場合これはあなたが欲しい答えではないので私に教えてください。私はあなたを助けてくれるでしょう。

3

目的を達成するためにハンドラを使用するだけで、実行可能ファイルを作成してハンドラの外に宣言し、postDelayedハンドラ内の名前で使用し、ユーザがクリックすると、すべてのハンドラコールバック:

// first create runnable 
Runnable r = new Runnable{ 
    public void run(){ 
     //do what you need to do after 5 seconds 
    } 
} 

// then create handler 
Handler mHandler = new Handler(); 

// then in your onCreate method 
nCreate() { 
     for (int i = 0; i < 2; i++) { 
      handler.postDelayed(new Runnable() { 
       public void run() { 

        imageAnswer.setImageBitmap(bmp); 

        imageAnswer.setId(R.id.imgAnswer); 
        //adding image to screen 
        finalRLayout.removeAllViews(); 
        finalRLayout.addView(imageAnswer, rLayParams); 

        //starting handler, if no answer in 5 seconds, run again timer 
        mHandler.postDelayed(r, 5000); 

        //clicklisterner 
        imageAnswer.setOnClickListener(new View.OnClickListener() { 
         @Override 
         public void onClick(View view) { 
          //if clicks true, cancel timer and go to next iteration of for loop 
          if (view == findViewById(R.id.imgAnswer)) { 
           Log.d(TAG, "clicked"); 
           //PUT IN CODE HERE TO GET NEXT IMAGE 
           myHandler.removeCallbacks(r); 

          } else { //if not true, run again timer for last chance 
           Log.d(TAG, "nonclick"); 
           // stop the handler 
           myHandler.removeCallbacks(r); 
           // run a new one 
           mHandler.postDelayed(r, 5000); 

          } 
         } 
        }); 
       } 
      }, 2000 * i); 


     } //for end 

    } //oncreate end 
関連する問題