my app shows a bunch of bitmaps that animate one by one as it's stored in a Bitmap array and initially when app starts up curPosition is 0 to start animating obj at index 0. The handleMessage will animate each obj with a 1000ms delay between each obj when app starts up first time and so when app starts up first time handleMessage animates each obj normally.
The issue is once I double tap the restart button bitmap. I used the GestureDetector class and I have a Restart button constructed via a bitmap that when I listen for onDoubleTap and what should happen is the handleMessage will go thru each bitmap restarting animating them.
For some reason, when I double tap the Restart button bitmap, the handleMessage is running and i know this since I put in a logcat message and for that logcat message in update method I see it running thru each curPosition so I mean this line: Log.i ("cur pos. so far:", "" + curPosition );
but I don't visually see the animation running thru update method unless I interrupt app (i.e. close app OR minimize then resume app) and double tap the Restart button bitmap and the double tapping Restart button bitmap WORKS ONLY ONCE so I need to interrupt app to get it to work again.
public class MainActivity extends Activity implements
GestureDetector.OnGestureListener,
GestureDetector.OnDoubleTapListener {
private MySurfaceView mysurfaceView;
private Bitmap restart_buttonBitmap;
private GestureDetector mGestureDetector;
private MiniProj2Button restart;
private MiniProj2Button newLevel;
private final int SIZE = 5;
private final int DELAY = 1000;
private Bitmap[] myObjs = new Bitmap[ SIZE ];
//Screen size info
private int screenWidth;
private int screenHeight;
//The size in pixels of a place on the game board
private int blockSize;
private int numBlocksWide;
private int numBlocksHigh;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mySurfaceView = new MySurfaceView(this);
setContentView(mySurfaceView);
// Create a GestureDetector
mGestureDetector = new GestureDetector(this, this);
// Attach listeners that'll be called for double-tap and related gestures
mGestureDetector.setOnDoubleTapListener( this );
}//END METHOD: onCreate
#Override
protected void onStop() {
super.onStop();
Log.d("onStop", "Main Activity's onStop called");
gameView.surfaceDestroyed( mySurfaceView.getHolder() );
this.finish();
}
#Override
protected void onResume() {
super.onResume();
Log.d("onResume", "Main Activity's onResume called");
mySurfaceView = new MySurfaceView(this);
setContentView(mySurfaceView);
mySurfaceView.surfaceCreated( mySurfaceView.getHolder() );
}
#Override
protected void onPause() {
super.onPause();
Log.i("onPause", "Main Activity's onPause called");
mySurfaceView.surfaceDestroyed( mySurfaceView.getHolder() );
}
#Override
public boolean onDoubleTap(MotionEvent e) {
//reset animation if Restart button pressed!
if ( restart.isButtonTouched(e.getX(), e.getY(), blockSize,blockSize) ) {
curPosition = 0;
}
return true;
}
public void configureDisplay() {
//find out the width and height of the screen
Display display =
getWindowManager().getDefaultDisplay();
Point size = new Point();
display.getSize(size);
screenWidth = size.x;
screenHeight = size.y;
//Determine the size of each block/place on the board
// blockSize = screenWidth/10;
blockSize = screenWidth/10;
//Determine how many blocks will fit into the
//height and width
// numBlocksWide = 10;
numBlocksWide = 10;
numBlocksHigh = ( ( screenHeight ) ) / blockSize;
}//END METHOD: configureDisplay
#Override
public boolean onTouchEvent(MotionEvent e) {
mGestureDetector.onTouchEvent(e);
return super.onTouchEvent(e);
}//END onTouchEvent
class MySurfaceView extends SurfaceView implements SurfaceHolder.Callback, Handler.Callback {
Canvas canvas = new Canvas();
SurfaceHolder surfaceHolder;//this lets us access the canvas but still need to use Canvas class
Handler myHandler;
Paint paint = new Paint ();
public MySurfaceView(Context context) {
super(context);
paint.setColor(Color.argb(255, 0, 0, 0));
path = new Path ();
myHandler = new Handler(this);
getHolder().addCallback(this);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
this.surfaceHolder = holder;
myHandler.sendEmptyMessage(0);
}
#Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
// What do I enter here???
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.i("Me", "surfaceDestroyed: bye!" );
myHandler.removeCallbacksAndMessages(null);
}
protected void drawIt ( ) {
if ( surfaceHolder.getSurface().isValid() ) {
canvas = surfaceHolder.lockCanvas();
canvas.drawColor(Color.WHITE);//the background
//for each obj, draw it
surfaceHolder.unlockCanvasAndPost(canvas);
}//END IF BLOCK: For valid surfaceHolder
}//END METHOD: drawIt
public void update() {
Log.i ("cur pos. so far:", "" + curPosition );
if ( curPosition < SIZE ) {
myObjs [ curPosition ].animateMe ( );
curPosition++;
}
}//END METHOD: update
#Override
public boolean handleMessage(Message msg) {
if (curPosition < SIZE ) {
Log.i("Still objs 2 animate","Yes");
Log.i ("cur pos. so far:", "" + curPosition );
gameView.update();
gameView.drawIt();
myHandler.sendEmptyMessageDelayed(msg.what, DELAY);
}
else {
myHandler.sendEmptyMessageDelayed(msg.what, 10);
gameView.drawIt();
}
return true;
}//END METHOD: handleMessage
}//END INNER CLASS: MySurfaceView
}//END CLASS: MainActivity
Related
I'm new to Android and threading.
What app does
I have a simple app that just shows a bitmap bouncing around within the screen's boundaries (i.e. if bitmap hits the right edge of the screen, it will reverse direction).
Issue
App freezes when I minimize it and also sometimes takes a long time to load and when it loads I see a black screen.
QUESTION
Please try to run the code it is just one file shown below, I just use SurfaceView as layout. There is nothing advanced in term of what app does.
I'm confused as to why we need to use SurfaceHolder.Callback anonymous class (used in a method in the nested SurfaceView class) if there are life cycle methods I write called a pause, resume and stop in nested SurfaceView class that is called by the Main Activity's onPause, onResume, onStop methods. The entire code is shown followed by the structure of app to see an overview that I made because I don't see the point of SurfaceHolder.Callback methods so I mean I don't know why we need to use surfaceCreated, surfaceChanged, surfaceDestroyed and I don't know what to put in surfaceChanged. I also have an onSaveInstanceSate and onRestoreInstance state methods that just save the bitmap's x and y coordinates.
public class MainActivity extends Activity {
GameView gameView;
Handler myHandler;
int xPos = 0;
int yPos = 0;
int deltaX = 3;
int deltaY = 3;
int iconWidth;
int iconHeight;
static final String STATE_POS_X = "playerPosX";
static final String STATE_POS_Y = "playerPosY";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
myHandler = new Handler ();
gameView = new GameView(this);
setContentView(gameView);
}
class GameView extends SurfaceView {
private SurfaceHolder surfaceHolder;
private Bitmap bmpIcon;
private MyThread myThread;
volatile boolean playingGame = true;
public GameView(Context context) {
super(context);
init();
}
public GameView(Context context,
AttributeSet attrs) {
super(context, attrs);
init();
}
public GameView(Context context,
AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init(){
myThread = new MyThread(this);
surfaceHolder = getHolder();
bmpIcon = BitmapFactory.decodeResource(getResources(),
R.drawable.rubberBall);
iconWidth = bmpIcon.getWidth();
iconHeight = bmpIcon.getHeight();
surfaceHolder.addCallback( new SurfaceHolder.Callback(){
#Override
public void surfaceCreated(SurfaceHolder holder) {
myThread.setRunning(true);
myThread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder,
int format, int width, int height) {
// What do I enter here???
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
myThread.setRunning(false);
while (retry) {
try {
myThread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}});
}
protected void drawSomething(Canvas canvas) {
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(bmpIcon,
getWidth()/2, getHeight()/2, null);
xPos += deltaX;
if(deltaX > 0){
if(xPos >= getWidth() - iconWidth){
deltaX *= -1;
}
}else{
if(xPos <= 0){
deltaX *= -1;
}
}
yPos += deltaY;
if(deltaY > 0){
if(yPos >= getHeight() - iconHeight){
deltaY *= -1;
}
}else{
if(yPos <= 0){
deltaY *= -1;
}
}
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(bmpIcon,
xPos, yPos, null);
}
public void pause() {
playingGame = false;
try {
myThread.join();
} catch (InterruptedException e) {
}
}
public void resume() {
playingGame = true;
myThread = new MyThread(this);
myThread.start();
}
}//END INNER CLASS: GameView
class MyThread extends Thread {
GameView myView;
private boolean running = false;
public MyThread(GameView view) {
myView = view;
}
public void setRunning(boolean run) {
running = run;
}
#Override
public void run() {
while (running){
Canvas canvas = myView.getHolder().lockCanvas();
if(canvas != null) {
synchronized (myView.getHolder()) {
myView.drawSomething(canvas);
}
myView.getHolder().unlockCanvasAndPost(canvas);
}
try {
this.sleep(30);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}//END WHILE
}
}//END INNER CLASS: MyThread
/**
* BELOW are Main Activity Life Cycle Call Back methods!
*
*/
#Override
protected void onStop() {
super.onStop();
Log.d("onStop", "Main Activity's onStop called");
while (true) {
gameView.pause();
break;
}
this.finish();
}
#Override
protected void onResume() {
super.onResume();
Log.d("onResume", "Main Activity's onResume called");
gameView.resume();
}
#Override
protected void onPause() {
super.onPause();
Log.d("onPause", "Main Activity's onPause called");
gameView.pause();
}
//save and restore state
#Override
public void onSaveInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can save the view hierarchy state
super.onSaveInstanceState(savedInstanceState);
// Save the user's current game state
savedInstanceState.putInt(STATE_POS_X, xPos);
savedInstanceState.putInt(STATE_POS_Y, yPos);
}
public void onRestoreInstanceState(Bundle savedInstanceState) {
// Always call the superclass so it can restore the view hierarchy
super.onRestoreInstanceState(savedInstanceState);
// Restore state members from saved instance
xPos = savedInstanceState.getInt(STATE_POS_X);
yPos = savedInstanceState.getInt(STATE_POS_Y);
}
}//END CLASS: MainActivity
STRUCTURE of MainActivity housing the nested SurfaceView class
MainActivity life cycle methods
--------------------------------
onCreate:
------------
-links up the layout which is the SurfaceView instance
-initialize variables
onPause:
---------
call the SurfaceView's custom pause method here in addition to calling the
super's onPause
onStop:
------
call the SurfaceView's custom stop method here in addition to calling the
super's onStop
onResume:
---------
call the SurfaceView's custom resume method here in addition to calling the
super's onResume
nested Thread class
------------------------
run method to run SurfaceView
nested class SurfaceView's life cycle methods
-------------------------------------------------------
pause method which pauses the worker thread
---------------------------------------------
stop the worker thread:
stop method which stops the worker thread:
-----------------------------------------
stop the worker thread
resume method which creates a new worker thread:
---------------------------------------------------
make a new worker thread
SurfaceHolder.Callback lifespan methods
***Why do we need to write the methods below if I have pause,
resume stop already that will be called by the Main Activity's
onXXX, respectively????
==========================================
surfaceCreated:
---------------
make a new worker thread
surfaceChanged:
---------------
What do I enter here??
surfaceDestroyed:
-----------------
destroy current worker thread
END of nested SurfaceView class
override onSaveInstanceState method:
------------------------------------
save the bitmap's position (x and y coordinates)
override onRestoreInstanceState method:
-----------------------------------------
restore the bitmap's position (x and y coordinates)
END of MainActivity
Check the very well explanation because SurfaceView is more fine tuned control of graphics unlike drawing with a Custom View or using predefined graphical inputs or GUI elems.
http://blog.infrared5.com/2011/07/android-graphics-and-animation-part-ii-animation/
To preface, I'm probably going to work with Views instead of SurfaceView given this weird interaction, but my curiosity is getting the better of me and I want to know what's going on.
So I have a matrix class variable. I run matrix.setTranslate() once, and every other frame I say matrix.setTranslate(). After this I call canvas.drawBitmap(, matrix, null). After 100 frames, I stop drawing the bitmap.
Here's the code:
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
// matrix = new Matrix(); //Doesn't matter if I add this.
// matrix.reset(); //This doesn't matter either.
if (!once) {
matrix.setTranslate(100, 100);
} else {
matrix.setTranslate(800,800);
}
once = true;
if (++timer < 100) {
canvas.drawBitmap(ball, matrix, null);
}
}
What I expect to happen: Three possibilities.
Only the bottom right bitmap is visible since the entire screen was invalidated
Both bitmaps are visible because SurfaceView was smart with the dirty rectangle
Nothing is shown because nothing was drawn.
What actually happens: The top left bitmap blinks, bottom right bitmap displays solidly.
I'm pretty sure I have all of my bases covered:
All class variables are properly set in the constructor.
SurfaceView.onDraw() is called every 33 millis in its own thread.
Thread calls lockCanvas, then onDraw, then unlockCanvasAndPost
So, what's going on here? And bonus question, do these ghost images consume any extra resources and how can I clear them?
Rest of the code, mostly boilerplate:
public class FullscreenActivity extends Activity {
GameSurface ball;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ball = new GameSurface(this);
setContentView(ball);
}
}
class GameSurface extends SurfaceView implements SurfaceHolder.Callback {
GameThread thread;
boolean once = false;
Bitmap ball;
Matrix matrix;
int timer = 0;
public GameSurface(Context context) {
super(context);
ball = BitmapFactory.decodeResource(getResources(),R.drawable.football);
matrix = new Matrix();
getHolder().addCallback(this);
setFocusable(true);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
// matrix = new Matrix(); //Doesn't matter if I add this.
// matrix.reset(); //This doesn't matter either.
if (!once) {
matrix.setTranslate(100, 100);
} else {
matrix.setTranslate(800,800);
}
//matrix.postRotate(timer); //For even more weirdness...
once = true;
if (++timer < 100) {
canvas.drawBitmap(ball, matrix, null);
}
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
thread = new GameThread(getHolder(), this);
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
class GameThread extends Thread {
private SurfaceHolder surfaceHolder;
private GameSurface gameView;
private boolean run = false;
public GameThread(SurfaceHolder surfaceHolder, GameSurface gameView) {
this.surfaceHolder = surfaceHolder;
this.gameView = gameView;
}
public void setRunning(boolean run) {
this.run = run;
}
#Override
public void run() {
Canvas c;
while (run) {
c = null;
try {
Thread.sleep(33);
}
catch(InterruptedException e) {}
try {
c = surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
gameView.onDraw(c);
}
} finally {
if (c != null) {
surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
}
So I am essentially making a Pong game that has a Activity that sets its contentView() as a SurfaceView.
public class Pong_Activity extends Activity {
private static final String TAG = Pong_Activity.class.getSimpleName();
static int screenWidth;
static int screenHeight;
public View image;
LayoutInflater inflater;
RelativeLayout mainView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
Display screen = getWindowManager().getDefaultDisplay();
Rect rect_screen = new Rect();
screen.getRectSize(rect_screen);
screenWidth = rect_screen.width();
screenHeight = rect_screen.height();
Log.d(TAG, "The size of the screen is width: " + screenWidth
+ "height: " + screenHeight);
// set Content view to surfaceView (the game panel)
setContentView(new MainGamePanel(this));
Log.d(TAG, "SurfaceView mainGamePanel added");
}
Within the SurfaceView I have overrided the onDraw() and call it continuously through an inner Thread class to make the graphics move. I know if you do not repaint the canvas the
previous position of the graphics will be retained so I usally just call canvas.drawColor()
to get rid of that. Now I want to add in a image from my #drawables/ to place in the background of the surfaceView and refresh it when onDraw() is called, but it does not seem to be drawing the view from (background) onto the canvas.
public MainGamePanel(Context context ) {
super(context);
getHolder().addCallback(this);
// Create the thread for game loop
thread = new gameThread(getHolder(), this);
rectPlayer = new Player_Rect(leftX,false);
otherPlayer = new Player_Rect(rightX,true);
gameBall = new Ball();
inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
background = inflater.inflate(R.layout.basic_game_screen, null);
setFocusable(true);
Log.d(TAG, "mainGame Panel, thread created");
}
#Override
protected void onDraw(Canvas canvas) {
//canvas.drawColor(Color.BLACK);
background.draw(canvas);
gameBall.borderCollision();
gameBall.rectangleCollison(rectPlayer);
gameBall.rectangleCollison(otherPlayer);
otherPlayer.compterResponse(gameBall);
if (gameBall.cloneBall != null) {
gameBall.cloneBall.draw(canvas);
}
gameBall.draw(canvas);
rectPlayer.draw(canvas);
otherPlayer.draw(canvas);
}
This is where draw() is called, it is an inner class of MainGamepanel
private class gameThread extends Thread {
private boolean running;
private SurfaceHolder surfaceHolder;
private MainGamePanel gamePanel;
private Canvas canvas;
private static final String TAG = "gameThread";
public gameThread(SurfaceHolder holder, MainGamePanel panel) {
super("Gamethread");
this.surfaceHolder = holder;
this.gamePanel = panel;
}
public void setRunning(boolean running) {
this.running = running;
}
#Override
public void run() {
long threadRunTime = 0L;
Log.d(TAG, "Starting the game loop through game thread class.");
while (running) {
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
// One accessible by one thread at a time
synchronized (surfaceHolder) {
// Update the canvas by calling surface view methods.
this.gamePanel.onDraw(canvas);
}
} finally {
// If canvas exists reupdate all the drawn objects
// to the canvas through
if (canvas != null) {
surfaceHolder.unlockCanvasAndPost(canvas);
}
}
threadRunTime++;
}
Log.d(TAG, "The thread ran " + threadRunTime + "times");
}
}
good day... im a new programmer in android... and actually its my first time doing so...
but i have basic knowledge about java...
so here goes.. my game will have an icon that can be controlled by a joystick... and another icon that goes up and down the screen(non controllable) i want the speed to increase a little..... i have started the code but dont know where and how to start the collision.. another one is that the icon that is controllabe always passes the screen and pop out the opposite direction...
public class GameSurface1 extends SurfaceView implements SurfaceHolder.Callback {
private Context _context;
private GameThread1 _thread;
private GameControl _controls;
private GameJoystick1 _joystick;
private int y = 0;
private int xSpeed = 1;
private Bitmap _pointer, bmp;
public GameSurface1(Context context) {
super(context);
// TODO Auto-generated constructor stub
_context = context;
init();
}
private void init(){
//initialize our screen holder
SurfaceHolder holder = getHolder();
holder.addCallback( this);
//initialize our game engine
//initialize our Thread class. A call will be made to start it later
_thread = new GameThread1(holder, _context, new Handler(),this);
setFocusable(true);
_joystick = new GameJoystick1(getContext().getResources());
_pointer = (Bitmap)BitmapFactory.decodeResource(getResources(), R.drawable.icon1);
bmp = (Bitmap)BitmapFactory.decodeResource(getResources(), R.drawable.bad1);
//contols
_controls = new GameControl();
setOnTouchListener(_controls);
}
public void doDraw(Canvas canvas){
if (y == getHeight() - bmp.getHeight()) {
xSpeed = -1;
}
if (y == 0) {
xSpeed = 1;
}
y = y + xSpeed;
//update the pointer
_controls.update(null);
//draw the pointer
canvas.drawBitmap(_pointer, _controls._pointerPosition.x, _controls._pointerPosition.y, null);
//draw the joystick background
canvas.drawBitmap(_joystick.get_joystickBg(), 15,215, null);
//draw the dragable joystick
canvas.drawBitmap(_joystick.get_joystick(),_controls._touchingPoint.x - 26, _controls._touchingPoint.y - 26, null);
canvas.drawBitmap(bmp, 280, y, null);
}
//these methods are overridden from the SurfaceView super class. They are automatically called
//when a SurfaceView is created, resumed or suspended.
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {}
private boolean retry;
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
retry = true;
//code to end gameloop
_thread.state = GameThread1.STOPED;
while (retry) {
try {
//code to kill Thread
_thread.join();
retry = false;
} catch (InterruptedException e) {
}
}
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
if(_thread.state==GameThread1.PAUSED){
//When game is opened again in the Android OS
_thread = new GameThread1(getHolder(), _context, new Handler(),this);
_thread.start();
}else{
//creating the game Thread for the first time
_thread.start();
}
}
ill appreciate all the help you can give...
thank you
I have created a class like this:
public class nir extends Activity implements OnClickListener{
/** Called when the activity is first created. */
ImageButton btnNew, btnPlay, btnSignUp;
TextView txtTitle;
Typeface font;
//sprite
SurfaceView pet;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
font = Typeface.createFromAsset(getAssets(), "fonts/aaaiight.ttf");
btnNew = (ImageButton)findViewById(R.id.btnNew);
btnNew.setOnClickListener(this);
btnPlay = (ImageButton)findViewById(R.id.btnPlay);
btnPlay.setOnClickListener(this);
txtTitle = (TextView)findViewById(R.id.lblTama);
txtTitle.setTypeface(font);
//sprite
//setContentView(new MainGamePanel(this));
}
}
Now I want to make that SurfaceView show any sprite. I've tried
<view class="Tamagotchi.nir.MainGamePanel...">
in my XML, but it gives me a "Force Close" dialog.
I also have this class:
public class MainGamePanel extends SurfaceView implements
SurfaceHolder.Callback {
private static final String TAG = MainGamePanel.class.getSimpleName();
private MainThread thread;
private Sprite elaine;
// the fps to be displayed
private String avgFps;
public void setAvgFps(String avgFps) {
this.avgFps = avgFps;
}
public MainGamePanel(Context context) {
super(context);
// adding the callback (this) to the surface holder to intercept events
getHolder().addCallback(this);
// create Elaine and load bitmap
elaine = new Sprite(
BitmapFactory.decodeResource(getResources(),
R.drawable.walk_elaine),
10, 50, // initial position
30, 47, // width and height of sprite
5, 5); // FPS and number of frames in the animation
// create the game loop thread
thread = new MainThread(getHolder(), this);
// make the GamePanel focusable so it can handle events
setFocusable(true);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// at this point the surface is created and
// we can safely start the game loop
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
Log.d(TAG, "Surface is being destroyed");
// tell the thread to shut down and wait for it to finish
// this is a clean shutdown
boolean retry = true;
while (retry) {
try {
thread.join();
retry = false;
} catch (InterruptedException e) {
// try again shutting down the thread
}
}
Log.d(TAG, "Thread was shut down cleanly");
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// handle touch
}
return true;
}
public void render(Canvas canvas) {
canvas.drawColor(Color.BLACK);
elaine.draw(canvas);
// display fps
displayFps(canvas, avgFps);
}
/**
* This is the game update method. It iterates through all the objects
* and calls their update method if they have one or calls specific
* engine's update method.
*/
public void update() {
elaine.update(System.currentTimeMillis());
}
private void displayFps(Canvas canvas, String fps) {
if (canvas != null && fps != null) {
Paint paint = new Paint();
paint.setARGB(255, 255, 255, 255);
canvas.drawText(fps, this.getWidth() - 50, 20, paint);
}
}
}
What is the reason for the crash?
Take out view class =
in front of Your package name all you need is the package name.YourSurfaceViewClass
This is how your code should look
<Tamagotchi.nir.MainGamePanel.YourSurfaceViewClassName
android:id="#+id/myView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>