2017-01-06 59 views
0

我在Android中爲學習目的創建了一個演示遊戲。在遊戲中,當兩個對象之間發現碰撞時 - 我想顯示「遊戲結束」對話框。在對話框裏面有一個再次播放按鈕。按下後,線程應該重新啓動。如何在Android遊戲中重新啓動Java線程?

我收到以下錯誤java.lang.IllegalThreadStateException: Thread already started

這裏是我的代碼:

public class GamePanel extends SurfaceView implements Runnable { 

    private Thread thread = null; 
    private Ball ball; 
    private SurfaceHolder surfaceHolder; 
    private Paint paint; 
    private Canvas canvas; 

    volatile boolean playing = true; 

    private int hurdleCount = 3; 
    private Hurdles[] hurdles; 

    private int screenX, screenY; 
    private Rect ball_detectCollision; 

    public GamePanel(Context context, final int screenX, final int screenY) { 
     super(context); 

     ball = new Ball(context, screenX, screenY); 
     surfaceHolder = getHolder(); 

     this.screenX = screenX; 
     this.screenY = screenY; 

     paint = new Paint(); 
     canvas = new Canvas(); 

     hurdles = new Hurdles[hurdleCount]; 
     for (int i = 0; i < hurdleCount; i++) { 
      hurdles[i] = new Hurdles(context, screenX, screenY); 
     } 

     ball_detectCollision = new Rect(ball.getBall_x(), ball.getBall_y(), ball.getBitmap().getWidth(), ball.getBitmap().getHeight()); 
     surfaceHolder.addCallback(new SurfaceHolder.Callback() { 

      @Override 
      public void surfaceCreated(SurfaceHolder holder) { 

       System.out.println("Surface Created"); 
       setUpdated_x(ball.getBall_x()); 
      } 

      @Override 
      public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 

       System.out.println("Surface Changed"); 
       thread = new Thread(GamePanel.this); 
       thread.start(); 
      } 

      @Override 
      public void surfaceDestroyed(SurfaceHolder holder) { 

       System.out.println("Surface Destroyed"); 
      } 
     }); 
    } 

    public int getUpdated_x() { 
     return updated_x; 
    } 

    public void setUpdated_x(int updated_x) { 
     this.updated_x = updated_x; 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 

     setUpdated_x((int) event.getX()); 

     switch (event.getAction() & MotionEvent.ACTION_MASK) { 

      case MotionEvent.ACTION_UP: 

       break; 

      case MotionEvent.ACTION_DOWN: 

       initial_X = getUpdated_x(); 
       break; 

      case MotionEvent.ACTION_MOVE: 

       if (getUpdated_x() < screenX - ball.getBitmap().getWidth() || getUpdated_x() > screenX - ball.getBitmap().getWidth()) { 
        draw(getUpdated_x()); 
       } 
       break; 
     } 
     return true; 
    } 

    private void draw(int updatedValue) { 

     canvas = surfaceHolder.lockCanvas(); 
     canvas.drawColor(Color.RED); 
     canvas.drawBitmap(ball.getBitmap(), updatedValue, ball.getBall_y(), paint); 
     ball.setBall_x(updatedValue); 

     ball_detectCollision.left = ball.getBall_x(); 
     ball_detectCollision.top = screenY - ball.getBitmap().getHeight() - 260; 
     ball_detectCollision.right = ball.getBall_x() + ball.getBitmap().getWidth(); 
     ball_detectCollision.bottom = screenY - ball.getBitmap().getHeight() - 260 + ball.getBitmap().getHeight(); 

     for (int i = 0; i < hurdleCount; i++) { 
      canvas.drawBitmap(hurdles[i].getBitmap(), hurdles[i].getX(), hurdles[i].getY(), paint); 
     } 
     surfaceHolder.unlockCanvasAndPost(canvas); 
    } 

    @Override 
    public void run() { 

     while (playing) { 
      update(); 
      draw(getUpdated_x()); 
      control(); 
     } 
    } 

    private void update() { 

     for (int i = 0; i < hurdleCount; i++) { 
      hurdles[i].update(); 

      if (Rect.intersects(getBall_detectCollision(), hurdles[i].getDetectCollision())) { 
       System.out.println("Collision Detected"); 

       playing = false; 
       Handler handler = new Handler(Looper.getMainLooper()); 
       handler.post(new Runnable() { 
        @Override 
        public void run() { 
         showGameOverMessage(); 

        } 
       }); 
      } 
     } 
    } 


    public void pause() { 

     playing = false; 
     try { 
      thread.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    private void showGameOverMessage() { 

     Toast.makeText(getContext(), "Game Over", Toast.LENGTH_SHORT).show(); 
     Dialog showDialog = new Dialog(getContext()); 
     showDialog.setContentView(R.layout.dialog_game_over); 
     Button playAgainButton = (Button) showDialog.findViewById(R.id.playAgainButton); 
     playAgainButton.setOnClickListener(new OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       playing = true; 
       thread.start(); 
      } 
     }); 
     showDialog.show(); 

    } 
} 
+0

()'你應該調用'thread.start()'之前創建一個新的線程,但我不能運行你的代碼,看看是否需要別的東西 – nandsito

+0

我創建了新的實例,但錯誤保持不變 – AbhayBohra

回答

3

您不能重新啓動已停止的線程。解決方案是簡單地實例化一個新的並啓動它。

+0

我試過了,但不起作用 – AbhayBohra

0

當遊戲結束時,只需停止線程並再次播放按鈕即可踢出新線程。

如果您需要保存上一個線程的任何實例,請將它們保存在外部變量中。無論如何,這種情況下有很多選擇。

編輯

你完全停止您的線程。當您想要開始新遊戲時,您只需開始一個新線程。

我建議保留這樣的功能並刪除implements Runnable

private void startGame() { 
    // Start a new game 
    playing = true; 

    Thread thread = new Thread() { 
     @Override 
     public void run() { 
      try { 
       while (playing) { 
        update(); 
        draw(getUpdated_x()); 
        control(); 
       } 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    }; 

    thread.start(); 
} 
在`showGameOverMessage
+0

如何停止線程?我試圖創建新的實例,但它不工作 – AbhayBohra

+0

請參閱更新的答案。 –

+0

不能不工作..問題依然如此 – AbhayBohra