Android : Intents crashing in simple android game

on Friday, April 17, 2015


I am making a simple game for android, however as I am kind of beginner sometimes I have some problems with basic things and errors in my code. What I am trying to do is:


• in GameActivity class, complete the finish() method so that the number of hits(score) can be returned to the MainMenu class. For the code below to work, you will need to create a getHitCount() method in the GameView class to return the hitCount.



public void finish(){
Intent returnIntent = new Intent();
returnIntent.putExtra("GAME_SCORE",gameView.getHitCount());
setResult(RESULT_OK, returnIntent);
super.finish();
}


• Check that the game score is displayed on by MainMenu class


The game is crashing everytime I press the back button, or sometimes the back button does not even respond and this is where I would appreciate your help.


GameActivity:



public class GameActivity extends Activity {

GameView gameView;// Reference the gameView



protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
// remove title bar
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Set the layout
setContentView(R.layout.game_view_container);
// Get the id of the layout
RelativeLayout mainscreen = (RelativeLayout) findViewById(R.id.mainscreen);
// Make the GameView
gameView = new GameView(this);
// Get data from intent and config gameView here

gameView.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT));
// Add GameView
mainscreen.addView(gameView);
}

/* Called when activity is done and should be closed.
* The ActivityResult is propagated back to whoever launched via onActivityResult()
*/
public void finish(){
Intent returnIntent = new Intent();
returnIntent.putExtra("GAME_SCORE",gameView.getHitCount());
setResult(RESULT_OK, returnIntent);
super.finish();
}
}


GameLoopThread:



public class GameLoopThread extends Thread {

private final static int FPS = 30; // How many times per second the game should be updated, drawn?
private final static int MAX_FRAME_SKIPS = 5; // Maximum number of frames to be skipped
private final static int FRAME_PERIOD = 1000 / FPS; // The time for one frame

// Surface holder that can access the physical surface.
private SurfaceHolder surfaceHolder;

private GameView gameView;//To link to GameView

// Holds the state of the game loop.
public boolean running;

public GameLoopThread(SurfaceHolder surfaceHolder, GameView gameView) {
super();
this.surfaceHolder = surfaceHolder;
this.gameView = gameView; // To link to GameView
}

@Override
public void run() {
Canvas canvas;
long startTime; // the time when the cycle begun
long timeDiff; // the time it took for the cycle to execute
int sleepTime; // ms to sleep (<0 if we're behind)
int framesSkipped; // number of frames being skipped

sleepTime = 0;

while(running){
canvas = null;

try {
canvas = this.surfaceHolder.lockCanvas(); // Try locking the canvas for exclusive pixel editing in the surface.
synchronized(surfaceHolder) {
startTime = System.currentTimeMillis();//of canvas locked
framesSkipped = 0; // Resetting the frames skipped.
gameView.update();//Update the assets
gameView.doDraw(canvas);//Draw on the surface
/* SYNCHRONISE THE LOOP CYCLE WITH THE FRAME PERIOD */
// First calculate how long the drawing/frame took.
timeDiff = System.currentTimeMillis() - startTime;
//Calculate the time to sleep to synch with frame time(period)
sleepTime = (int)(FRAME_PERIOD - timeDiff);

if (sleepTime > 0) {//Loop going faster than Frame, so sleep
try {
// Send the thread to sleep for a short period.
Thread.sleep(sleepTime);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

while (sleepTime < 0 && framesSkipped < MAX_FRAME_SKIPS) {
// We need to catch up, so we update without drawing the game to the screen.
sleepTime += FRAME_PERIOD; // Add FRAME_PERIOD to check while condition again.
framesSkipped++;
}

}
} catch(Exception e) {
e.printStackTrace();
} finally {
// In case of an exception the surface is not left in an inconsistent state.
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);//All in synch - unlock canvas
}
}
}
}
}


GameView:



public class GameView extends SurfaceView implements SurfaceHolder.Callback {



/* Member (state) fields */
private GameLoopThread gameLoopThread;
private Paint paint; //Reference a paint object
private Paint paint2; //Reference a paint object

/** The drawable to use as the background of the animation canvas */
private Bitmap mBackgroundImage;
private Sprite sprite;
private int hitCount;

/* For the countdown timer */
private long startTime ; //Timer to count down from
private final long interval = 1 * 1000; //1 sec interval
private CountDownTimer countDownTimer; //Reference to class
private boolean timerRunning = false;
private String displayTime; //To display time on the screen

private boolean gameOver;


public GameView(Context context) {
super(context);
// Focus must be on GameView so that events can be handled.
this.setFocusable(true);
// For intercepting events on the surface.
this.getHolder().addCallback(this);

mBackgroundImage = BitmapFactory.decodeResource(this.getResources(),
R.drawable.game_background);

}
/* Called immediately after the surface created */
public void surfaceCreated(SurfaceHolder holder) {
mBackgroundImage = Bitmap.createScaledBitmap(mBackgroundImage, getWidth(), getHeight(), true);
// We can now safely setup the game start the game loop.
ResetGame();//Set up a new game up - could be called by a 'play again option'
gameLoopThread = new GameLoopThread(this.getHolder(), this);
gameLoopThread.running = true;
gameLoopThread.start();
}

/* Countdown Timer - private class */
private class MyCountDownTimer extends CountDownTimer {

public MyCountDownTimer(long startTime, long interval) {
super(startTime, interval);
}
public void onFinish() {
displayTime = "Times Over!";
timerRunning = false;
countDownTimer.cancel();
gameOver = true;
}
public void onTick(long millisUntilFinished) {
displayTime = " " + millisUntilFinished / 1000;
}
}//End of MyCountDownTimer



//To initialise/reset game
private void ResetGame(){
gameOver = false;
/* Set paint details */
paint = new Paint();
paint.setColor(Color.WHITE);
paint.setTextSize(50);
paint2 = new Paint();
paint2.setColor(Color.RED);
paint2.setTextSize(200);

sprite = new Sprite(this);

hitCount = 0;
//Set timer
startTime = 10;//Start at 60s to count down
//Create new object - convert startTime to milliseconds
countDownTimer=new MyCountDownTimer(startTime*1000,interval);
countDownTimer.start();//Start it running
timerRunning = true;
}

//This class updates and manages the assets prior to drawing - called from the Thread
public void update(){
if(gameOver == false){
sprite.update();
}
}
/**
* To draw the game to the screen
* This is called from Thread, so synchronisation can be done
*/
public void doDraw(Canvas canvas) {
canvas.drawBitmap(mBackgroundImage, 0, 0, null);
//Draw all the objects on the canvas
canvas.drawText("Hit Count: "+hitCount,5,40, paint);
canvas.drawText("Time Left: "+displayTime,5,90, paint);

if(gameOver == true){
canvas.drawText("GAME",300,700, paint2);
canvas.drawText("OVER!",300,900, paint2);
}

sprite.draw(canvas);
}

//To be used if we need to find where screen was touched
public boolean onTouchEvent(MotionEvent event) {
if (sprite.wasItTouched(event.getX(), event.getY())){
/* For now, just renew the Sprite */
if(gameOver == false){
sprite = new Sprite(this);
hitCount++;
}
}
return true;
}

public int getHitCount(){
return hitCount;
}

public void surfaceDestroyed(SurfaceHolder holder) {
gameLoopThread.running = false;

// Shut down the game loop thread cleanly.
boolean retry = true;
while(retry) {
try {
gameLoopThread.join();
retry = false;
} catch (InterruptedException e) {}
}
}

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

}
}


and MainMenu:



public class MainMenu extends Activity {

private static final int SCORE_REQUEST_CODE = 1;// The request code for the intent

TextView tvScore;
String score;
Intent gameIntent;

protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.game_start);
}

public void startGame(View v){
gameIntent = new Intent(this,GameActivity.class);
startActivityForResult(gameIntent, SCORE_REQUEST_CODE );
}
/* Create Options Menu */
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}

// Respond to item selected on OPTIONS MENU
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
switch (item.getItemId()) {
//put data in Intent
case R.id.easy:
Toast.makeText(this, "Easy chosen", Toast.LENGTH_SHORT).show();
return true;
case R.id.medium:
Toast.makeText(this, "Medium chosen", Toast.LENGTH_SHORT).show();
return true;
case R.id.hard:
Toast.makeText(this, "Hard chosen", Toast.LENGTH_SHORT).show();
return true;
case R.id.other:
Toast.makeText(this, "Other chosen", Toast.LENGTH_SHORT).show();
return true;
default:
return super.onOptionsItemSelected(item);
}
}

protected void onActivityResult(int requestCode, int resultCode, Intent retIntent) {
// Check which request we're responding to
if (requestCode == SCORE_REQUEST_CODE) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
if (retIntent.hasExtra("GAME_SCORE")) {
int scoreFromGame = retIntent.getExtras().getInt("GAME_SCORE");
tvScore.setText(""+Integer.toString(scoreFromGame));
}
}
}

}
}

0 comments:

Post a Comment