I am making an android game that is checking the players health value when this method is being runned. But however, it's not reacting. It doesn't do anything, when the value is less than 3, it shouldn't do anything, but when it is equal to 3, it should run a method. Please help me and thanks SO much in advance! This is the code that i am using:
private void checkLivesLeftValue() {
if (livesLeftValue == 3) {
//Message to display: "You lost!
onMethod();
}
else {
livesLeftValue = livesLeftValue + 1;
}
}
Full code:
package com.mysoftwaremobileapps.ParachuteHunter;
import java.util.ArrayList;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.media.MediaPlayer;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;
import android.widget.Toast;
public class ExampleView extends SurfaceView implements SurfaceHolder.Callback
{
class ExampleThread extends Thread
{
private ArrayList<Parachuter> parachuters;
private Bitmap parachuter;
private Paint black;
private boolean running;
private SurfaceHolder mSurfaceHolder;
private Context mContext;
private Handler mHandler;
private GameScreenActivity mActivity;
private long frameRate;
private boolean loading;
public float x;
public float y;
public MediaPlayer mp1;
public int parachuterIndexToResetAndDelete;
public int canvasGetWidth;
public int livesLeftValue;
public ExampleThread(SurfaceHolder sHolder, Context context, Handler handler)
{
mSurfaceHolder = sHolder;
mHandler = handler;
mContext = context;
mActivity = (GameScreenActivity) context;
parachuters = new ArrayList<Parachuter>();
parachuter = BitmapFactory.decodeResource(getResources(), R.drawable.parachuteman);
black = new Paint();
black.setStyle(Paint.Style.FILL);
black.setColor(Color.WHITE);
running = true;
// This equates to 26 frames per second.
frameRate = (long) (1000 / 26);
loading = true;
}
#Override
public void run()
{
while (running)
{
Canvas c = null;
try
{
c = mSurfaceHolder.lockCanvas();
synchronized (mSurfaceHolder)
{
long start = System.currentTimeMillis();
doDraw(c);
long diff = System.currentTimeMillis() - start;
if (diff < frameRate)
Thread.sleep(frameRate - diff);
}
} catch (InterruptedException e)
{
}
finally
{
if (c != null)
{
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
protected void doDraw(Canvas canvas)
{
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), black);
canvasGetWidth = canvas.getWidth();
//Draw
for (int i = 0; i < parachuters.size(); i++)
{
canvas.drawBitmap(parachuter, parachuters.get(i).getX(), parachuters.get(i).getY(), null);
parachuters.get(i).tick();
}
//Remove
for (int i = 0; i < parachuters.size(); i++)
{
if (parachuters.get(i).getY() > canvas.getHeight()) {
parachuters.remove(i);
onPlaySound();
checkLivesLeftValue();
}
}
}
public void onPlaySound()
{
try {
mp1 = MediaPlayer.create(getContext(), R.raw.bombsound);
mp1.start();
} catch (Exception e) {
e.printStackTrace();
mp1.release();
}
}
public void onMethod() {
mHandler.post(new Runnable() {
#Override
public void run() {
Toast.makeText(getContext(), "You lost!", 15).show();
}
});
}
private void checkLivesLeftValue() {
// TODO Auto-generated method stub
if (livesLeftValue == 3) {
//Message to display: "You lost!
onMethod();
}
else {
livesLeftValue = livesLeftValue + 1;
}
}
public boolean onTouchEvent(MotionEvent event)
{
if (event.getAction() != MotionEvent.ACTION_DOWN)
return false;
float x1 = event.getX();
float y1 = event.getY();
initiateDrawParachuters();
return true;
}
public void initiateDrawParachuters()
{
drawParachuter1();
}
private void drawParachuter1() {
// TODO Auto-generated method stub
//Parachuter nr. 1
x = 68;
y = 40;
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
drawParachuter2();
}
private void drawParachuter2() {
// TODO Auto-generated method stub
//Parachuter nr. 2
x = 100;
y = 80;
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
drawParachuter3();
}
private void drawParachuter3() {
// TODO Auto-generated method stub
//Parachuter nr. 3
x = 150;
y = 120;
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
drawParachuter4();
}
private void drawParachuter4() {
// TODO Auto-generated method stub
//Parachuter nr. 4
x = 170;
y = 150;
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
drawParachuter5();
}
private void drawParachuter5() {
// TODO Auto-generated method stub
//Parachuter nr. 5
x = 180;
y = 170;
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
drawParachuter6();
}
private void drawParachuter6() {
// TODO Auto-generated method stub
//Parachuter nr. 6
x = 200;
y = 180;
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
}
public void drawParachuters()
{
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
Toast.makeText(getContext(), "x=" + x + " y=" + y, 15).show();
}
public void setRunning(boolean bRun)
{
running = bRun;
}
public boolean getRunning()
{
return running;
}
}
/** Handle to the application context, used to e.g. fetch Drawables. */
private Context mContext;
/** Pointer to the text view to display "Paused.." etc. */
private TextView mStatusText;
/** The thread that actually draws the animation */
private ExampleThread eThread;
public ExampleView(Context context)
{
super(context);
// register our interest in hearing about changes to our surface
SurfaceHolder holder = getHolder();
holder.addCallback(this);
// create thread only; it's started in surfaceCreated()
eThread = new ExampleThread(holder, context, new Handler()
{
#Override
public void handleMessage(Message m)
{
// mStatusText.setVisibility(m.getData().getInt("viz"));
// mStatusText.setText(m.getData().getString("text"));
}
});
setFocusable(true);
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
return eThread.onTouchEvent(event);
}
public ExampleThread getThread()
{
return eThread;
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
{
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder)
{
if (eThread.getState() == Thread.State.TERMINATED)
{
eThread = new ExampleThread(getHolder(), getContext(), getHandler());
eThread.start();
}
else
{
eThread.start();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
boolean retry = true;
eThread.setRunning(false);
while (retry)
{
try
{
eThread.join();
retry = false;
}
catch (InterruptedException e)
{
}
}
}
}
I agree with the others, check the value via Log messages, so you can see the actual values.
Also, check if it might go over 3. I dont know what kind of game you are making but for example, say that livesLeftValue=2 for now, but something happens, and it increases by 2, reaching 4, without ever having the value 3. Lets say it never gets decreased, so you will never ever hit the value 3, thus never invoking the game over thingie, and livesLeftValue will just increase to the infinity.
put some debug in there and see if you really get the right value in here.
private void checkLivesLeftValue() {
Log.d("checkLivesLeftValue", "lives = " + livesLeftValue);
if (livesLeftValue == 3) {
Log.d("checkLivesLeftValue", "calling onMethod now");
onMethod();
} else {
livesLeftValue = livesLeftValue + 1;
Log.d("checkLivesLeftValue", "increased lives to " + livesLeftValue);
}
}
public void onMethod() {
Log.d("onMethod", "in onMethod");
mHandler.post(new Runnable() {
#Override
public void run() {
Log.d("onMethod", "showing Toast now");
Toast.makeText(getContext(), "You lost!", 15).show();
}
});
}
Related
I'm programming a pacman, the game is drawed in a SurfaceView, but I have problem to pause it and getting the atributes while it's running (no when I set them)
For example, I set a Semaphore that should be referenced in the Activity and in the Game view, and it is set it correct, but when the thread of the game view is running, and try to release the semaphore it indicates a NullPointerException.
On the other hand, when I try to pause the game, the game used to keep running in the background, and now when I resume it don't run
I'm sure the problem is with the references in memory, when I set and atribute as static i can access from both (view and surfaceview are the same object). I don't know why this happen.
Brief resume: An AppCompatActivity (which is PlayActivity) has a SurfaView (which is GameView), and this SurfaceView has the GameManager(which has all the things of the pacman in a moment). The references when the AppCompatActivity try to get something of the SurfaceView (for example the gameManager) are lost in execution.
Here the code
PlayActivity
public class PlayActivity extends AppCompatActivity {
private TextView playerNickname;
private TextView scoreTv;
private TextView maxScore;
private SurfaceView gameSurfaceView;
private GameView gameView;
private static Semaphore CHANGE_LIFES_MUTEX=new Semaphore(0,true);
private static Semaphore CHANGE_SCORE_MUTEX=new Semaphore(0,true);
private static Semaphore CHANGE_DIRECTION_MUTEX=new Semaphore(0,true);
private Thread changeScoreThread, changeDirectionThread;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Modified code
setContentView(R.layout.activity_game);
//we get text view that we will use
playerNickname=(TextView) this.findViewById(R.id.tv_player);
scoreTv=(TextView) this.findViewById(R.id.tv_current_score);
maxScore=(TextView) this.findViewById(R.id.tv_current_max_score);
gameSurfaceView= (GameView) this.findViewById(R.id.game_view);
//set text view initial values
playerNickname.setText(getIntent().getExtras().getString("playerNickname"));
scoreTv.setText("0");
maxScore.setText("To modify");
this.gameView=new GameView(gameSurfaceView.getContext());
this.gameView.setSemaphores(CHANGE_SCORE_MUTEX,CHANGE_DIRECTION_MUTEX);
this.gameSurfaceView.getHolder().addCallback(this.gameView);
}
protected void onResume(){
super.onResume();
this.gameView.resume();
this.initChangerThreads();
}
public void updateScoreTv(int score){
this.scoreTv.setText(""+score);
}
protected void onPause(){
super.onPause();
this.gameView.pause();
//in order to stop the threads
CHANGE_SCORE_MUTEX.release();
CHANGE_DIRECTION_MUTEX.release();
}
public void onLose(int score){
//We try to save the score, if there is a previous register we write only if this score
//is better that the one before
DBManager manager;
long raw;
Score scoreToSave;
manager=new DBManager(this);
scoreToSave=new Score(this.playerNickname.toString(), score);
if(manager.saveScore(scoreToSave)==-1){
//if i couldn't save the score
if(manager.updateScore(scoreToSave)!=-1){
//if my new score is better than the one previous
}else{
//if my new score is worse or equal than the one previous
}
}
}
private void initChangerThreads() {
this.changeScoreThread = new Thread(new Runnable() {
public void run() {
while (gameView.isDrawing()) {
//Log.i("Score ",""+gameManager.getScore());
try {
CHANGE_SCORE_MUTEX.acquire();
runOnUiThread(new Runnable() {
#Override
public void run() {
updateScoreTv(gameView.getGameManager().getScore());
}
});
}catch (Exception e){}
}
Log.i("Score Thread","ended");
}
});
this.changeScoreThread.start();
}
}
GameView
public class GameView extends SurfaceView implements Runnable, SurfaceHolder.Callback, GestureDetector.OnGestureListener {
private static final float SWIPE_THRESHOLD = 2;
private static final float SWIPE_VELOCITY = 2;
private static boolean CAN_DRAW = false;
private boolean GHOST_INICIALIZED=false;
private GestureDetector gestureDetector;
private GameManager gameManager;
private Thread thread; //game thread
private SurfaceHolder holder;
private int blockSize; // Ancho de la pantalla, ancho del bloque
private static int movementFluencyLevel=8; //this movement should be a multiple of the blocksize and multiple of 4, if note the pacman will pass walls
private int totalFrame = 4; // Cantidad total de animation frames por direccion
private int currentArrowFrame = 0; // animation frame de arrow actual
private long frameTicker; // tiempo desde que el ultimo frame fue dibujado
//----------------------------------------------------------------------------------------------
//Constructors
public GameView(Context context) {
super(context);
this.constructorHelper(context);
}
public GameView(Context context, AttributeSet attrs) {
super(context, attrs);
this.constructorHelper(context);
}
public GameView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
this.constructorHelper(context);
}
private void constructorHelper(Context context) {
this.gestureDetector = new GestureDetector(this);
setFocusable(true);
this.holder = getHolder();
this.holder.addCallback(this);
this.frameTicker = (long) (1000.0f / totalFrame);
this.gameManager=new GameManager();
int screenWidth=getResources().getDisplayMetrics().widthPixels;
this.blockSize = ((((screenWidth/this.gameManager.getGameMap().getMapWidth())/movementFluencyLevel)*movementFluencyLevel)/4)*4;
this.holder.setFixedSize(blockSize*this.gameManager.getGameMap().getMapWidth(),blockSize*this.gameManager.getGameMap().getMapHeight());
this.gameManager.getGameMap().loadBonusBitmaps(this.getBlockSize(),this.getResources(),this.getContext().getPackageName());
this.gameManager.setPacman(new Pacman("pacman","",this.movementFluencyLevel,this.gameManager.getGameMap().getPacmanSpawnPosition(),this.blockSize,this.getResources(),this.getContext().getPackageName()));
Ghost.loadCommonBitmaps(this.blockSize,this.getResources(),this.getContext().getPackageName());
}
//----------------------------------------------------------------------------------------------
//Getters and setters
public int getBlockSize() {
return blockSize;
}
public GameManager getGameManager() {
return gameManager;
}
public boolean isDrawing(){
return CAN_DRAW;
}
//----------------------------------------------------------------------------------------------
private synchronized void initGhost(){
if(!GHOST_INICIALIZED){
GHOST_INICIALIZED=true;
this.gameManager.initGhosts(this.blockSize,this.getResources(),this.getContext().getPackageName(),movementFluencyLevel);
}
}
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void run() {
long gameTime;
Canvas canvas;
while (!holder.getSurface().isValid()) {
}
this.initGhost();
this.setFocusable(true);
while (CAN_DRAW) {
gameTime=System.currentTimeMillis();
if(gameTime > frameTicker + (totalFrame * 15)){
canvas = holder.lockCanvas();
if(canvas!=null){
if(this.updateFrame(gameTime,canvas)){
try {
Thread.sleep(3000);
}catch (Exception e){}
}
holder.unlockCanvasAndPost(canvas);
if(this.gameManager.checkWinLevel()){
CAN_DRAW=false;
this.gameManager.cancelThreads();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {}
//animation
Log.i("Game","You win");
}else if(!this.gameManager.getPacman().hasLifes()){
//we lost
CAN_DRAW=false;
this.gameManager.cancelThreads();
//animation
Log.i("Game","You lose");
}
}
}
}
}
// Method to capture touchEvents
#Override
public boolean onTouchEvent(MotionEvent event) {
//To swipe
//https://www.youtube.com/watch?v=32rSs4tE-mc
this.gestureDetector.onTouchEvent(event);
super.onTouchEvent(event);
return true;
}
//Chequea si se deberia actualizar el frame actual basado en el
// tiempo que a transcurrido asi la animacion
//no se ve muy rapida y mala
#RequiresApi(api = Build.VERSION_CODES.N)
private boolean updateFrame(long gameTime, Canvas canvas) {
Pacman pacman;
Ghost[] ghosts;
boolean pacmanIsDeath;
pacman=this.gameManager.getPacman();
ghosts=this.gameManager.getGhosts();
// Si el tiempo suficiente a transcurrido, pasar al siguiente frame
frameTicker = gameTime;
canvas.drawColor(Color.BLACK);
this.gameManager.getGameMap().draw(canvas, Color.BLUE,this.blockSize,this.gameManager.getLevel());
this.gameManager.moveGhosts(canvas,this.blockSize);
pacmanIsDeath=pacman.move(this.gameManager,canvas);
if(!pacmanIsDeath){
// incrementar el frame
pacman.changeFrame();
for(int i=0; i<ghosts.length;i++){
ghosts[i].changeFrame();
}
currentArrowFrame++;
currentArrowFrame%=7;
}else{
pacman.setNextDirection(' ');
for(int i=0; i<ghosts.length;i++){
ghosts[i].respawn();
}
}
return pacmanIsDeath;
}
public int getScore(){
return this.getGameManager().getScore();
}
public void setSemaphores(Semaphore changeScoreSemaphore, Semaphore changeDirectionSemaphore){
this.gameManager.setChangeScoreSemaphore(changeScoreSemaphore);
this.gameManager.getPacman().setChangeDirectionSemaphore(changeDirectionSemaphore);
Log.i("Semaphore", "setted");
}
//----------------------------------------------------------------------------------------------
//Callback methods
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void surfaceCreated(SurfaceHolder holder) {
CAN_DRAW = true;
this.thread= new Thread(this);
this.thread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i("Surface","destroyed");
}
//----------------------------------------------------------------------------------------------
public void resume() {
CAN_DRAW = true;
thread = new Thread(this);
thread.start();
}
public void pause() {
CAN_DRAW = false;
while (true) {
try {
thread.join();
} catch (InterruptedException e) {
// retry
}
break;
}
this.thread=null;
}
#Override
public boolean onDown(MotionEvent e) {
return false;
}
#Override
public void onShowPress(MotionEvent e) {
}
#Override
public boolean onSingleTapUp(MotionEvent e) {
return false;
}
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
return false;
}
#Override
public void onLongPress(MotionEvent e) {
}
#Override
public boolean onFling(MotionEvent downEvent, MotionEvent moveEvent, float velocityX, float velocityY) {
//To swipe
//https://www.youtube.com/watch?v=32rSs4tE-mc
boolean result;
float diffX, diffY;
Pacman pacman;
Log.i("Fling", "detected");
result=false;
diffX = moveEvent.getX() - downEvent.getX();
diffY = moveEvent.getY() - downEvent.getY();
pacman=this.gameManager.getPacman();
if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY){
if (Math.abs(diffX) > Math.abs(diffY)) {
if (diffX > 0) {
//right
pacman.setNextDirection('r');
} else {
//left
pacman.setNextDirection('l');
}
}else{
if (diffY > 0) {
//down
pacman.setNextDirection('d');
} else {
//up
pacman.setNextDirection('u');
}
}
result=true;
}
return result;
}
}
GameManager
public class GameManager {
private static final int TOTAL_LEVELS=256;
private static int SCORE=0;
private GameMap gameMap;
private int level,bonusResetTime;//,score;
private CountDownScareGhosts scareCountDown;
private Pacman pacman;
private Ghost[] ghosts;
private boolean fruitHasBeenInTheLevel;
private static Semaphore CHANGE_SCORE_MUTEX;
public GameManager(){
this.fruitHasBeenInTheLevel=false;
//this.score=0;
this.gameMap=new GameMap();
this.gameMap.loadMap1();
this.level=1;
this.ghosts=new Ghost[4];
this.bonusResetTime = 5000;
this.scareCountDown=null;
}
public void setChangeScoreSemaphore(Semaphore changeScoreSemaphore) {
CHANGE_SCORE_MUTEX = changeScoreSemaphore;
//if(this.changeScoreSemaphore==null){
// Log.i("Change Score Semaphore","I'm null");
//}else{
// Log.i("Change Score Semaphore","I'm not null");
//}
}
public void addScore(int s){
//this.score+=s;
SCORE+=s;
CHANGE_SCORE_MUTEX.release();
/*if(this.changeScoreSemaphore==null){
Log.i("Change Score Semaphore","I'm null");
}else{
Log.i("Change Score Semaphore","I'm not null");
}*/
//this.changeScoreSemaphore.release();
}
public int getScore() {
return SCORE;
//return this.score;
}
public int getLevel() {
return this.level;
}
public GameMap getGameMap() {
return this.gameMap;
}
public Ghost[] getGhosts(){
return this.ghosts;
}
public Pacman getPacman(){
return this.pacman;
}
public void setPacman(Pacman pacman){
this.pacman=pacman;
}
public void eatPallet(int posXMap, int posYMap){
SCORE+=10;
CHANGE_SCORE_MUTEX.release();
//this.score+=10;
Log.i("Score GM", ""+SCORE);
//Log.i("Score GM", ""+this.score);
this.gameMap.getMap()[posYMap][posXMap]=0;
//this.changeScoreSemaphore.release();
//if(this.changeScoreSemaphore==null){
// Log.i("Change Score Semaphore","I'm null");
//}else{
// Log.i("Change Score Semaphore","I'm not null");
//}
}
public void eatBonus(int posXMap,int posYMap){
SCORE+=500;
CHANGE_SCORE_MUTEX.release();
//this.score+=500;
//Log.i("Score", Double.toString(this.score).substring(0,Double.toString(this.score).indexOf('.')));
this.gameMap.getMap()[posYMap][posXMap]=0;
//this.changeScoreSemaphore.release();
}
public void eatSuperPallet(int posXMap,int posYMap){
SCORE+=50;
CHANGE_SCORE_MUTEX.release();
//this.score+=50;
this.gameMap.getMap()[posYMap][posXMap]=0;
//Si hay un timer andando lo cancelo y ejecuto otro
if (this.scareCountDown != null){
this.scareCountDown.cancel();
}
this.scareCountDown = new CountDownScareGhosts(this.ghosts,this.gameMap.getMap());
this.scareCountDown.start();
//this.changeScoreSemaphore.release();
}
public void tryCreateBonus(){
//only if pacman has eaten 20 pallets we should allow the fruit appear
if(!this.fruitHasBeenInTheLevel && this.gameMap.getEatenPallets()>=20){
//to not allow the fruit be again in the level
this.fruitHasBeenInTheLevel=true;
new CountdownBonusThread(this.gameMap,this.bonusResetTime).start();
}
}
#RequiresApi(api = Build.VERSION_CODES.N)
public void moveGhosts(Canvas canvas,int blocksize) {
for (int i = 0; i < ghosts.length; i++) {
ghosts[i].move(this.gameMap.getMap(),this.pacman);
ghosts[i].draw(canvas);
}
}
public synchronized void initGhosts(int blocksize, Resources res, String packageName,int movementFluency) {
int[][]spawnPositions,cornersPositions, notUpDownPositions,defaultTargets;
defaultTargets=this.gameMap.getDefaultGhostTarget();
notUpDownPositions=this.gameMap.getNotUpDownDecisionPositions();
spawnPositions=this.gameMap.getGhostsSpawnPositions();
cornersPositions=this.gameMap.getGhostsScatterTarget();
//start position
// 5 blinky spawn [13, 11]
// 6 pinky spawn [15,11]
// 7 inky spawn [13,16]
// 8 clyde spawn [15,16]
this.ghosts=new Ghost[4];
ghosts[0] = new Ghost("blinky",spawnPositions[0], cornersPositions[0] ,new BehaviorChaseAgressive(notUpDownPositions,movementFluency,defaultTargets[0]),movementFluency,notUpDownPositions,'l',defaultTargets[0],blocksize,res,packageName);
ghosts[1] = new Ghost("pinky",spawnPositions[1],cornersPositions[1],new BehaviorChaseAmbush(notUpDownPositions,movementFluency,defaultTargets[1]),movementFluency,notUpDownPositions,'r',defaultTargets[1],blocksize,res,packageName);
ghosts[2] = new Ghost("inky",spawnPositions[2],cornersPositions[2],new BehaviorChasePatrol(notUpDownPositions,this.ghosts[0],movementFluency,defaultTargets[0]),movementFluency,notUpDownPositions,'l',defaultTargets[0],blocksize,res,packageName);
ghosts[3] = new Ghost("clyde",spawnPositions[3],cornersPositions[3],new BehaviorChaseRandom(notUpDownPositions,cornersPositions[3],movementFluency,defaultTargets[1]),movementFluency,notUpDownPositions,'r',defaultTargets[1],blocksize,res,packageName);
try{
Thread.sleep(200);
}catch(Exception e){}
for (int i=0;i<ghosts.length;i++){
ghosts[i].onLevelStart(1);
}
}
public boolean checkWinLevel() {
//player win the level if he has eaten all the pallet
return this.gameMap.countPallets()==0;
}
public void onResume(){
for (int i=0 ; i<this.ghosts.length;i++){
this.ghosts[i].cancelBehavoirThread();
}
if(this.scareCountDown!=null && !this.scareCountDown.hasEnded()){
this.scareCountDown.start();
}
}
public void onPause(){
for (int i=0 ; i<this.ghosts.length;i++){
this.ghosts[i].cancelBehavoirThread();
}
if(this.scareCountDown!=null && !this.scareCountDown.hasEnded()){
this.scareCountDown=this.scareCountDown.onPause();
}
}
public void cancelThreads(){
for (int i=0 ; i<this.ghosts.length;i++){
this.ghosts[i].cancelBehavoirThread();
}
if(this.scareCountDown!=null){
this.scareCountDown.cancel();
}
}
}
I'm developing an android game, trying to store the character's coordinates. I'm using the onSaveInstanceState and onRestoreInstanceState methods. But when I tested the coordinates get's changed.
So it loads the correct value but after that it saves a bad number then it loads this bad value.
Class1
package hu.cig.vob;
import android.app.Activity;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnTouchListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import cug.hu.vob.R;
public class Level extends Activity {
private LevelView lv;
private LinearLayout linearL;
private Button left, right, jump, fire;
private mListener l = new mListener();
//Konstansok az activity allapotanak mentesehez
private String playerX = "PlayerX",playerY="PlayerY",playerH="PlayerH";
#SuppressWarnings("deprecation")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.level_layout);
final ImageView healthBar = (ImageView) findViewById(R.id.life_view);
Drawable d = getResources().getDrawable(R.drawable.main_screen_bg);
linearL = (LinearLayout) findViewById(R.id.linear_layout);
linearL.setBackgroundDrawable(d);
lv = new LevelView(getApplicationContext(), getIntent().getIntExtra(
MainActivity.LEVEL_EXTRA, 0), getWindowManager());
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT);
lv.setLayoutParams(params);
linearL.addView(lv, 0);
left = (Button) findViewById(R.id.left);
right = (Button) findViewById(R.id.right);
jump = (Button) findViewById(R.id.jump);
fire = (Button) findViewById(R.id.fire);
left.setOnTouchListener(l);
right.setOnTouchListener(l);
jump.setOnTouchListener(l);
fire.setOnTouchListener(l);
lv.setOnClickListener(new OnClickListener() {
// Game over screen esetén kilép
#Override
public void onClick(View v) {
if (lv.getGameState()) {
finish();
}
}
});
// Életcsik frissitése az életnek megfelelően
new Thread() {
#Override
public void run() {
while (true) {
if (lv.getRobot().getHealth() <= 0) {
runOnUiThread(new Runnable() {
#Override
public void run() {
healthBar.setImageResource(R.drawable.battery5);
}
});
} else if (lv.getRobot().getHealth() <= 25) {
runOnUiThread(new Runnable() {
#Override
public void run() {
healthBar.setImageResource(R.drawable.battery4);
}
});
} else if (lv.getRobot().getHealth() <= 50) {
runOnUiThread(new Runnable() {
#Override
public void run() {
healthBar.setImageResource(R.drawable.battery3);
}
});
} else if (lv.getRobot().getHealth() <= 75) {
runOnUiThread(new Runnable() {
#Override
public void run() {
healthBar.setImageResource(R.drawable.battery2);
}
});
}else if(lv.getRobot().getHealth() >= 75){
runOnUiThread(new Runnable() {
#Override
public void run() {
healthBar.setImageResource(R.drawable.battery);
}
});
}
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
#Override
protected void onPause() {
overridePendingTransition(0, 0);
super.onPause();
}
// TODO:
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
lv.getRobot().setX(savedInstanceState.getInt(playerX));
lv.getRobot().setY(savedInstanceState.getInt(playerY));
Log.d("LoL","Loaded y:"+savedInstanceState.getInt(playerY));
lv.getRobot().setHealth(savedInstanceState.getInt(playerH));
super.onRestoreInstanceState(savedInstanceState);
}
#Override
protected void onSaveInstanceState(Bundle outState) {
outState.putInt(playerX , lv.getRobot().getX());
outState.putInt(playerY, lv.getRobot().getY());
Log.d("LoL","Saved y:"+lv.getRobot().getY());
outState.putInt(playerH, lv.getRobot().getHealth() );
super.onSaveInstanceState(outState);
}
// iránygombok kezelése
private class mListener implements OnTouchListener {
#Override
public boolean onTouch(View v, MotionEvent event) {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
switch (v.getId()) {
case R.id.left:
lv.getRobot().moveLeft();
break;
case R.id.right:
lv.getRobot().moveRight();
break;
case R.id.jump:
lv.getRobot().jump();
break;
case R.id.fire:
lv.getRobot().shot();
break;
}
break;
case MotionEvent.ACTION_UP:
switch (v.getId()) {
case R.id.left:
lv.getRobot().stopMovingLeft();
break;
case R.id.right:
lv.getRobot().stopMovingRight();
break;
case R.id.fire:
lv.getRobot()._shot();
break;
}
break;
}
return true;
}
}
}
class2
package hu.cig.vob;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Rect;
import cug.hu.vob.R;
public class Robot {
private Bitmap icon, currIcon, iconShot;
private int x, y, speedX = 0, speedY = 0, health = 100;
private final int MOVESPEED = 3, JumpSpeed = 15;
private boolean isMovingLeft = false, isMovingRight = false,
isFalling = true, isJumping = false, canJump = true;
private Rect bottom, horizontal;
private Context context;
private List<Bullet> bullets = Collections
.synchronizedList(new ArrayList<Bullet>());
public Robot(int in_x, int in_y, Bitmap i, float sc, Context c) {
context = c;
icon = i;
currIcon = icon;
iconShot = BitmapFactory.decodeResource(c.getResources(),
R.drawable.shot_right);
x = in_x * (icon.getWidth()/2);
y = in_y * (icon.getHeight()/2);
y = (int) (sc - y);
// for colliding
horizontal = new Rect((int) (x + icon.getWidth() * (31.5 / 100)),
y + 5, (int) (x + icon.getWidth() - icon.getWidth()
* (31.5 / 100)), y + icon.getHeight() - 5);
bottom = new Rect((int) (x + icon.getWidth() * (31.5 / 100) + 5), y
+ icon.getHeight() - 10, (int) (x + icon.getWidth()
- icon.getWidth() * (31.5 / 100) - 5), y + icon.getHeight());
}
public void update(List<Block> blocks) {
int oldX = x, oldY = y;
if (!(x + speedX < 0 || x + speedX > LevelView.intScreenWidth)) {
x += speedX;
}
updateRect();
for (int i = 0; i < blocks.size(); i++) {
if (horizontal.intersect(blocks.get(i).getRect())) {
stopMovingRight();
stopMovingLeft();
x = oldX;
updateRect();
}
}
if (bullets.size() > 0) {
Iterator<Bullet> it = bullets.iterator();
while (it.hasNext()) {
Bullet b = it.next();
if (b.getCx() > LevelView.screenWidth) {
it.remove();
} else {
b.update();
}
Iterator<Block> itt = blocks.iterator();
while (itt.hasNext()) {
Block bb = itt.next();
if (bb.getRect().intersect(b.getRect())) {
it.remove();
}
}
}
}
// #graviti"
if (isJumping) {
y -= speedY;
speedY--;
if (speedY == 0) {
isFalling = true;
isJumping = false;
}
updateRect();
}
if (isFalling) {
y += JumpSpeed - 5;
canJump = false;
updateRect();
}
for (Block b : blocks) {
if (bottom.intersect(b.getRect())) {
y = oldY;
updateRect();
canJump = true;
}
}
}
private void updateRect() {
horizontal = new Rect((int) (x + icon.getWidth() * (31.5 / 100)),
y + 10, (int) (x + icon.getWidth() - icon.getWidth()
* (31.5 / 100)), y + icon.getHeight() - 10);
bottom = new Rect((int) (x + icon.getWidth() * (31.5 / 100) + 5), y
+ icon.getHeight() - 10, (int) (x + icon.getWidth()
- icon.getWidth() * (31.5 / 100) - 5), y + icon.getHeight() - 2);
}
public void moveLeft() {
speedX = -MOVESPEED;
isMovingLeft = true;
}
public void moveRight() {
speedX = MOVESPEED;
isMovingRight = true;
}
public void stopMovingLeft() {
isMovingLeft = false;
stop();
}
public void stopMovingRight() {
isMovingRight = false;
stop();
}
public void stop() {
if (isMovingRight == false && isMovingLeft == false) {
speedX = 0;
}
if (isMovingRight == true && isMovingLeft == false) {
moveRight();
}
if (isMovingRight == false && isMovingLeft == true) {
moveLeft();
}
}
public Bitmap getIcon() {
return currIcon;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public int getSpeed() {
return speedX;
}
public boolean isMovingLeft() {
return isMovingLeft;
}
public boolean isMovingRight() {
return isMovingRight;
}
public Rect getBottomRect() {
return bottom;
}
public Rect getHRect() {
return horizontal;
}
public int getHealth() {
return health;
}
public void setX(int x) {
this.x = x;
}
public void setY(int y) {
this.y = y;
}
public void setHealth(int health) {
this.health = health;
}
public void shot() {
currIcon = iconShot;
Bullet b = new Bullet((float) (x + iconShot.getWidth()),
(float) (y + ((26.31 * iconShot.getHeight()) / 100)),
Helper.convertPx_Dpi(10, context), 2);
bullets.add(b);
}
public void _shot() {
currIcon = icon;
}
public List<Bullet> getBullets() {
return bullets;
}
public void jump() {
if (!isJumping && canJump) {
isJumping = true;
isFalling = false;
speedY = JumpSpeed;
}
}
public void increaseHealth(int x){
health += x;
if(health > 100){
health = 100;
}
}
public void degreeseHealth(int a) {
health -= a;
}
}
Your app can resume while obscured by the lock screen. If you want to tell the difference between "resume is hidden by a lock screen" and "resume is actually displayed" you can check your window focus.
See Making Android Games that Play Nice for more details.
A different way to get a similar "wait until actually displayed" is to wait for the first Activity.onUserInteraction after a resume before restarting your game.
I'm developing a simple game like BSD robots. This game contains a rather large board (over 40 cells) and it doesn't look nice even at 10 inch tablet. My decision was to scroll (move) surface view and not to scale each figure which size is like finger spot.
I've read tons articles about surface view but I cannot understand how to move it?
My activity code:
package ru.onyanov.robots;
public class MainActivity extends Activity {
public BoardView board;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
requestWindowFeature(Window.FEATURE_NO_TITLE);
board = new BoardView(this);
setContentView(board);
}
}
Class Board:
package ru.onyanov.robots;
public class BoardView extends SurfaceView {
private GameThread mThread;
private boolean running = false;
public final int sizeX = 50;
public final int sizeY = 35;
public final int cellSize = 64;
private int robotCount = 4;
public ArrayList<Cell> cells = new ArrayList<Cell>();
private ArrayList<Robot> robots = new ArrayList<Robot>();
private Hero hero;
public Bitmap imageCell;
public Bitmap imageRobot;
public Bitmap imageHero;
public BoardView(Context context) {
super(context);
makeGraphic();
constructCells();
constructRobots();
hero = new Hero(this, 3, 2, imageHero);
mThread = new GameThread(this);
getHolder().addCallback(new SurfaceHolder.Callback() {
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
mThread.setRunning(false);
while (retry) {
try {
mThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
public void surfaceCreated(SurfaceHolder holder) {
mThread.setRunning(true);
mThread.start();
}
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
}
private void makeGraphic() {
Bitmap cellImageSource = BitmapFactory.decodeResource(getResources(),
R.drawable.cell);
imageCell = Bitmap.createScaledBitmap(cellImageSource, cellSize,
cellSize, false);
imageRobot = BitmapFactory.decodeResource(getResources(),
R.drawable.robot);
imageHero = BitmapFactory.decodeResource(getResources(),
R.drawable.hero);
}
private void constructRobots() {
Robot robot;
Random rand = new Random();
for (int r = 0; r < robotCount; r++) {
int x = rand.nextInt(sizeX);
int y = rand.nextInt(sizeY);
robot = new Robot(this, x, y, imageRobot);
robots.add(robot);
}
return;
}
private void constructCells() {
Cell cell;
for (int y = 0; y < sizeY; y++) {
for (int x = 0; x < sizeX; x++) {
cell = new Cell(this, x, y, imageCell);
cells.add(cell);
}
}
return;
}
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
Cell cell;
for (int c = 0; c < cells.size(); c++) {
cell = cells.get(c);
cell.onDraw(canvas);
}
Robot robot;
for (int r = 0; r < robots.size(); r++) {
robot = robots.get(r);
robot.onDraw(canvas);
}
hero.onDraw(canvas);
}
public boolean onTouchEvent(MotionEvent e) {
int shotX = (int) e.getX();
int shotY = (int) e.getY();
if (e.getAction() == MotionEvent.ACTION_MOVE){
//TODO move board
showToast("move Board");
} else if (e.getAction() == MotionEvent.ACTION_UP) {
showToast("touchPoint: " + shotX + ", "+shotY);
hero.moveByDirection(shotX, shotY);
this.scrollTo(shotX, shotY);
}
return true;
}
public void showToast(String mes) {
Toast toast = Toast.makeText(getContext(), mes, Toast.LENGTH_LONG);
toast.show();
}
public class GameThread extends Thread {
private BoardView view;
public GameThread(BoardView view) {
this.view = view;
}
public void setRunning(boolean run) {
running = run;
}
public void run() {
while (running) {
Canvas canvas = null;
try {
canvas = view.getHolder().lockCanvas();
synchronized (view.getHolder()) {
onDraw(canvas);
}
canvas.scale(300, 300);
} catch (Exception e) {
} finally {
if (canvas != null) {
view.getHolder().unlockCanvasAndPost(canvas);
}
}
}
}
}
}
Some magic digits here are temporary. Now I just want to move BoardView;
The issue was to add x and y fields to SurfaceView, change them at onTouchEvent and draw all the elements in canvas with x- and y-offset. It's strange that I didn't recieved any answers...
I am making an android game that needs to run a method continiously, kind of like a timer. I need that it is being called every second. How can i make this possible???
Java code:
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;
import android.widget.Toast;
public class ExampleView extends SurfaceView implements SurfaceHolder.Callback
{
class ExampleThread extends Thread
{
private ArrayList<Parachuter> parachuters;
private Bitmap parachuter;
private Paint black;
private boolean running;
private SurfaceHolder mSurfaceHolder;
private Context mContext;
private Handler mHandler;
private GameScreenActivity mActivity;
private long frameRate;
private boolean loading;
public ExampleThread(SurfaceHolder sHolder, Context context, Handler handler)
{
mSurfaceHolder = sHolder;
mHandler = handler;
mContext = context;
mActivity = (GameScreenActivity) context;
parachuters = new ArrayList<Parachuter>();
parachuter = BitmapFactory.decodeResource(getResources(), R.drawable.parachuteman);
black = new Paint();
black.setStyle(Paint.Style.FILL);
black.setColor(Color.WHITE);
running = true;
// This equates to 26 frames per second.
frameRate = (long) (1000 / 26);
loading = true;
}
#Override
public void run()
{
while (running)
{
Canvas c = null;
try
{
c = mSurfaceHolder.lockCanvas();
synchronized (mSurfaceHolder)
{
long start = System.currentTimeMillis();
doDraw(c);
long diff = System.currentTimeMillis() - start;
if (diff < frameRate)
Thread.sleep(frameRate - diff);
}
} catch (InterruptedException e)
{
}
finally
{
if (c != null)
{
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
protected void doDraw(Canvas canvas)
{
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), black);
//Draw
for (int i = 0; i < parachuters.size(); i++)
{
canvas.drawBitmap(parachuter, parachuters.get(i).getX(), parachuters.get(i).getY(), null);
parachuters.get(i).tick();
}
//Remove
for (int i = 0; i < parachuters.size(); i++)
{
if (parachuters.get(i).getY() > canvas.getHeight())
parachuters.remove(i);
}
}
public boolean onTouchEvent(MotionEvent event)
{
if (event.getAction() != MotionEvent.ACTION_DOWN)
return false;
float x = event.getX();
float y = event.getY();
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
Toast.makeText(getContext(), "x=" + x + " y=" + y, 15).show();
return true;
}
public void setRunning(boolean bRun)
{
running = bRun;
}
public boolean getRunning()
{
return running;
}
}
/** Handle to the application context, used to e.g. fetch Drawables. */
private Context mContext;
/** Pointer to the text view to display "Paused.." etc. */
private TextView mStatusText;
/** The thread that actually draws the animation */
private ExampleThread eThread;
public ExampleView(Context context)
{
super(context);
// register our interest in hearing about changes to our surface
SurfaceHolder holder = getHolder();
holder.addCallback(this);
// create thread only; it's started in surfaceCreated()
eThread = new ExampleThread(holder, context, new Handler()
{
#Override
public void handleMessage(Message m)
{
// mStatusText.setVisibility(m.getData().getInt("viz"));
// mStatusText.setText(m.getData().getString("text"));
}
});
setFocusable(true);
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
return eThread.onTouchEvent(event);
}
public ExampleThread getThread()
{
return eThread;
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
{
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder)
{
if (eThread.getState() == Thread.State.TERMINATED)
{
eThread = new ExampleThread(getHolder(), getContext(), getHandler());
eThread.start();
}
else
{
eThread.start();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
boolean retry = true;
eThread.setRunning(false);
while (retry)
{
try
{
eThread.join();
retry = false;
}
catch (InterruptedException e)
{
}
}
}
}
I need to add a function or a socalled "method", a public void or something like that, that should be called every second and should do the exact same code as the MotionEvent event method, the onTouchEvent.
Following Rob's commented link, consider (which is not the accepted answer, though) reviewing this from the Android Developer's site, Resources section: http://developer.android.com/resources/articles/timed-ui-updates.html
It describes how to use the android os Handler class to implement a timer, rather than using the Timer and TimerTask classes themselves.
This pretty much what you are looking for.
How to run a Runnable thread in Android?
It does sth every 1000ms using a thread.
onRestoreInstanceState(Bundle savedInstanceState)
is not geting called, I am pasting my code below. Actually I want to redraw all the points that are saved when my activity went in background.
package com.geniteam.mytest;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
public class Tutorial2D extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new Panel(this));
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Panel panel = new Panel(this);
outState.putSerializable("test", panel._graphics);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Panel panel = new Panel(this);
panel.set_graphics((ArrayList<GraphicObject>) savedInstanceState.getSerializable("test"));
}
class Panel extends SurfaceView implements SurfaceHolder.Callback {
private TutorialThread _thread;
private ArrayList<GraphicObject> _graphics = new ArrayList<GraphicObject>();
public ArrayList<GraphicObject> get_graphics() {
return _graphics;
}
public void set_graphics(ArrayList<GraphicObject> graphics) {
_graphics = graphics;
}
public Panel(Context context) {
super(context);
getHolder().addCallback(this);
_thread = new TutorialThread(getHolder(), this);
setFocusable(true);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
synchronized (_thread.getSurfaceHolder()) {
// if (event.getAction() == MotionEvent.ACTION_DOWN) {
GraphicObject graphic = new GraphicObject(BitmapFactory.decodeResource(getResources(), R.drawable.icon));
graphic.getCoordinates().setX((int) event.getX() - graphic.getGraphic().getWidth() / 2);
graphic.getCoordinates().setY((int) event.getY() - graphic.getGraphic().getHeight() / 2);
_graphics.add(graphic);
//}
return true;
}
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
Bitmap bitmap;
GraphicObject.Coordinates coords;
for (GraphicObject graphic : _graphics) {
bitmap = graphic.getGraphic();
coords = graphic.getCoordinates();
canvas.drawBitmap(bitmap, coords.getX(), coords.getY(), null);
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
try{
_thread.setRunning(true);
_thread.start();
}catch(Exception ex){
_thread = new TutorialThread(getHolder(), this);
_thread.start();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// simply copied from sample application LunarLander:
// we have to tell thread to shut down & wait for it to finish, or else
// it might touch the Surface after we return and explode
boolean retry = true;
_thread.setRunning(false);
while (retry) {
try {
_thread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
}
class TutorialThread extends Thread {
private SurfaceHolder _surfaceHolder;
private Panel _panel;
private boolean _run = false;
public TutorialThread(SurfaceHolder surfaceHolder, Panel panel) {
_surfaceHolder = surfaceHolder;
_panel = panel;
}
public void setRunning(boolean run) {
_run = run;
}
public SurfaceHolder getSurfaceHolder() {
return _surfaceHolder;
}
#Override
public void run() {
Canvas c;
while (_run) {
c = null;
try {
c = _surfaceHolder.lockCanvas(null);
synchronized (_surfaceHolder) {
_panel.onDraw(c);
}
} finally {
// do this in a finally so that if an exception is thrown
// during the above, we don't leave the Surface in an
// inconsistent state
if (c != null) {
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
class GraphicObject {
/**
* Contains the coordinates of the graphic.
*/
public class Coordinates {
private int _x = 100;
private int _y = 0;
public int getX() {
return _x + _bitmap.getWidth() / 2;
}
public void setX(int value) {
_x = value - _bitmap.getWidth() / 2;
}
public int getY() {
return _y + _bitmap.getHeight() / 2;
}
public void setY(int value) {
_y = value - _bitmap.getHeight() / 2;
}
public String toString() {
return "Coordinates: (" + _x + "/" + _y + ")";
}
}
private Bitmap _bitmap;
private Coordinates _coordinates;
public GraphicObject(Bitmap bitmap) {
_bitmap = bitmap;
_coordinates = new Coordinates();
}
public Bitmap getGraphic() {
return _bitmap;
}
public Coordinates getCoordinates() {
return _coordinates;
}
}
}
onRestoreInstanceState only gets called if the app is destroyed and re-created. Putting the app in the background then bringing it up again will call onResume, but not onRestoreInstanceState.