I need to stop the timer and run a frame animation - java

I have a game where image Views changes on a timer. When a button is clicked (stop) the update is called to update score and spins. I need to stop when the whammy(); is called and run a frame animation then start the timer back when the animation has ended. I have tried to call sleep(2500); but it cause the everything to wait the 2.5 seconds and the frame animation then runs with the image view timer. That just won't work for what I need. Below is the section of code I need help with:
public void onClick(View v) {
if (v.getId() == R.id.btstop) {
final Button bstop = (Button) findViewById(R.id.btstop);
bstop.setEnabled(false);
updateState();
}
}
/**
* set random view. get random 1 point from class utils and display to 1
* position random
*/
public void setRandomView() {
int item = new Random().nextInt(18);
current = Utils.getAPoint();
int img = current.getImg();
int score = current.getScore();
int spin = current.getSpin();
iv[item].setImageResource(img);
dataPoint.get(item).setImg(img);
dataPoint.get(item).setScore(score);
dataPoint.get(item).setSpin(spin);
ivcenter.setImageResource(img);
}
/**
* display Name,score & spin to screen
*/
public void setPoint() {
tvspin.setText(spins + "\n" + name);
tvpoint.setText(point + "");
}
/**
* Start Thread Sets the speed of the game board Enable STOP button to true
*
* #param time
*/
public void start(int time) {
countDownTimer = new CountDownTimer(time, 300) {
#Override
public void onTick(long millisUntilFinished) {
// call to set random view
setRandomView();
}
#Override
public void onFinish() {
// TODO Auto-generated method stub
}
}.start();
}
/**
* stop timer thread
*/
public void stop() {
try {
countDownTimer.cancel();
} catch (Exception e) {
// TODO: handle exception
} finally {
}
}
/**
* update state game and check what tile is in the center
*/
public void updateState() { // get score,spin current point
int scoreCurrent = current.getScore();
int spinCurrent = current.getSpin();
spins--;// Take one from spins
// if score = 2, that mean to double score
if (scoreCurrent == 2) {
point = point * 2;
playmp3(R.raw.correct);
}
// if score = 0, that means tile is a whammy
if (scoreCurrent == 0) {
playmp3(R.raw.buzz);
whammy();// I need to put everything else on hold here and animation here
point = 0;// sets the score to 0
whammy++; // Add a whammy to the whammy count
// Display the whammy that was added
for (int i = 0; i < whammy; i++) {
popup[i].setVisibility(View.VISIBLE);
}
// sleep(2500);
if (whammy == 4) {
stop();
stopmp3();
callFinish();
}
}
// else ,score = score current + point.getscore
else {
playmp3(R.raw.correct);
point = point + scoreCurrent;
}
// spins--;// Take one from spint
// if spin > 0, that mean is add a spin
if (spinCurrent > 0) {
spins = spins + spinCurrent;
}
setPoint(); // display spin,score and name to screen
sleep(2000); // Adds a delay so that the whammy pop up can be seen
// if spint >0 start new data random
if (spins > 0) {
stop();
final Button bstop = (Button) findViewById(R.id.btstop);
bstop.setEnabled(true);
start(10000 * 60 * 60 * 24);
} else {
// stop all
stop();
stopmp3();
// if spin < 2, that round <2 move to spin activity
if (round < 2) {
Intent it = new Intent(getBaseContext(), SpinActivity.class);
startActivity(it);
finish();
}
// else move to high score activity
else {
callFinish();
}
}
}
private void whammy() {
// set up the whammy act animation
final ImageView act = (ImageView) findViewById(R.id.whammyact);
act.setBackgroundResource(R.drawable.tnt_animation);
actAnim = (AnimationDrawable) act.getBackground();
actAnim.setVisible(true, true);
}

OK Here are the changes that were made to make the animation run and finish before the game timer gets started back...
IF THERE ARE QUESTION OR ANYONE NEED HELP FEEL FREE TO ASK.
if (scoreCurrent == 0) {
countDownTimer.cancel();
countDownTimer = null;
// Use Timer to set visibility to GONE after the animation finishes.
TimerTask timerTask = new TimerTask(){
#Override
public void run() {
PressActivity.this.runOnUiThread(new Runnable(){
public void run() {
resumeLogicAfterPress();
}
});}};
Timer timer = new Timer();
timer.schedule(timerTask, getWhammyAnimationTotalDuration(actAnim));
} else {
resumeLogicAfterPress();
}
}
public void resumeLogicAfterPress() {
// Display the whammy that was added
for (int i = 0; i < whammy; i++) {
popup[i].setVisibility(View.VISIBLE);
}
sleep(2500); //Adds a delay so that the whammy pop up can be seen
//Start the background music
playmp3(mpPress, R.raw.press);
// if whammy = 4. stop all and move to high score
if (whammy == 4) {
stop();
stopmp3();
callFinish();
}
// if spint >0 start new data random
if (spint > 0) {
stop();
final Button bstop = (Button) findViewById(R.id.btstop);
bstop.setEnabled(true);
start(10000 * 60 * 60 * 24);
} else {
// stop all
stop();
stopmp3();
// if spin < 2, that round <2 move to spin activity
if (spin < 2) {
Intent it = new Intent(getBaseContext(), SpinActivity.class);
startActivity(it);
finish();
}
// esle move to high score activity
else {
callFinish();
}
}
}
private void whammy() {
// set up the whammy act animation
final ImageView act = (ImageView) findViewById(R.id.whammyact);
act.setBackgroundResource(R.drawable.tnt_animation);
actAnim = (AnimationDrawable) act.getBackground();
actAnim.setVisible(true, true);
}

Related

What code should I put inside the Android Lifecycle method?

I am new in Android. I am currently developing a game and when I press the back button I realize that my activity's state is not saved so I search and I found out about Android Lifecycle. I read it and now i know how they work but the thing is I don't know how to pause and resume my activity or What code should I use because it is the auto-generated grid and my timer is CountDownTimer.
When I press the Back button this Activity is what appears.
GameModeActivity
Now i want to detect if the game is still going on .. so if I click again the game mode this is what should appear.
GamePlayActivity
The problem is The grid was back to its normal state. and when I click a button timer never runs. If possible i want to restore the player's progress (like the position of mines, the flags, and the timer itself.).
My question is ... Is there a specific code to get the whole state of activity? so that i can just pause it and when i came back it will just resume?
This is the code of timer and grid in GameEngine class:
public static GameEngine getInstance() {
if (instance == null) {
instance = new GameEngine();
}
return instance;
}
private GameEngine() {
}
public void startit() {
countdowntimer = new CountDownTimer(60000, 1000) {
TextView timer = (TextView) ((GamePlayActivity) context).findViewById(R.id.tvTimeValue);
#Override
public void onTick(long millisUntilFinished) {
timer.setText("" + millisUntilFinished / 1000);
}
#Override
public void onFinish() {
timer.setText("Times up!");
timer.setTextColor(Color.RED);
}
}.start();
}
public static void cancel() {
if (countdowntimer != null) {
countdowntimer.cancel();
countdowntimer = null;
}
}
public void createGrid(Context context) {
Log.e("GameEngine", "Creating Grid..");
this.context = context;
int[][] GeneratedGrid = Generator.generate(bombnumber, WIDTH, HEIGHT);
setGrid(context, GeneratedGrid);
}
private void setGrid(final Context context, final int[][] grid) {
for (int x = 0; x < WIDTH; x++) {
for (int y = 0; y < HEIGHT; y++) {
if (MinesweeperGrid[x][y] == null) {
MinesweeperGrid[x][y] = new Cell(context, x, y);
}
MinesweeperGrid[x][y].setValue(grid[x][y]);
MinesweeperGrid[x][y].invalidate();
}
}
}
public Cell getCellposition(int position) {
int x = position % WIDTH;
int y = position / WIDTH;
return MinesweeperGrid[x][y];
}
public Cell getCellposition(int x, int y) {
return MinesweeperGrid[x][y];
}
I call the GameEngine.getInstance().createGrid(this) class in onCreate method of GamePlayActivity
And when I press the Back button on phone it will go to the previous activity which is GameModeActivity.

Speeding the Random process

I am practising on a simple Android Game where a round button is randomly placed on the screen when the user taps on it..
it works fine but i want to speedify the process of placing the button so that the game gets harder for user...
here is the Code I'm using -
public class GameWindow extends Activity implements View.OnClickListener {
static int score;
private Timer t;
private int TimeCounter = 29;
private boolean canMove = true;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setVolumeControlStream(AudioManager.STREAM_MUSIC);
////Remove title screen for activty.
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_game_window);
moveButton();
endonTimeOver();
}
public void endonTimeOver(){
////Activity timer for 60 seconds.
final TextView timer = (TextView) findViewById(R.id.seconds);
t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
////Set string to timer.
#Override
public void run() {
// TODO Auto-generated method stub
runOnUiThread(new Runnable() {
public void run() {
timer.setText(String.valueOf(TimeCounter)); // you can set it to a textView to show it to the user to see the time passing while he is writing.
TimeCounter = TimeCounter - 1;
}
});
}
}, 1000, 1000); // 1000 means start from 1 sec, and the second 1000 is do the loop each 1 sec.
new Timer().schedule(new TimerTask(){
public void run() {
GameWindow.this.runOnUiThread(new Runnable() {
public void run() {
startActivity(new Intent(GameWindow.this, Finished.class));
}
});
}
}, 30000);
}
////Move button.
private void moveButton()
{
if(!canMove){ return; }
runOnUiThread(
new Runnable()
{
#Override
public void run()
{
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
Button button = (Button)findViewById(R.id.button);
Random r = new Random();
int startX = width/2;
int startY = height/2;
if(score==0){
button.setX(startX);
button.setY(startY);
}
else {
int x = r.nextInt(width - 210);
int y = r.nextInt(height - 200);
button.setX(x);
button.setY(y);
}
}
}
);
}
////Display score
public void displayScore(int score) {
TextView scoreView = (TextView) findViewById(R.id.score);
scoreView.setText(String.valueOf(score));
}
#Override
public void onClick(View v) {
MediaPlayer mp = MediaPlayer.create(this, R.raw.buttonsound);
mp.setOnCompletionListener(new OnCompletionListener() {
#Override
public void onCompletion(MediaPlayer mp) {
// TODO Auto-generated method stub
mp.release();
}
});
mp.start();
score = score + 1;
displayScore(score);
switch (v.getId()) {
case (R.id.button): {
moveButton();
}
}
}
public static int getScore(){
return score;
}}
Use global variables for values that don't change:
findViewById is slow
Creating new Random every time is not necessary
getting the window parameter every time is not necessary either
You seem to be starting a new thread and telling it to runonui , this might be slowing you down , try this :
private void moveButton()
{
if(!canMove){ return; }
Display display = getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
int width = size.x;
int height = size.y;
Button button = (Button)findViewById(R.id.button);
Random r = new Random();
int startX = width/2;
int startY = height/2;
if(score==0){
button.setX(startX);
button.setY(startY);
}
else {
int x = r.nextInt(width - 210);
int y = r.nextInt(height - 200);
button.setX(x);
button.setY(y);
}
}
the computation itself doesn't seem to heavy so no need for another thread , you can do it on the main thread , if you're calling from oncreate that means you're already on main thread , this might give you the answer if i understood the question , try it

Android studio: Check object states

I have a game that spawns 4 enemies on screen from image boxes, when a timer reaches zero, an enemy spawns onto the screen. I want a way to constantly check if the enemies are visible or not on screen.
My class currently containing a while loop to check visibility:
public class rear_gunner extends AppCompatActivity {
int clickcount=0;
CountDownTimer countDownTimer;
int score = 0;
int health2 = 100;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rear_gunner);
final TextView text = (TextView) findViewById(R.id.textView2);
final TextView scoreText = (TextView) findViewById(R.id.score);
final TextView health = (TextView) findViewById(R.id.Health);
health.setText("Health:"+ health2);
//Enemy ImageViews
final ImageView enemy1 = (ImageView) findViewById(R.id.enemy1);
final ImageView enemy2 = (ImageView) findViewById(R.id.enemy2);
final ImageView enemy3 = (ImageView) findViewById(R.id.enemy3);
final ImageView enemy4 = (ImageView) findViewById(R.id.enemy4);
//sets screen orientation on created
this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
//sets imageViews into array
final ImageView[] enemies = new ImageView[4];
enemies[0] = enemy1;
enemies[1] = enemy2;
enemies[2] = enemy3;
enemies[3] = enemy4;
boolean running = true;
while (!running) {
if (enemy1.getVisibility() == View.VISIBLE) {
int damage = 1;
health2 = health2 - damage;
health.setText("Health:" + health2);
} else {
// Either gone or invisible
}
if (enemy2.getVisibility() == View.VISIBLE) {
int damage = 1;
health2 = health2 - damage;
health.setText("Health:" + health2);
} else {
// Either gone or invisible
}
if (enemy3.getVisibility() == View.VISIBLE) {
int damage = 1;
health2 = health2 - damage;
health.setText("Health:" + health2);
} else {
// Either gone or invisible
}
if (enemy4.getVisibility() == View.VISIBLE) {
int damage = 1;
health2 = health2 - damage;
health.setText("Health:" + health2);
} else {
// Either gone or invisible
}
}
The above code just simply does not work. When I start the activity the screen goes black and remains like that until closed. Does this have anything to do with the way I am using the while loop for running?
My timer code if needed:
//random number generator between 10-25
Random r = new Random();
int Low = 10000;
int High = 25000;
int Result = r.nextInt(High-Low) + Low;
//count down timer for spawing enemies
countDownTimer = new CountDownTimer(Result, 1000) {
#Override
public void onTick(long millisUntilFinished) {
text.setText("seconds remaining: " + millisUntilFinished / 1000);
if (score == 500)
{
countDownTimer.cancel();
}
}
#Override
public void onFinish() {
Random r = new Random();
int Low = 0;
int High = 4;
int Result = r.nextInt(High-Low) + Low;
enemies[Result].setVisibility(View.VISIBLE);
countDownTimer.start();
if (score == 500)
{
countDownTimer.cancel();
}
}
};
countDownTimer.start();
}
}
Thank you for all the help and any advice for a more efficient way of doing this would be greatly appriciated.
boolean running = true;
while (!running) {
...
Your while loop never get chance to run, if you want refresh UI, you must write this code in another place, maybe a background Timer task thread or use Handler to deal with this.

Timer code crashes my app

I'm learning android development, and what I'm trying to do is to have a label that counts down from 40 minutes, and when it reaches 0 it would stop counting and do something else. This is my code:
#Override
protected void onStart() {
super.onStart();
count = 2400;
final Timer t = new Timer();//Create the object
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
minLeft = (int) Math.floor(count / 60);
secLeft = count - minLeft * 60;
counter = minLeft + ":" + secLeft;
TextView tv = (TextView) findViewById(R.id.timer);
Log.i(MainActivity.TAG,minLeft+", "+secLeft+", "+counter);
tv.setText(counter);
count--;
if (minLeft <= 0 && secLeft <= 0) {
t.cancel();
count = 2400;
onFinish();
}
}
}, 1000, 1000);
}
But, when I go to that activity by clicking a button in the main activity, the label has the text "Timer" (its original text), and after a few seconds the app crashes with CalledFromWrongThreadException, but the line that causes the problem seems to be the one where I set the text of the TextView.
Please help, thanks in advance.
Your scheduled task runs on the background thread.
And you try to set the text to the textview from this background thread.
However in Android all view related operations have to be done on the main thread.
That is way in your scheduled task you have to use something like:
#Override
protected void onStart() {
super.onStart();
count = 2400;
final Timer t = new Timer();//Create the object
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
minLeft = (int) Math.floor(count / 60);
secLeft = count - minLeft * 60;
counter = minLeft + ":" + secLeft;
// the name of your actual activity
MyActivity.this.runOnUiThread(new Runnable() {
#Override
public void run() {
TextView tv = (TextView) findViewById(R.id.timer);
Log.i(MainActivity.TAG,minLeft+", "+secLeft+", "+counter);
tv.setText(counter);
}
});
count--;
if (minLeft <= 0 && secLeft <= 0) {
t.cancel();
count = 2400;
onFinish();
}
}
}, 1000, 1000);
}
Please also note, that this code can be written more elegantly, without all/so many anonymous classes, but it should do the trick.

CountDownTimer Android issue

I'm trying to implement a CountDownTimer in an Android Application. This timer will, while running, countdown from a value, than reset, than countdown from a different value. Switching back and force between values until either a set number of rounds have elapsed or the stop button has been pressed. I can get the CountDownTimer samples to work, but I guess I'm missing something here. Below is the applicable button press code;
CounterState state = CounterState.WORKOUT;
private WorkoutTimer workoutTimer;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.workout_stopwatch);
requestWindowFeature(Window.FEATURE_NO_TITLE);
// Set up OnClickListeners
((Button) findViewById(R.id.start_button)).setOnClickListener(this);
((Button) findViewById(R.id.stop_button)).setOnClickListener(this);
((Button) findViewById(R.id.reset_button)).setOnClickListener(this);
}
#Override
public void onClick(View v) {
switch(v.getId()) {
case R.id.start_button:
if (!timer_running) {
timer_running = true;
Log.d(TAG, "clicked on Start Button");
// If the state is unknown, set it to Workout first
int State = state.getStateValue();
if (State == 0) {
state.setStateValue(1);
}
workoutTimer.start();
}
break;
case R.id.stop_button:
Log.d(TAG, "clicked on Stop Button");
if (timer_running); {
timer_running = false;
workoutTimer.cancel();
}
break;
private class WorkoutTimer extends CountDownTimer{
public WorkoutTimer(long interval) {
super(getThisTime(), interval);
Log.d(TAG, "WorkoutTimer Constructed...");
}
TextView digital_display = (TextView) findViewById(R.id.digital_display);
TextView numOfRounds = (TextView) findViewById(R.id.number_of_rounds);
public void onFinish() {
int State = state.getStateValue();
int roundsLeft = 0;
if (State == 1) {
state.setStateValue(2);
} else {
state.setStateValue(1);
}
decrementRounds();
try {
roundsLeft = Integer.parseInt(numOfRounds.getText().toString());
} catch(NumberFormatException nfe) {
roundsLeft = 999;
}
if (roundsLeft > 0 || roundsLeft != 999) {
workoutTimer.start();
}
}
public void onTick(long millisUntilFinished) {
final long minutes_left = ((millisUntilFinished / 1000) / 60);
final long seconds_left = (millisUntilFinished / 1000) - (minutes_left * 60);
final long millis_left = millisUntilFinished % 100;
String time_left = String.format("%02d:%02d.d", minutes_left, seconds_left,
millis_left);
digital_display.setText(time_left);
}
}
private long getThisTime() {
long time = 0;
TextView workout_time = (TextView) findViewById(R.id.workout_time);
TextView rest_time = (TextView) findViewById(R.id.rest_time);
switch(state) {
case WORKOUT:
try {
time = Integer.parseInt(workout_time.getText().toString());
} catch(NumberFormatException nfe) {
time = 999;
}
// time = 90;
Log.d(TAG, "Workout time = " + time);
break;
case REST:
try {
time = Integer.parseInt(rest_time.getText().toString());
} catch(NumberFormatException nfe) {
time = 999;
}
// time = 30;
Log.d(TAG, "Rest time = " + time);
break;
case UNKNOWN:
time = 0;
break;
}
return time;
}
Everything starts up okay, but crashes when I click either button. If I comment out my calls to the workoutTimer, no crash. I never see my log in the constructor of the workoutTimer class, so obviously I'm missing something here. Any help would be appreciated.
-Ian
You have not initialized your workoutTimer. You need to add the following line in your onCreate method.
workoutTimer = new WorkoutTimer(...);

Categories

Resources