Android - How to increase application performance with animated backgrounds? - android

I have and animated background for all screens in the application. I have
created that animated background using surface view and thread.
Here
is my SurfaceView class.
public class FloatingCirclesPanel extends SurfaceView implements
SurfaceHolder.Callback {
private static final String TAG = FloatingCirclesPanel.class
.getSimpleName();
public MainThread thread;
private Circle circle_white1;
private Circle circle_blue1;
private Circle circle_white2;
private Circle circle_blue2;
private Bitmap scaled;
Canvas canvas = null;
private Display mdisp;
private Context context;
private RotateAnimation anim;
private Matrix matrix;
#SuppressLint("NewApi")
public FloatingCirclesPanel(Context context) {
super(context);
this.context = context;
matrix = new Matrix();
// adding the callback (this) to the surface holder to intercept events
getHolder().addCallback(this);
// create droid and load bitmap
circle_white1 = new Circle(BitmapFactory.decodeResource(getResources(),
R.drawable.circle), 50, 50);
mdisp = ((Activity) getContext()).getWindowManager()
.getDefaultDisplay();
Point mdispSize = new Point();
mdisp.getSize(mdispSize);
int maxX = mdispSize.x;
int maxY = mdispSize.y;
Bitmap b = scaleDown(BitmapFactory.decodeResource(getResources(),
R.drawable.circle_img), 300, true);
Bitmap b1 = scaleDown(BitmapFactory.decodeResource(getResources(),
R.drawable.circle_img), 130, true);
Bitmap b2 = scaleDown(
BitmapFactory.decodeResource(getResources(), R.drawable.circle),
100, true);
// droid1 = new Droid(BitmapFactory.decodeResource(getResources(),
// R.drawable.icon), 150, 150);
if (b != null) {
circle_blue1 = new Circle(b, 500, 500);
} else {
circle_blue1 = new Circle(BitmapFactory.decodeResource(
getResources(), R.drawable.circle_img), 500, 500);
}
if (b1 != null) {
circle_white2 = new Circle(b1, 800, 800);
} else {
circle_white2 = new Circle(BitmapFactory.decodeResource(
getResources(), R.drawable.circle), 800, 800);
}
if (b2 != null) {
circle_blue2 = new Circle(b2, 1500, 1500);
} else {
circle_blue2 = new Circle(BitmapFactory.decodeResource(
getResources(), R.drawable.circle_img), 1500, 1500);
}
// droid3 = new Droid(BitmapFactory.decodeResource(getResources(),
// R.drawable.icon), 150, 150);
// create the game loop thread
thread = new MainThread(getHolder(), this, context);
// make the GamePanel focusable so it can handle events
setFocusable(true);
}
public FloatingCirclesPanel(Context context, AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
public FloatingCirclesPanel(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
public static Bitmap scaleDown(Bitmap realImage, float maxImageSize,
boolean filter) {
float ratio = Math.min((float) maxImageSize / realImage.getWidth(),
(float) maxImageSize / realImage.getHeight());
int width = Math.round((float) ratio * realImage.getWidth());
int height = Math.round((float) ratio * realImage.getHeight());
Bitmap newBitmap = Bitmap.createScaledBitmap(realImage, width, height,
filter);
return newBitmap;
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
// at this point the surface is created and
// we can safely start the game loop
if (thread != null && (thread.getState() == Thread.State.NEW)) {
thread.setRunning(true);// riga originale
thread.start();// riga originale
}
// after a pause it starts the thread again
else if (thread != null && thread.getState() == Thread.State.TERMINATED) {
thread = new MainThread(getHolder(), this, context);
;
thread.setRunning(true);
thread.start(); // Start a new thread
}
// 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.interrupt();
retry = false;
thread = null;
} catch (Exception e) {
// try again shutting down the thread
}
}
Log.d(TAG, "Thread was shut down cleanly");
}
public void render(Canvas canvas) {
if (canvas != null) {
Rect dest = new Rect(0, 0, getWidth(), getHeight());
Paint paint = new Paint(Paint.FILTER_BITMAP_FLAG);
paint.setFilterBitmap(true);
paint.setDither(true);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.splashscreen);
canvas.drawBitmap(bitmap, null, dest, paint);
// canvas.drawColor(Color.BLUE);
circle_white1.draw(canvas);
circle_blue1.draw(canvas);
circle_white2.draw(canvas);
circle_blue2.draw(canvas);
}
}
private void createAnimation(Canvas canvas) {
anim = new RotateAnimation(0, 360, getWidth() / 2, getHeight() / 2);
anim.setRepeatMode(Animation.RESTART);
anim.setRepeatCount(Animation.INFINITE);
anim.setDuration(10000L);
((Activity) context).runOnUiThread(new Runnable() {
#Override
public void run() {
startAnimation(anim);
}
});
}
/**
* 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() {
// check collision with right wall if heading right
if (circle_white1.getSpeed().getxDirection() == Speed.DIRECTION_RIGHT
&& circle_white1.getX() + circle_white1.getBitmap().getWidth()
/ 2 >= getWidth()) {
circle_white1.getSpeed().toggleXDirection();
}
// check collision with left wall if heading left
if (circle_white1.getSpeed().getxDirection() == Speed.DIRECTION_LEFT
&& circle_white1.getX() - circle_white1.getBitmap().getWidth()
/ 2 <= 0) {
circle_white1.getSpeed().toggleXDirection();
}
// check collision with bottom wall if heading down
if (circle_white1.getSpeed().getyDirection() == Speed.DIRECTION_DOWN
&& circle_white1.getY() + circle_white1.getBitmap().getHeight()
/ 2 >= getHeight()) {
circle_white1.getSpeed().toggleYDirection();
}
// check collision with top wall if heading up
if (circle_white1.getSpeed().getyDirection() == Speed.DIRECTION_UP
&& circle_white1.getY() - circle_white1.getBitmap().getHeight()
/ 2 <= 0) {
circle_white1.getSpeed().toggleYDirection();
}
// Update the lone droid
circle_white1.update();
if (circle_blue1.getSpeed().getxDirection() == Speed.DIRECTION_RIGHT
&& circle_blue1.getX() + circle_blue1.getBitmap().getWidth()
/ 2 >= getWidth()) {
circle_blue1.getSpeed().toggleXDirection();
}
// check collision with left wall if heading left
if (circle_blue1.getSpeed().getxDirection() == Speed.DIRECTION_LEFT
&& circle_blue1.getX() - circle_blue1.getBitmap().getWidth()
/ 2 <= 0) {
circle_blue1.getSpeed().toggleXDirection();
}
// check collision with bottom wall if heading down
if (circle_blue1.getSpeed().getyDirection() == Speed.DIRECTION_DOWN
&& circle_blue1.getY() + circle_blue1.getBitmap().getHeight()
/ 2 >= getHeight()) {
circle_blue1.getSpeed().toggleYDirection();
}
// check collision with top wall if heading up
if (circle_blue1.getSpeed().getyDirection() == Speed.DIRECTION_UP
&& circle_blue1.getY() - circle_blue1.getBitmap().getHeight()
/ 2 <= 0) {
circle_blue1.getSpeed().toggleYDirection();
}
// Update the lone droid1
circle_blue1.update();
if (circle_white2.getSpeed().getxDirection() == Speed.DIRECTION_RIGHT
&& circle_white2.getX() + circle_white2.getBitmap().getWidth()
/ 2 >= getWidth()) {
circle_white2.getSpeed().toggleXDirection();
}
// check collision with left wall if heading left
if (circle_white2.getSpeed().getxDirection() == Speed.DIRECTION_LEFT
&& circle_white2.getX() - circle_white2.getBitmap().getWidth()
/ 2 <= 0) {
circle_white2.getSpeed().toggleXDirection();
}
// check collision with bottom wall if heading down
if (circle_white2.getSpeed().getyDirection() == Speed.DIRECTION_DOWN
&& circle_white2.getY() + circle_white2.getBitmap().getHeight()
/ 2 >= getHeight()) {
circle_white2.getSpeed().toggleYDirection();
}
// check collision with top wall if heading up
if (circle_white2.getSpeed().getyDirection() == Speed.DIRECTION_UP
&& circle_white2.getY() - circle_white2.getBitmap().getHeight()
/ 2 <= 0) {
circle_white2.getSpeed().toggleYDirection();
}
// Update the lone droid2
circle_white2.update();
if (circle_blue2.getSpeed().getxDirection() == Speed.DIRECTION_RIGHT
&& circle_blue2.getX() + circle_blue2.getBitmap().getWidth()
/ 2 >= getWidth()) {
circle_blue2.getSpeed().toggleXDirection();
}
// check collision with left wall if heading left
if (circle_blue2.getSpeed().getxDirection() == Speed.DIRECTION_LEFT
&& circle_blue2.getX() - circle_blue2.getBitmap().getWidth()
/ 2 <= 0) {
circle_blue2.getSpeed().toggleXDirection();
}
// check collision with bottom wall if heading down
if (circle_blue2.getSpeed().getyDirection() == Speed.DIRECTION_DOWN
&& circle_blue2.getY() + circle_blue2.getBitmap().getHeight()
/ 2 >= getHeight()) {
circle_blue2.getSpeed().toggleYDirection();
}
// check collision with top wall if heading up
if (circle_blue2.getSpeed().getyDirection() == Speed.DIRECTION_UP
&& circle_blue2.getY() - circle_blue2.getBitmap().getHeight()
/ 2 <= 0) {
circle_blue2.getSpeed().toggleYDirection();
}
// Update the lone droid3
circle_blue2.update();
}
}
I am adding that surfaceView into my activity like below
#Override
protected void onStart() {
super.onStart();
View childView = getLayoutInflater().inflate(R.layout.main, null);
circleAnimation = new FloatingCirclesPanel(this);
setContentView(circleAnimation);
final ImageView image = (ImageView) childView.findViewById(R.id.logout);
Now the problem is the app is running slow while navigating through screens in the app.
If I add that SurfaceView code in onStart/onResume entire views are redesigning twice and causing performance issues.
How can I improve performance?

Related

How to implement Accelerometer into app correctly

I want to control my simple android game (arcanoid) with accelerometer. Paddle in game is now being controlled with touch screen event. I want to control it with accelerometer.
I tried to implement accelerometer into GameActivity class which is "controlling" BreakOutView class like this:
public class GameActivity extends Activity implements SensorEventListener {
// gameView will be the view of the Menu_Layout
// It will also hold the logic of the Menu_Layout
// and respond to screen touches as well
BreakOutView breakoutView;
private SensorManager sManager;
Sensor accelerometer;
Paddle paddle;
float x;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
breakoutView = new BreakOutView(this);
sManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); // zisk managera
if (sManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) != null) {
accelerometer = sManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sManager.registerListener(this, accelerometer, SensorManager.SENSOR_DELAY_NORMAL);
}
// Initialize gameView and set it as the view
setContentView(breakoutView);
}
// This method executes when the player starts the Game
#Override
protected void onResume() {
super.onResume();
sManager.registerListener(this,accelerometer,SensorManager.SENSOR_DELAY_NORMAL);
// Tell the gameView resume method to execute
breakoutView.resume();
}
// This method executes when the player quits the Menu_Layout
#Override
protected void onPause() {
super.onPause();
sManager.unregisterListener(this);
// Tell the gameView pause method to execute
breakoutView.pause();
}
#Override
public void onSensorChanged(SensorEvent sensorEvent) {
if (sensorEvent.sensor.getType() == Sensor.TYPE_ACCELEROMETER)
{
x = sensorEvent.values[0];
if (x > 0) {
breakoutView.paddle.setMovementState(paddle.LEFT);
}
else { breakoutView.paddle.setMovementState(paddle.RIGHT);
}
}
}
#Override
public void onAccuracyChanged(Sensor sensor, int i) {
}
}
This is code for BreakOutView class.
onTouchEvent method is now disabled because I want to use accelerometer to control Paddle in application.
public class BreakOutView extends SurfaceView implements Runnable{
// This is our thread
Thread gameThread = null;
// This is new. We need a SurfaceHolder
// When we use Paint and Canvas in a thread
// We will see it in action in the draw method soon.
SurfaceHolder ourHolder;
// A boolean which we will set and unset
// when the Menu_Layout is running- or not.
volatile boolean playing;
// Game is paused at the start
boolean paused = true;
// A Canvas and a Paint object
Canvas canvas;
Paint paint;
// This variable tracks the Menu_Layout frame rate
long fps;
Bitmap bitmapBob;
Bitmap bitmapBall;
Bitmap bitmapPaddal;
Bitmap bitmapBrick1;
Bitmap bitmapBrick2;
Bitmap bitmapBrick3;
// The size of the screen in pixels
int screenX;
int screenY;
// The players paddle
Paddle paddle;
// A ball
Ball ball;
// Up to 200 bricks
Brick[] bricks = new Brick[24];
int numBricks = 0;
// For sound FX
SoundPool soundPool;
int beep1ID = -1;
int beep2ID = -1;
int beep3ID = -1;
int loseLifeID = -1;
int explodeID = -1;
// The score
int score = 0;
int level = 1;
// Lives
int lives = 3;
Rect dest;
DisplayMetrics dm;
int densityDpi;
// When we initialize (call new()) on BreakOutView
// This special constructor method runs
public BreakOutView(Context context) {
super(context);
// The next line of code asks the
// SurfaceView class to set up our object.
// How kind.
// Initialize ourHolder and paint objects
ourHolder = getHolder();
paint = new Paint();
// Get a Display object to access screen details
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
// Load the resolution into a Point object
Point size = new Point();
// TODO target API < 13
display.getSize(size);
screenX = size.x;
screenY = size.y;
// using dpi to set sizes for objects
dm = context.getResources().getDisplayMetrics();
densityDpi = dm.densityDpi;
paddle = new Paddle(screenX, screenY, densityDpi);
// Create a ball
ball = new Ball(screenX, screenY);
// Load the sounds
// This SoundPool is deprecated but don't worry
soundPool = new SoundPool(10, AudioManager.STREAM_MUSIC, 0);
try {
// Create objects of the 2 required classes
AssetManager assetManager = context.getAssets();
AssetFileDescriptor descriptor;
// Load our fx in memory ready for use
descriptor = assetManager.openFd("beep1.wav");
beep1ID = soundPool.load(descriptor, 0);
descriptor = assetManager.openFd("beep2.wav");
beep2ID = soundPool.load(descriptor, 0);
descriptor = assetManager.openFd("beep3.wav");
beep3ID = soundPool.load(descriptor, 0);
descriptor = assetManager.openFd("loseLife.wav");
loseLifeID = soundPool.load(descriptor, 0);
descriptor = assetManager.openFd("explode.wav");
explodeID = soundPool.load(descriptor, 0);
} catch (IOException e) {
// Print an error message to the console
Log.e("error", "failed to load sound files");
}
// Load Images from resource files
bitmapBob = BitmapFactory.decodeResource(this.getResources(), R.drawable.wall);
bitmapBall = BitmapFactory.decodeResource(this.getResources(), R.drawable.ball);
bitmapPaddal = BitmapFactory.decodeResource(this.getResources(), R.drawable.ball);
bitmapBrick1 = BitmapFactory.decodeResource(this.getResources(), R.drawable.brick_red);
bitmapBrick2 = BitmapFactory.decodeResource(this.getResources(), R.drawable.brick_green);
bitmapBrick3 = BitmapFactory.decodeResource(this.getResources(), R.drawable.brick_monster);
//Make Sizes Depending on DPI
int heightX = densityDpi / 8;
float length_Paddal = densityDpi / 1.50f;
int height_Paddal = densityDpi / 7;
int brickWidth = screenX / 8;
int brickHeight = screenY / 10;
bitmapBall = getResizedBitmap(bitmapBall, heightX, heightX);
bitmapPaddal = getResizedBitmap(bitmapPaddal, length_Paddal, height_Paddal);
bitmapBrick1 = getResizedBitmap(bitmapBrick1, brickWidth, brickHeight);
bitmapBrick2 = getResizedBitmap(bitmapBrick2, brickWidth, brickHeight);
bitmapBrick3 = getResizedBitmap(bitmapBrick3, brickWidth, brickHeight);
// Create bricks for level 1
createBricksAndRestart(1);
}
public void createBricksAndRestart(int Xlevel) {
// Put the ball back to the start
ball.reset(screenX, screenY);
level = Xlevel;
switch (Xlevel) {
case 2:
// level 2
ball.xVelocity = 600;
ball.yVelocity = -1000;
break;
// level 3
case 3:
ball.xVelocity = 1000;
ball.yVelocity = -1400;
break;
// level 1
default:
ball.xVelocity = 400;
ball.yVelocity = -800;
break;
}
// Brick Size
int brickWidth = screenX / 8;
int brickHeight = screenY / 10;
// Build a wall of bricks
numBricks = 0;
for (int column = 0; column < 8; column++) {
for (int row = 0; row < 3; row++) {
bricks[numBricks] = new Brick(row, column, brickWidth, brickHeight);
numBricks++;
}
}
// if Game is over reset scores ,lives &Level
if (lives == 0) {
score = 0;
lives = 3;
level = 1;
}
}
#Override
public void run() {
while (playing) {
// Capture the current time in milliseconds in startFrameTime
long startFrameTime = System.currentTimeMillis();
// Update the frame
if (!paused) {
update();
}
// Draw the frame
draw();
// Calculate the fps this frame
// We can then use the result to
// time animations and more.
long timeThisFrame = System.currentTimeMillis() - startFrameTime;
if (timeThisFrame >= 1) {
fps = 1000 / timeThisFrame;
}
}
}
// Everything that needs to be updated goes in here
// Movement, collision detection etc.
public void update() {
// Move the paddle if required
paddle.update(fps);
ball.update(fps);
// Check for ball colliding with a brick
for (int i = 0; i < numBricks; i++) {
if (bricks[i].getVisibility()) {
if (RectF.intersects(bricks[i].getRect(), ball.getRect())) {
bricks[i].setInvisible();
ball.reverseYVelocity();
score = score + 10;
soundPool.play(explodeID, 1, 1, 0, 0, 1);
}
}
}
// Check for ball colliding with paddle
if (
ball.getRect().intersect(paddle.getRect()) ||
RectF.intersects(paddle.getRect(), ball.getRect()) ||
paddle.getRect().intersect(ball.getRect())
) {
ball.reverseYVelocity();
// ReverseX Direction + IncreaseX speed
if (paddle.getMovementState() == paddle.RIGHT && ball.xVelocity < 0 || paddle.getMovementState() == paddle.LEFT && ball.xVelocity > 0) {
ball.reverseXVelocity();
}
// SameX Direction + IncreaseX speed
else if (paddle.getMovementState() == paddle.RIGHT && ball.xVelocity > 0 || paddle.getMovementState() == paddle.LEFT && ball.xVelocity < 0) {
ball.sameXVelocity();
}
/*// Paddle is still, DecreaseX speed
else if (paddle.getMovementState() == paddle.STOPPED) {
ball.zeroXVelocity();
}*/
// Some intersection Bugs
ball.clearObstacleY(paddle.getRect().top - 20);
soundPool.play(beep1ID, 1, 1, 0, 0, 1);
}
// Bounce the ball back when it hits the bottom of screen
// And Lose a life
if (ball.getRect().bottom > screenY) {
ball.reverseYVelocity();
ball.clearObstacleY(screenY - 5);
// Lose a life
lives--;
soundPool.play(loseLifeID, 1, 1, 0, 0, 1);
if (lives == 0) {
paused = true;
//draw Loss;
canvas = ourHolder.lockCanvas();
paint.setColor(getResources().getColor(R.color.orange));
paint.setTextSize(getResources().getDimension(R.dimen.text_size_big));
canvas.drawText("أنت خسرت!",
screenX / 2 - (densityDpi / 1.90f), screenY / 2 + (densityDpi), paint);
ourHolder.unlockCanvasAndPost(canvas);
try {
// Wait 3 seconds then reset a new game
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// Create bricks at level 1
createBricksAndRestart(1);
}
}
// Pause if cleared screen
if (score == numBricks * 10) {
// Create bricks at level 2
createBricksAndRestart(2);
// fix for a pause bug
// so that it won't Pause After finishing the Game
score = score + 10;
// Gift the player with 1 new live
lives = lives + 1;
} else if (score == (numBricks * 20) + 10) {
// Create bricks at level 3
createBricksAndRestart(3);
// fix for a pause bug
// so that it won't Pause After finishing the Game
score = score + 10;
// Gift the player with 2 new lives
lives = lives + 2;
}
// Pause if cleared screen
// if score equals to the whole Bricks scores after 3 levels
else if (score == (numBricks * 10 * 3) + 20) {
paused = true;
}
// Bounce the ball back when it hits the top of screen
if (ball.getRect().top < 0) {
ball.reverseYVelocity();
ball.clearObstacleY(40);
soundPool.play(beep2ID, 1, 1, 0, 0, 1);
}
// If the ball hits left wall bounce
if (ball.getRect().left < 0) {
ball.reverseXVelocity();
ball.clearObstacleX(2);
soundPool.play(beep3ID, 1, 1, 0, 0, 1);
}
// If the ball hits right wall Velocity
if (ball.getRect().right > screenX) {
ball.reverseXVelocity();
ball.clearObstacleX(screenX - 57);
soundPool.play(beep3ID, 1, 1, 0, 0, 1);
}
}
// Draw the newly updated scene
public void draw() {
// Make sure our drawing surface is valid or we crash
if (ourHolder.getSurface().isValid()) {
// Lock the canvas ready to draw
canvas = ourHolder.lockCanvas();
// Draw the background color
// canvas.drawColor(getResources().getColor(R.color.deeppurple));
dest = new Rect(0, 0, getWidth(), getHeight());
// Draw bob as background with dest size
canvas.drawBitmap(bitmapBob, null, dest, paint);
// Choose the brush color for drawing
paint.setColor(Color.argb(255, 255, 255, 255));
// Draw the ball
// canvas.drawCircle(ball.getRect().centerX(), ball.getRect().centerY(), 25, paint);
canvas.drawBitmap(bitmapBall, ball.getRect().left, ball.getRect().top, null);
// Draw the paddle
//canvas.drawRect(paddle.getRect(), paint);
canvas.drawBitmap(bitmapPaddal, paddle.getRect().left, paddle.getRect().top, null);
// Change the brush color for drawing
// paint.setColor(getResources().getColor(R.color.redorange));
// Draw the bricks if visible
for (int i = 0; i < numBricks; i++) {
if (bricks[i].getVisibility()) {
// canvas.drawRect(bricks[i].getRect(), paint);
switch (level) {
case 1:
canvas.drawBitmap(bitmapBrick1, bricks[i].getRect().left, bricks[i].getRect().top, null);
break;
case 2:
canvas.drawBitmap(bitmapBrick2, bricks[i].getRect().left, bricks[i].getRect().top, null);
break;
case 3:
canvas.drawBitmap(bitmapBrick3, bricks[i].getRect().left, bricks[i].getRect().top, null);
break;
}
}
}
// Choose the brush color for drawing
paint.setColor(Color.argb(255, 255, 255, 255));
// Draw the score
paint.setTextSize(getResources().getDimension(R.dimen.text_size));
// Score Text
canvas.drawText(
"النقاط: " + score
, screenX - (densityDpi / 1.50f), screenY / 2, paint);
// Lives Text
canvas.drawText("الصحة: " + lives
, densityDpi / 5, screenY / 2, paint);
// Levels Text
canvas.drawText("المرحلة: " + level
, screenX / 2 - (densityDpi / 5), screenY / 2 + (densityDpi / 5), paint);
// Has the player cleared the screen?
if (score >= (numBricks * 10 * 3) + 20) {
paint.setColor(getResources().getColor(R.color.colorAccent));
paint.setTextSize(getResources().getDimension(R.dimen.text_size_big));
canvas.drawText("أنت كسبت!", screenX / 2 - (densityDpi / 1.90f), screenY / 2 + (densityDpi / 1), paint);
}
// Draw everything to the screen
ourHolder.unlockCanvasAndPost(canvas);
}
}
// If GameActivity is paused/stopped
// shutdown our thread.
public void pause() {
playing = false;
try {
gameThread.join();
} catch (InterruptedException e) {
Log.e("Error:", "joining thread");
}
}
// If GameActivity is started
// start our thread.
public void resume() {
playing = true;
gameThread = new Thread(this);
gameThread.start();
}
// The SurfaceView class implements onTouchListener
// So we can override this method and detect screen touches.
/* #Override
public boolean onTouchEvent(MotionEvent motionEvent) {
switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) {
// Player has touched the screen
case MotionEvent.ACTION_DOWN:
if (!(lives == 0)) {
paused = false;
}
// If touch motion > Half of the Screen
if (motionEvent.getX() > screenX / 2) {
// move paddle right
paddle.setMovementState(paddle.RIGHT);
} else {
// move paddle left
paddle.setMovementState(paddle.LEFT);
}
break;
// Player has removed finger from screen
case MotionEvent.ACTION_UP:
// paddle stopped
paddle.setMovementState(paddle.STOPPED);
break;
}
return true;
}*/
// Resize Bitmap function to Handle all the Images from resources the right size
public Bitmap getResizedBitmap(Bitmap bm, float newWidth, int newHeight) {
int width = bm.getWidth();
int height = bm.getHeight();
float scaleWidth = newWidth / width;
float scaleHeight = ((float) newHeight) / height;
// CREATE A MATRIX FOR THE MANIPULATION
Matrix matrix = new Matrix();
// RESIZE THE BIT MAP
matrix.postScale(scaleWidth, scaleHeight);
// "RECREATE" THE NEW BITMAP
Bitmap resizedBitmap = Bitmap.createBitmap(
bm, 0, 0, width, height, matrix, false);
bm.recycle();
return resizedBitmap;
}
}
And this is code for Paddle class:
import android.graphics.RectF;
public class Paddle {
// Which ways can the paddle move
public final int STOPPED = 0;
public final int LEFT = 1;
public final int RIGHT = 2;
int scrX;
// RectF is an object that holds four coordinates - just what we need
private RectF rect;
// How long and high our paddle will be
private float length;
private float height;
// X is the far left of the rectangle which forms our paddle
private float x;
// Y is the top coordinate
private float y;
// This will hold the pixels per second speedthat the paddle will move
private float paddleSpeed;
// Is the paddle moving and in which direction
private int paddleMoving = STOPPED;
private int MYscreenDPI;
// This the the constructor method
// When we create an object from this class we will pass
// in the screen width and height
public Paddle(int screenX, int screenY, int screenDPI) {
// Dynamic size based on each device DPI
length = screenDPI / 2;
height = screenDPI / 5;
MYscreenDPI = screenDPI;
scrX = screenX;
// Start paddle in roughly the sceen centre
x = screenX / 2;
y = screenY - screenDPI / 4.50f;
rect = new RectF(x, y, x + length, y + height);
// How fast is the paddle in pixels per second
paddleSpeed = 800;
}
public float getX() {
return x;
}
public void setX(float x) {
this.x = x;
}
public float getY() {
return y;
}
public void setY(float y) {
this.y = y;
}
// This is a getter method to make the rectangle that
// defines our paddle available in BreakoutView class
public RectF getRect() {
return rect;
}
public int getMovementState() {
return paddleMoving;
}
// This method will be used to change/set if the paddle is going left, right or nowhere
public void setMovementState(int state) {
paddleMoving = state;
}
// This update method will be called from update in BreakoutView
// It determines if the paddle needs to move and changes the coordinates
// contained in rect if necessary
public void update(long fps) {
if (paddleMoving == LEFT) {
// to fix Paddle going off the Screen
if (x >= -MYscreenDPI / 10)
// Decrement position
x = x - paddleSpeed / fps;
}
if (paddleMoving == RIGHT) {
// to fix Paddle going off the Screen
if (x <= scrX - length - MYscreenDPI / 14)
// Increment position
x = x + paddleSpeed / fps;
}
// Apply the New position
rect.left = x;
rect.right = x + length;
}
}
When I tried to run it application is always crashing and not working. When I try to use onTouchEvent method to control paddle it is not crashing but accelerometer is not working.
I know that I'm doing something bad. I'm trying to figure it out for like one week but I don't know how to make it working.
If you can tell me any suggestions I will be really thankful. Thank you for all responses.
--EDIT--
Here is error message from logcat when I clicked on new game in emulator:
2019-04-13 17:30:55.116 7082-7082/com.kazaky.breakout E/SensorManager: Exception dispatching input event. 2019-04-13 17:30:55.122 7082-7082/com.kazaky.breakout E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.kazaky.breakout, PID: 7082
java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.Class java.lang.Object.getClass()' on a null object reference
at com.kazaky.breakout.GameActivity.onSensorChanged(GameActivity.java:73)
at android.hardware.SystemSensorManager$SensorEventQueue.dispatchSensorEvent(SystemSensorManager.java:833)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:326)
at android.os.Looper.loop(Looper.java:160)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 2019-04-13 17:31:06.794 7082-7117/com.kazaky.breakout E/Surface: queueBuffer: error queuing buffer to SurfaceTexture, -19 2019-04-13 17:31:06.794 7082-7117/com.kazaky.breakout E/Surface: queueBuffer (handle=0xe9f16140) failed (No such device)
As suggested by the Stack Trace you are trying to access a null object, which in this case I'm guessing sensroEvent in onSensorChanged.
Add a nullability check and return if sensorEvent is null, like so:
if (sensorEvent == null) return
and write the rest of the function after the Guard Condition.

Is it possible to draw a bitmap multiple times with only 2 instances of the bitmap?

I'm trying to understand game-creation in Android. Therefore I try to program a simple TicTacToe without using buttons or layout files. Instead I want to only use bitmaps.
My Problem is that I can create the board, toggle the "X" and "O" symbol correctly, but my onDraw() only draws 2 symbols simultanously at max and I dont quite understand why or how to solve this.
public class GameScreen extends View {
List<TicTacToeSymbol> symbolList = new ArrayList<>();
float posX;
float posY;
int displayWidth;
int displayHeight;
Bitmap background;
Bitmap bitmapX;
Bitmap bitmapO;
Rect dst = new Rect();
boolean touched = false;
TicTacToeSymbol currentSymbol;
TicTacToeSymbol symbolX;
TicTacToeSymbol symbolO;
Grid grid = new Grid();
// Declaring the coordinates for the colums and rows
int ZERO_COLUMN_X = 0;
int FIRST_COLUMN_X = 480;
int SECOND_COLUMN_X = 910;
int THIRD_COLUMN_X = 1425;
(...)
int centerX = 0;
int centerY = 0;
public GameScreen(Context context) {
super(context);
try {
AssetManager assetManager = context.getAssets();
InputStream inputStream = assetManager.open("tictactoegrid.jpg");
background = BitmapFactory.decodeStream(inputStream);
inputStream = assetManager.open("X.png");
bitmapX = BitmapFactory.decodeStream(inputStream);
inputStream = assetManager.open("O.png");
bitmapO = BitmapFactory.decodeStream(inputStream);
inputStream.close();
// I create only 2 symbols, which might be the problem
symbolX = new TicTacToeSymbol(0, 0, 1);
symbolX.setBitmap(bitmapX);
symbolO = new TicTacToeSymbol(0, 0, 2);
symbolO.setBitmap(bitmapO);
setCurrentSymbol(symbolX, 1);
} catch (IOException e) {
e.printStackTrace();
}
}
#Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
Display display = this.getDisplay();
Point size = new Point();
display.getSize(size);
displayWidth = size.x;
displayHeight = size.y;
}
public void toggleCurrentSymbol() {
if (currentSymbol == symbolX) {
currentSymbol = symbolO;
} else {
currentSymbol = symbolX;
}
}
public void setCurrentSymbol(TicTacToeSymbol ticTacToeSymbol, int type) {
this.currentSymbol = ticTacToeSymbol;
if (type == 1) {
currentSymbol.setType(1);
} else
currentSymbol.setType(2);
}
public void setCoordinatesCurrentSymbol(int centerX, int centerY) {
currentSymbol.setPosX(centerX);
currentSymbol.setPosY(centerY);
}
#Override
public void onDraw(Canvas canvas) {
dst.set(0, 0, displayWidth, displayHeight - 200);
canvas.drawBitmap(background, null, dst, null);
if (touched) {
// Checking where the user has clicked
// First row
if (posX >= ZERO_COLUMN_X && posX <= FIRST_COLUMN_X
&& posY > ZERO_ROW_Y && posY < FIRST_ROW_Y) {
centerX = FIRST_CENTER_X;
centerY = FIRST_CENTER_Y;
setCoordinatesCurrentSymbol(centerX, centerY);
grid.placeSignInGrid(0, 0, currentSymbol);
toggleCurrentSymbol();
}
if (posX > FIRST_COLUMN_X && posX <= SECOND_COLUMN_X
&& posY > ZERO_ROW_Y && posY < FIRST_ROW_Y) {
centerX = SECOND_CENTER_X;
centerY = FIRST_CENTER_Y;
setCoordinatesCurrentSymbol(centerX, centerY);
grid.placeSignInGrid(1, 0, currentSymbol);
toggleCurrentSymbol();
}
(...)
}
// Go through the grid, get the symbol at the position and add it to the list of symbols
for (int i = 0; i < Grid.GRID_SIZE; i++) {
for (int j = 0; j < Grid.GRID_SIZE; j++) {
if (grid.getSymbolAtField(i, j) != null) {
if (!symbolList.contains(grid.getSymbolAtField(i, j))) {
symbolList.add(grid.getSymbolAtField(i, j));
}
}
}
}
// Draw every symbol in the list.
for (TicTacToeSymbol ttts : symbolList) {
canvas.drawBitmap(ttts.getBitmap(), ttts.getPosX(), ttts.getPosY(), null);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
touched = true;
posX = event.getX();
posY = event.getY();
invalidate();
return true;
}
return false;
}
}
I create only 2 TicTacToeSymbols, namely symbolXand symbolO. Therefore the symbolList only contains these 2 and draws only those 2.
But how can I draw the same symbol several times? Else I would have to create 9 X-Symbols including the bitmap and 9 O-Symbols to cover all grid-fields with the possible symbols. This would seem wrong / not very elegant?
So how can I draw my 2 symbols several times at the correct positions?
I've looked into several posts like this but could not derive a solution for my problem:
Draw multiple times from a single bitmap on a canvas ... this positions the bitmaps randomly, but I want my symbols on specific positions.

Show image in one half of the sphere

I would like to show image with resolution 4096x2048 (this is not a spherical image) in one half of the sphere. I use panoramagl android library to obtain panoramic view. In my activity which extends com.panoramagl.PLIView I declare:
CustomPLSpherical2Panorama cylindricalPanorama = new CustomPLSpherical2Panorama();
PLImage imageFace = new PLImage(PLUtils.getBitmap(this, R.drawable.spherical_pano), false);
cylindricalPanorama.setImage(imageFace);
setPanorama(cylindricalPanorama);
In order to don't exceed max texture size which is 1024x1024 I scale this image 2 times down.
public class CustomPLSpherical2Panorama extends PLQuadricPanoramaBase {
/**
* init methods
*/
public CustomPLSpherical2Panorama() {
super();
}
#Override
protected void initializeValues() {
super.initializeValues();
this.setPreviewDivs(PLConstants.kDefaultSphere2PreviewDivs);
this.setDivs(PLConstants.kDefaultSphere2Divs);
}
/**
* property methods
*/
#Override
public int getTilesNumber() {
return 4;
}
#Override
public void setImage(PLIImage image) {
if (image != null) {
int w = image.getWidth(), h = image.getHeight();
image = image.scale(w / 2, h / 2);
w = image.getWidth();
h = image.getHeight();
if (w >= 128 && w <= 2048 && h >= 64 && h <= 1024 && PLMath.isPowerOfTwo(w) && PLMath.isPowerOfTwo(h) && w % h == 0) {
int w2 = w >> 1, w32 = w2 >> 4;
PLIImage frontImage = PLImage.crop(image, w2 - w32, 0, w32 << 1, h);
PLIImage backImage = PLImage.joinImagesHorizontally(PLImage.crop(image, w - w32, 0, w32, h), PLImage.crop(image, 0, 0, w32, h));
PLIImage leftImage = PLImage.crop(image, 0, 0, w2, h);
PLIImage rightImage = PLImage.crop(image, w2, 0, w2, h);
this.setTexture(new PLTexture(frontImage), PLSpherical2FaceOrientation.PLSpherical2FaceOrientationFront.ordinal());
this.setTexture(new PLTexture(backImage), PLSpherical2FaceOrientation.PLSpherical2FaceOrientationBack.ordinal());
this.setTexture(new PLTexture(leftImage), PLSpherical2FaceOrientation.PLSpherical2FaceOrientationLeft.ordinal());
this.setTexture(new PLTexture(rightImage), PLSpherical2FaceOrientation.PLSpherical2FaceOrientationRight.ordinal());
}
}
}
/**
* render methods
*/
#Override
protected void internalRender(GL10 gl, PLIRenderer renderer) {
PLITexture previewTexture = this.getPreviewTextures()[0];
PLITexture[] textures = this.getTextures();
PLITexture frontTexture = textures[PLSpherical2FaceOrientation.PLSpherical2FaceOrientationFront.ordinal()];
PLITexture backTexture = textures[PLSpherical2FaceOrientation.PLSpherical2FaceOrientationBack.ordinal()];
PLITexture leftTexture = textures[PLSpherical2FaceOrientation.PLSpherical2FaceOrientationLeft.ordinal()];
PLITexture rightTexture = textures[PLSpherical2FaceOrientation.PLSpherical2FaceOrientationRight.ordinal()];
boolean frontTextureIsValid = (frontTexture != null && frontTexture.getTextureId(gl) != 0);
boolean backTextureIsValid = (backTexture != null && backTexture.getTextureId(gl) != 0);
boolean leftTextureIsValid = (leftTexture != null && leftTexture.getTextureId(gl) != 0);
boolean rightTextureIsValid = (rightTexture != null && rightTexture.getTextureId(gl) != 0);
if (frontTextureIsValid || backTextureIsValid || leftTextureIsValid || rightTextureIsValid || (previewTexture != null && previewTexture.getTextureId(gl) != 0)) {
gl.glEnable(GL10.GL_TEXTURE_2D);
GLUquadric quadratic = this.getQuadric();
float radius = PLConstants.kPanoramaRadius * 10;
int divs = this.getDivs();
int halfDivs = this.getDivs() / 2, quarterDivs = halfDivs / 2;
if (previewTexture != null) {
if (frontTextureIsValid && backTextureIsValid && leftTextureIsValid && rightTextureIsValid)
this.removePreviewTextureAtIndex(0, true);
else {
int previewDivs = this.getPreviewDivs();
gl.glBindTexture(GL10.GL_TEXTURE_2D, previewTexture.getTextureId(gl));
GLUES.gluSphere(gl, quadratic, radius, previewDivs, previewDivs);
}
}
// Front Face
if (frontTextureIsValid) {
gl.glBindTexture(GL10.GL_TEXTURE_2D, frontTexture.getTextureId(gl));
GLUES.glu3DArc(gl, quadratic, PLConstants.kPI8, -PLConstants.kPI16, false, radius, quarterDivs, quarterDivs);
}
// Back Face
if (backTextureIsValid) {
gl.glBindTexture(GL10.GL_TEXTURE_2D, backTexture.getTextureId(gl));
GLUES.glu3DArc(gl, quadratic, PLConstants.kPI8, -PLConstants.kPI16, true, radius, quarterDivs, quarterDivs);
}
// Left Face
if (leftTextureIsValid) {
gl.glBindTexture(GL10.GL_TEXTURE_2D, leftTexture.getTextureId(gl));
GLUES.gluHemisphere(gl, quadratic, false, radius, halfDivs, halfDivs);
//GLUES.gluPartialDisk(gl, quadratic, 0, PLConstants.kPI16, quarterDivs, quarterDivs, PLConstants.kPI16, PLConstants.kPI8);
}
//Right Face
if (rightTextureIsValid) {
gl.glBindTexture(GL10.GL_TEXTURE_2D, rightTexture.getTextureId(gl));
GLUES.gluHemisphere(gl, quadratic, true, radius, halfDivs, halfDivs);
}
gl.glDisable(GL10.GL_TEXTURE_2D);
}
}
}
Above code help me show my image in sphere but the problem is that the image isn't spherical so it stretches too much at the bottom and top of the sphere.
The best solution for that problem could be as black area shows at below image:
It should show from -90 to +90 degrees horizontally and from -90 to +90 degrees vertically (ideally should be -80 to +80 degrees vertically).
I tried to use:
public static void gluPartialDisk(GL10 gl, GLUquadric qobj, float innerRadius, float outerRadius, int slices, int loops, float startAngle, float sweepAngle)
but it doesn't work. It shows black screen.
To sum up the questions are:
How to show image on the sphere as black area shows on the image?
How to set min, max horizontal and vertical rotation in degrees (in user guide is atvMin, atvMax, athMin, athMax option but I couldn't find it in panoramagl source code)?
1) What about using PLCylindricalPanorama setting correct height?
2) atvMin, atvMax, athMin, athMax are in PLConstants as:
for atv:
public static final float kDefaultPitchMinRange = -90.0f;
public static final float kDefaultPitchMaxRange = 90.0f;
for ath:
public static final float kRotationMinValue = -180.0f;
public static final float kRotationMaxValue = 180.0f;

How to set-up automatic collision with just an update() function?

I've just started with Android programming using eclipse and recently came across this problem. I have a bunch of sprites assigned to an arraylist. Now, I want to make it so that collision is detected automatically between sprites but the template I'm currently using can only detect collision between the surface's borders and the moving sprites. Each sprite's position and speed is generated randomly.
How can I change the update() function in my Sprite() class to detect collision between the moving sprites themselves and at the same changing/bouncing to the opposite direction?
Here's my Sprite class template:
package com.gameproject.cai_test;
import java.util.Random;
public Sprite(GameView gameView, Bitmap bmp) {
this.width = bmp.getWidth() / BMP_COLUMNS;
this.height = bmp.getHeight() / BMP_ROWS;
this.gameView = gameView;
this.bmp = bmp;
Random rnd = new Random();
x = rnd.nextInt(gameView.getWidth() - width);
y = rnd.nextInt(gameView.getHeight() - height);
xSpeed = rnd.nextInt(MAX_SPEED * 2) - MAX_SPEED;
ySpeed = rnd.nextInt(MAX_SPEED * 2) - MAX_SPEED;
}
private void update() {
if (x >= gameView.getWidth() - width - xSpeed || x + xSpeed <= 0) {
xSpeed = -xSpeed;
}
x = x + xSpeed;
if (y >= gameView.getHeight() - height - ySpeed || y + ySpeed <= 0) {
ySpeed = -ySpeed;
}
y = y + ySpeed;
currentFrame = ++currentFrame % BMP_COLUMNS;
}
public void onDraw(Canvas canvas) {
update();
int srcX = currentFrame * width;
int srcY = getAnimationRow() * height;
Rect src = new Rect(srcX, srcY, srcX + width, srcY + height);
Rect dst = new Rect(x, y, x + width, y + height);
canvas.drawBitmap(bmp, src, dst, null);
}
private int getAnimationRow() {
double dirDouble = (Math.atan2(xSpeed, ySpeed) / (Math.PI / 2) + 2);
int direction = (int) Math.round(dirDouble) % BMP_ROWS;
return DIRECTION_TO_ANIMATION_MAP[direction];
}
//gameplay operations
//only values from 0 to 9 will be picked; each assigned its own sprite in the list
public int randomValue(){
Random rnd = new Random();
RandomValue = rnd.nextInt(10);
return RandomValue;
}
//sequence operation from addition, subtraction, multiplication, and division
public int produceSum(){
int addOne = 0;
int addTwo = 0;
Sum = addOne + addTwo;
return Sum;
}
public int produceDiff(){
int deductOne = 0;
int deductTwo = 0;
Difference = deductOne - deductTwo;
return Difference;
}
public int produceProduct(){
int multiOne = 0;
int multiTwo = 0;
Product = multiOne * multiTwo;
return Product;
}
public int produceQuotient(){
int divideOne = 0;
int divideTwo = 0;
Quotient = divideOne / divideTwo;
return Quotient;
}
//each time this returns true, the game is reset with new operation
//compares the value of the bubble picked to the random number being compared through operations
public boolean compareBubbleValue(int randomBubble, int bubbleValue){
if (randomBubble == bubbleValue){
return true;
}
return false;
}
}
As you can see, the update() method only checks the collision between the moving sprites and the borders.
Okey, so lets name your array of sprites spriteArray and loop through it twice
public Rect getBounds(){ //put this in your sprite and enemy-class.
return new Rect(x, y, x+width, y+height);
}
Public void checkCollision(){
for (int i = 0; i<spriteArray.size(); i++){
Rect mySprite = spriteArray.get(i).getBounds(); //create rect for every sprite in array
for (int j = 0; j<spriteArray.size(); i++){
Rect myOtherSprite = spriteArray.get(i).getBounds();
if(mySprite.intersect(myOtherSprite)){ //check if they touch
//Todo code here
}
}
}
}
then you just put this method in your update-method.
Here's the coding for the GameView class (pardon the mess, it's a jumble of codes and comments):
package com.gameproject.cai_test;
public class GameView extends SurfaceView {
private Bitmap bmp;
private Bitmap background;
private Bitmap backgroundImage;
private Bitmap pop;
private SurfaceHolder holder;
private GameLoopThread gameLoopThread;
private List<Sprite> sprites = new ArrayList<Sprite>();
private List<TempSprite> temps = new ArrayList<TempSprite>();
private int[] bubbleValue = {0,1,2,3,4,5,6,7,8,9,10};
private long lastClick;
private SpriteObject timer;
private SpriteObject morebanner;
private SpriteObject formulaBox;
private SpriteObject levelbanner1;
private SurfaceHolder surfaceHolder;
public GameView(Context context) {
super(context);
gameLoopThread = new GameLoopThread(this);
timer = new SpriteObject (BitmapFactory.decodeResource(getResources(), R.drawable.hourglass), 1200, 100);
morebanner = new SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.morebanner), 650, 300);
formulaBox = new SpriteObject(BitmapFactory.decodeResource(getResources(), R.drawable.formulabox), 650, 600);
background = BitmapFactory.decodeResource(getResources(), R.drawable.background);
backgroundImage = BitmapFactory.decodeResource(getResources(), R.drawable.background);
pop = BitmapFactory.decodeResource(getResources(), R.drawable.pop);
final Toast toast1 = Toast.makeText(context, "LEVEL 1 start", Toast.LENGTH_LONG);
holder = getHolder();
holder.addCallback(new Callback() {
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
//setSurfaceSize(getWidth(), getHeight());
toast1.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast1.show();
createSprites();
gameLoopThread.setRunning(true);
gameLoopThread.start();
//banner();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
}
private void createSprites() {
sprites.add(createSprite(R.drawable.bubble1));
sprites.add(createSprite(R.drawable.bubble2));
sprites.add(createSprite(R.drawable.bubble3));
sprites.add(createSprite(R.drawable.bubble4));
sprites.add(createSprite(R.drawable.bubble5));
sprites.add(createSprite(R.drawable.bubble6));
sprites.add(createSprite(R.drawable.bubble7));
sprites.add(createSprite(R.drawable.bubble8));
sprites.add(createSprite(R.drawable.bubble9));
sprites.add(createSprite(R.drawable.bubble10));
for (int i = 0; i <= 10; i++){
bubbleValue[i] = sprites.indexOf(i);
}
}
private Sprite createSprite(int resource) {
Bitmap bmp = BitmapFactory.decodeResource(getResources(), resource);
return new Sprite(this, bmp);
}
public void setSurfaceSize(int width, int height)
{
synchronized (surfaceHolder)
{
int canvasWidth = width;
int canvasHeight = height;
backgroundImage = Bitmap.createScaledBitmap(backgroundImage, width, height, true);
}
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.WHITE);
//levelbanner1.draw(canvas);//causes error when applied;for reference only
for (int i = temps.size() - 1; i >= 0; i--) {
temps.get(i).onDraw(canvas);
}
for (Sprite sprite : sprites) {
timer.draw(canvas);
//formulaBox.draw(canvas);
sprite.onDraw(canvas);
}
if (sprites.size() == 0){
morebanner.draw(canvas);
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (System.currentTimeMillis() - lastClick > 300) {
lastClick = System.currentTimeMillis();
float x = event.getX();
float y = event.getY();
synchronized (getHolder()) {
for (int i = sprites.size() - 1; i >= 0; i--) {
Sprite sprite = sprites.get(i);
if (sprite.isCollition(x, y)) {
sprites.remove(sprite);
temps.add(new TempSprite(temps, this, x, y, pop));
break;
}
}
}
}
return true;
}
public void update(){
//for possible check of collision bet. sprites
//
}
}
I've tried assigning a Rect for the sprites here and checking collision on the bottom update() function but result gets awry and produces a runtime error. Probably would be better if its automated in the Sprite class update() function, just as it does for border collision.
If you want to have nice and proper collisions between your sprites, maybe looking at a physics engine like http://www.jbox2d.org/ would help.
It will handle a lot of the complex specific cases for you (tunnelling, time of impact, broadphase for early discard...)

Android canvas.translate()

I am using canvas.translate to change the coodinates of my canvas so that the viewport changes
my code :
public class draw extends View {
View v;
Paint paint;
int width;
int height;
int view_x;
int view_y;
static final int MAX_GAME_SPEED = 25;
static int fps;
public draw(Context context) {
super(context);
// tb.loadimg();
Thread myThread = new Thread(new UpdateThread());
myThread.start();
}
#Override
protected void onDraw(Canvas c) {
super.onDraw(c);
paint = new Paint(); // Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
// get screen size
WindowManager wm = (WindowManager) this.getContext().getSystemService(
Context.WINDOW_SERVICE);
Display display = wm.getDefaultDisplay();
width = display.getWidth(); // deprecated
height = display.getHeight(); // deprecated
// make the entire canvas white
paint.setColor(Color.WHITE);
c.drawPaint(paint);
if (tb.dirt != null && tb.stone != null && tb.sand != null
&& tb.gold != null && tb.iron != null && tb.coal != null
&& tb.kies != null && tb.diamond != null && tb.redstone != null
&& tb.lava != null && tb.azur != null && tb.water != null) {
c.drawBitmap(tb.dirt, 0, 0, paint);
c.drawBitmap(tb.stone, 0, 50, paint);
c.drawBitmap(tb.sand, 0, 100, paint);
c.drawBitmap(tb.gold, 0, 150, paint);
c.drawBitmap(tb.iron, 50, 0, paint);
c.drawBitmap(tb.coal, 50, 50, paint);
c.drawBitmap(tb.kies, 50, 100, paint);
c.drawBitmap(tb.diamond, 50, 150, paint);
c.drawBitmap(tb.redstone, 100, 0, paint);
c.drawBitmap(tb.lava, 100, 50, paint);
c.drawBitmap(tb.azur, 100, 100, paint);
c.drawBitmap(tb.water, 100, 150, paint);
}
if (tb.map == null) {
}
view_x = 100;
view_y = 100;
c.translate(0, -4);
}
public Handler updateHandler = new Handler() {
/** Gets called on every message that is received */
// #Override
public void handleMessage(Message msg) {
invalidate();
super.handleMessage(msg);
}
};
public class UpdateThread implements Runnable {
#Override
public void run() {
while (true) { // Game Loop
long startTime = System.currentTimeMillis();
draw.this.updateHandler.sendEmptyMessage(0); // veranlassen,
// dass paint()
// erneut
// aufgerufen
// werden soll
// for (int i=0; i<999999; i++); //Bremse
Thread.yield();
long executionTime = System.currentTimeMillis() - startTime;
if (executionTime < MAX_GAME_SPEED) {
try {
Thread.sleep(MAX_GAME_SPEED - (int) executionTime);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
fps = 1000 / MAX_GAME_SPEED;
} else
fps = (int) (1000 / executionTime);
}
}
}
}
but simply nothing happens
I have seen many online examples but I just don't get throug my problem -.-
I think you have to call translate() first, then draw your objects
I think if you do translate(0,-4),
now your c coodinates is out of the screeen

Categories

Resources