I am creating a demo game in Android for learning purposes. In the game, when a collision is detected between two objects - I want to show a "game over" dialog. Inside the dialog box there is a play again button. When pressed, the thread should be started again.
I am getting the following error java.lang.IllegalThreadStateException: Thread already started
.
Here is my code:
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();
}
}
When the game is over, just stop the thread and play again button should kick a new thread.
If you need to save any instance of your previous thread, do save them in external variables. There are plenty of options in this case anyway.
Edit
You stopped your thread perfectly. You just have to start a new thread when you want the new game to be started.
I would suggest to keep a function like this and remove
implements Runnable
.