I have this code but they show errors in
myelement=new Element(getResources(),(int)event.getX(),(int)event.getY());
(Error: The constructor is undefined.
and
myelement.mX=(int)event.getX()-myelement.bitmap.getWidth()/2;
Error: mX cannot be resolved or is not a field
and
myelement.doDraw(canvas);
Error: The method doDraw(Canvas) is undefined for the type Element
public class GamePanel extends SurfaceView implements SurfaceHolder.Callback{
Element myelement;
private MainThread thread;
public GamePanel(Context context) {
super(context);
getHolder().addCallback(this);
thread =new MainThread(getHolder(),this);
setFocusable(true);
}
public boolean onTouchEvent(MotionEvent event) {
if(myelement==null)
{
myelement=new Element(getResources(),(int)event.getX(),(int)event.getY());
return true;
}
else
{
myelement.mX=(int)event.getX()-myelement.bitmap.getWidth()/2;
myelement.mY=(int)event.getY()-myelement.bitmap.getHeight()/2;
}
if(event.getAction()==MotionEvent.ACTION_DOWN)
{
myelement.mX=(int)event.getX()-myelement.bitmap.getWidth()/2;
myelement.mY=(int)event.getY()-myelement.bitmap.getHeight()/2;
}
if(event.getAction()==MotionEvent.ACTION_UP)
{
myelement.mX=(int)event.getX()-myelement.bitmap.getWidth()/2;
myelement.mY=(int)event.getY()-myelement.bitmap.getHeight()/2;
}
if(event.getAction()==MotionEvent.ACTION_MOVE)
{
myelement.mX=(int)event.getX()-myelement.bitmap.getWidth()/2;
myelement.mY=(int)event.getY()-myelement.bitmap.getHeight()/2;
}
return true;
}
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if(myelement!=null)
myelement.doDraw(canvas);
}
And:
public class Element {
Bitmap bitmap;
int mX;
int mY;
public Element(Resources res, int x,int y)
{
bitmap=BitmapFactory.decodeResource(res,R.drawable.ic_launcher);
mX=x-bitmap.getWidth()/2;
mY=y-bitmap.getHeight()/2;
}
public Element(Resources res, int x, int y, int idHinh)
{
bitmap=BitmapFactory.decodeResource(res,idHinh);
mX=x-bitmap.getWidth()/2;
mY=y-bitmap.getHeight()/2;
}
public void doDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, mX,mY, null);
}
}
Edit: First, double-check your import declarations. There are several Element classes present in the Android API, i.e. android.renderscript.Element, which you may be inadvertently accessing rather than your custom Element class.
Your Element constructor requires a Resources object for its first argument. However, you call getResources() inside a class that extends SurfaceView, whereas getResources() is a method associated with Context.
SurfaceView is a subclass of View, that has the getContext() method. So, instead of:
myelement=new Element(getResources(),(int)event.getX(),(int)event.getY());
try
myelement=new Element(this.getContext().getResources(),(int)event.getX(),(int)event.getY());
Related
I am trying to adapt a snake game in Android Studio so that game over triggers a GameOverActivity. The problem is that the game over text is currently written to the screen in the redrawCanvas() function:
public void redrawCanvas(Canvas canvas) {
if (this.snake.isEnabled()) {
this.snake.draw(canvas);
this.apple.draw(canvas);
this.score.draw(canvas);
} else {
Paint p = getPaint();
p.setTextSize(50);
p.setColor(Color.BLACK);
canvas.drawText("Game over!", 100, 100, p);
// LAUNCH PLAY AGAIN ACTIVITY HERE?
}
}
and this redrawCanvas code is contained in a class extending SurfaceView. I would ordinarily call an intent, but I can't call startActivity() from within a SurfaceView class. My SnakeGameActivity just sets the content view, and all the code occurs in this surface view. Here is the code in SnakeGameActivity:
public class SnakeGameActivity extends com.codepath.simplegame.GameActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//before activity is created : cold start
//switch back to original Theme (App Theme)
setTheme(R.style.AppTheme);
switchFullscreen();
setContentView(new SnakeGamePanel(this));
}
}
And here is the full code in SnakeGamePanel:
public class SnakeGamePanel extends AbstractGamePanel {
public SnakeGamePanel(Context context) {
super(context);
}
private SnakeActor snake;
private AppleActor apple ;
private ScoreBoard score;
private boolean isPaused = false;
#Override
public void onStart() {
this.snake = new SnakeActor(100, 100);
this.apple = new AppleActor(200, 50);
this.score = new ScoreBoard(this);
}
#Override
public void onTimer() {
if (!isPaused) {
if (this.snake.checkBoundsCollision(this)) {
this.snake.setEnabled(false);
}
this.snake.move();
if (this.apple.intersect(this.snake)) {
this.snake.grow();
this.score.earnPoints(50);
this.apple.reposition(this);
}
}
}
#Override
public void redrawCanvas(Canvas canvas) {
if (this.snake.isEnabled()) {
this.snake.draw(canvas);
this.apple.draw(canvas);
this.score.draw(canvas);
} else {
Paint p = getPaint();
p.setTextSize(50);
p.setColor(Color.BLACK);
canvas.drawText("Game over!", 100, 100, p);
// LAUNCH PLAY AGAIN ACTIVITY?
}
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
this.snake.handleKeyInput(keyCode);
if (keyCode == KeyEvent.KEYCODE_G) {
this.onStart();
}
if (keyCode == KeyEvent.KEYCODE_P) {
isPaused = !isPaused;
}
return true;
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
this.snake.handleTouchInput(event);
return true;
}
return false;
}
}
Is there any way to start an activity when the game ends?
One alternative to your inner class solution is to pass a Context object to the constructor of your SurfaceView subclass. Then you can call startActivity() on that context.
I found what seems to be a solution so far. I just made the SurfaceView extension class be an inner class in my activity. That way, it has an activity as a containing class.
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);
}
}
}
}
}
}
I just made an Activity which uses at "setContentView" a view from a class which extends SurfaceView. The problem is:
It works fine, but when I exit it (BACK key) it crashes. Code:
package ro.etrandafir.mate.appCreator;
import android.app.Activity;
import android.os.Bundle;
import android.content.Context;
import android.view.View;
import android.view.SurfaceView;
import android.graphics.Canvas;
import android.view.MotionEvent;
import android.graphics.Color;
import android.graphics.Paint;
public class Sample2 extends Activity implements View.OnTouchListener {
float x = 0, y = 0;
SampleTwoView theView;
public boolean onTouch(View v, MotionEvent event) {
// TODO: Implement this method
x = event.getX();
y = event.getY();
return true;
}
#Override
protected void onPause() {
super.onPause();
finish();
}
#Override
protected void onCreate(Bundle b) {
super.onCreate(b);
theView = new SampleTwoView(this);
theView.setOnTouchListener(this);
setContentView(theView);
}
public class SampleTwoView extends SurfaceView implements Runnable {
Paint p = new Paint();
public SampleTwoView(Context context) {
super(context);
p.setColor(Color.RED);
Thread theThread = new Thread(this);
theThread.start();
}
public void run() {
while (true) {
if (!getHolder().getSurface().isValid()) continue;
Canvas canvas;
canvas = getHolder().lockCanvas();
canvas.drawColor(Color.BLUE);
if ((x != 0) && (y != 0)) canvas.drawCircle(x, y, 40, p);
getHolder().unlockCanvasAndPost(canvas);
}
}
}
}
What can I do? Should I add onDestroy or what?
Thanks in advance,
Matei
The issue you are getting is related to this code:
Canvas canvas;
canvas = getHolder().lockCanvas();
canvas.drawColor(Color.BLUE);
When your activity ends, your thread is still running, but your custom SurfaceView is no longer available, so you will get a null ptr exception. Your existing code can easily be patched by adding a boolean that gets set to false as soon as the onPause fn gets called:
public void run() {
while (booleanThatGetsSetToFalseWhenActivityPauses) {
if (!getHolder().getSurface().isValid()) continue;
Canvas canvas;
canvas = getHolder().lockCanvas();
canvas.drawColor(Color.BLUE);
if ((x != 0) && (y != 0)) canvas.drawCircle(x, y, 40, p);
getHolder().unlockCanvasAndPost(canvas);
}
}
However, I would suggest altering the structure of your application as a whole. This may just be for practice, but I think a more efficient and bug free way of accomplishing your goal would be to simply use a standard SurfaceView and to completely decouple your drawing logic from any custom view.
My redesigned activity is below, but it utilizes a Ball class that is used to maintain the ball's logic, which, in your current code is separately coupled with both the actvity (the coordinates) and the view (the Paint). In this new ball class, a ball has a location (specified by a PointF), a Paint, and a diameter. It also has methods to get most of these variables in addition to setting some.
public class Ball {
private Paint mPaint;
private PointF mCoordinates;
private int mDiameter;
public Ball (int color, int diameter) {
mPaint = new Paint();
mPaint.setColor(color);
mCoordinates = new PointF();
mCoordinates.x = 0;
mCoordinates.y = 0;
mDiameter = diameter;
}
public void setCoordinates (float x, float y) {
mCoordinates.x = x;
mCoordinates.y = y;
}
public PointF getCoordinates() {
return mCoordinates;
}
public Paint getPaint() {
return mPaint;
}
public int getDiameter() {
return mDiameter;
}
/* You did not want to draw the uninitialized ball, so this method checks that */
public boolean hasNonZeroLocation () {
return (mCoordinates.x != 0 && mCoordinates.y != 0);
}
}
I use the Ball class in the activity as shown below. Notice that the redrawing to the canvas now only occurs when a user touches the canvas as opposed to an infinite while loop. This is due to the utilization of the Handler class which posts actions to run to the UI thread. Additionally, now we do not need a custom view, and our ball's logic has been decoupled from the activity and the view.
public class RedBallActivity extends Activity {
Handler mDrawingHandler;
SurfaceView mDrawingSurfaceView;
Ball mBall;
private final Runnable drawRedBallOnBlueSurface = new Runnable() {
#Override
public void run() {
if (!mDrawingSurfaceView.getHolder().getSurface().isValid()) return;
Canvas canvas = mDrawingSurfaceView.getHolder().lockCanvas();
canvas.drawColor(Color.BLUE);
if (mBall.hasNonZeroLocation())
canvas.drawCircle(mBall.getCoordinates().x, mBall.getCoordinates().y, mBall.getDiameter(), mBall.getPaint());
mDrawingSurfaceView.getHolder().unlockCanvasAndPost(canvas);
}
};
private final OnTouchListener mCanvasTouchListener = new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
mBall.setCoordinates(event.getX(), event.getY());
mDrawingHandler.post(drawRedBallOnBlueSurface);
return true;
}
};
#Override
protected void onCreate(Bundle b) {
super.onCreate(b);
mDrawingSurfaceView = new SurfaceView(this);
mDrawingSurfaceView.setOnTouchListener(mCanvasTouchListener);
setContentView(mDrawingSurfaceView);
mBall = new Ball(Color.RED, 40);
mDrawingHandler = new Handler();
}
}
Now, if you actually run this code you will notice that initially the screen is not drawn with a blue background. You might be tempted to simply call mDrawingHandler.post(drawRedBallOnBlueSurface); at the end of the onCreate method, but it is not guaranteed that the SurfaceView will be ready to be drawn upon (see the documentation on this lockCanvas method). If you want the surface to initially be blue, you need to implement a [SurfaceHolder.Callback][2], which needs to be connected to the SurfaceView's SurfaceHolder, and on the surfaceCreated method being called, we know the surface is ready, so we can then call mDrawingHandler.post(drawRedBallOnBlueSurface);
Now, with this added, I change the Activity to implement [SurfaceHolder.Callback][2] as follows:
public class FriendManagerActivity extends Activity implements SurfaceHolder.Callback {
and add this line to the constructor:
mDrawingSurfaceView.getHolder().addCallback(this);
and implement the interface:
#Override
public void surfaceCreated(SurfaceHolder holder) {
mDrawingHandler.post(drawRedBallOnBlueSurface);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
Feel free to ask any questions on my little redesign! While your problem could be easily patched, I felt like the way you were coupling logic with Views was a little bit flawed, and thought a little more info on SurfaceView coding would be helpful.
As someone mentioned it in the above, when your activity ends, your thread is still running, but your custom SurfaceView is no longer available, so you will get a Null Point Exception. Your existing code can easily be patched by adding a boolean that gets set to false as soon as the onPause fn gets called:I had the same problem. To solve it I added the following onPause() to your SampleTwoView class:
// pause method will destroy the Thread
public void pause() {
isRunning = false;
while (true) {
try {
myThread.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
myThread = null;
}
Then call this onPause() method in your onPause() method of your Sample2 class as follows:
#Override
protected void onPause() {
super.onPause();
SampleTwoView.onPause();
finish();
}
So everytime the onPause() method of your main Activity class is called the Thread will be destroyed.
I hope this will help you.
Cheers!
I am trying to do a basic game.I have classes named Ball.java , Scratch.java and Panel.java
In Panel,I am trying to get information from Ball.java class but I am getting NullPointerException.Where is the mistake in my code?
Getting exceiption in this code in Panel.java
public Rect getBoundsBall(){
return new Rect (top.getX(), top.getY(),top.getX()+ball.getWidth() ,top.getY()+ball.getHeight() );
}
Error Log
10-13 12:57:28.746: E/AndroidRuntime(367): FATAL EXCEPTION: Thread-10
10-13 12:57:28.746: E/AndroidRuntime(367): java.lang.NullPointerException
10-13 12:57:28.746: E/AndroidRuntime(367): at com.emredavarci.denemeler.Panel.getBoundsBall(Panel.java:44)
10-13 12:57:28.746: E/AndroidRuntime(367): at com.emredavarci.denemeler.Panel.update(Panel.java:70)
10-13 12:57:28.746: E/AndroidRuntime(367): at com.emredavarci.denemeler.TutorialThread.run(TutorialThread.java:30)
Panel.java
public class Panel extends SurfaceView implements SurfaceHolder.Callback {
private TutorialThread _thread;
Scratch raket=new Scratch();
Ball top=new Ball();
Bitmap ball;
Bitmap _scratch;
public Panel(Context context) {
super(context);
getHolder().addCallback(this);
_thread = new TutorialThread(getHolder(), this); /
setFocusable(true);
}
#Override
public boolean onTouchEvent(MotionEvent event) { // to
switch (event.getAction()){
case MotionEvent.ACTION_MOVE: //
raket.setX((int)(event.getX()));
break;
}
return true;
}
public Rect getBoundsBall(){
return new Rect (top.getX(), top.getY(),top.getX()+ball.getWidth() ,top.getY()+ball.getHeight() );
}
public Rect getBoundsScratch(){
return new Rect (raket.getX(), raket.getY(),raket.getX()+_scratch.getWidth() ,raket.getY()+_scratch.getHeight() );
}
public void update(){ /
if((top.getX()<480) && (top.getX()>0)){
top.setX(top.getX()+top.getxdirection());
}
if((top.getX()==480) || (top.getX()==0)){
top.setxdirection(-1);
top.setX(top.getX()+top.getxdirection());
}
if((top.getY()<780) && (top.getY()>0)){
top.setY(top.getY()+top.getydirection());
}
if((top.getY()==780) || (top.getY()==0)){
top.setydirection(-1);
top.setY(top.getY()+top.getydirection());
}
Rect BallBounds = getBoundsBall();
Rect ScratchBounds = getBoundsScratch();
if( BallBounds.intersect(ScratchBounds) ){
top.setydirection(-1);
//top.setY(top.getY()); !!!!
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
_thread.setRunning(true);
_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...
}
}
}
#Override
public void onDraw(Canvas canvas) {
_scratch = BitmapFactory.decodeResource(getResources(), R.drawable.red2);
ball = BitmapFactory.decodeResource(getResources(), R.drawable.ball);
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(_scratch, raket.getX() - (_scratch.getWidth() / 2), raket.getY() - (_scratch.getHeight() / 2), null);
canvas.drawBitmap(ball, top.getX() - (ball.getWidth() / 2), top.getY() - (ball.getHeight() / 2), null);
}
}
Ball.java
public class Ball {
private int x=100; // the X coordinate
private int y=100; // the Y coordinate
int xdirection=10;
int ydirection=10;
public Ball() {
// TODO Auto-generated constructor stub
}
public int getX(){
return x;
}
public int getY(){
return y;
}
public void setX(int a){
x=a;
}
public void setY(int b){
y=b;
}
public int getxdirection(){
return xdirection;
}
public int getydirection(){
return ydirection;
}
public void setxdirection(int a){
xdirection=xdirection*a;
}
public void setydirection(int b){
ydirection=ydirection*b;
}
//while ile ball u hareket ettir
//ball un koordinatlarını sakla
}
Scratch.java
public class Scratch {
private int x = 250;
private int y = 600;
public Scratch() {
// TODO Auto-generated constructor stub
}
public void setX(int a){
x=a;
}
public void setY(int b){
y=b;
}
public int getX(){
return x;
}
public int getY(){
return y;
}
}
You are missing something like:
Ball top = new Ball();
i.e. the variable top is not initialized, but used in the update method.
Also, initialize the ball object outsite of onDraw. Who knows if update will be called before onDraw?
Adding to #Rudolph's answer, are you sure Bitmap ball is initialized? To be sure, try logging ball as:
public Rect getBoundsBall(){
log.v("ball",""+ball);
return new Rect (top.getX(), top.getY(),top.getX()+ball.getWidth() ,top.getY()+ball.getHeight() );
}
Either ball or top is the culprit. Find out which one is uninitialized and tackle it accordingly.