Reputation: 421
I am trying to make a very simple game. The user has to try to catch an apple using a basket moved by his finger. Everything seems to work pretty well, but I have a problem: I want to draw a background for the app. But using an image as backgorund makes the app extremely slow and causes a lot of lag. If I use White Background I have no problems.
Can somebody tell me what I am doing wrong?
I think it is because I draw the background everytime the app updates, but I don't know any way to change this.
Maybe my code is a bit confusional, I am still learning.
Thanks for the help!
package com.cris9696.mela;
import java.util.Random;
import com.cris9696.mela.R;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.Paint.Align;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
public class Game extends Activity implements OnTouchListener {
ClasseCanvas View;
float xApple, yApple, xBasket, yBasket;
Bitmap Apple, Basket, BackG;
Random rnd = new Random();
int win = 0, score = 0, level = 1;
int record = 0;
Typeface Font;
Paint TextP = new Paint();
Rect dest;
Paint paint;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Font = Typeface.createFromAsset(getAssets(), "TF2.ttf");
View = new ClasseCanvas(this);
View.setOnTouchListener(this);
TextP.setColor(Color.RED);
TextP.setTextSize(50);
TextP.setTypeface(Font);
xApple = yApple = xBasket = yBasket = 0;
xApple = rnd.nextInt(600);
Apple = BitmapFactory.decodeResource(getResources(), R.drawable.apple);
BackG = BitmapFactory
.decodeResource(getResources(), R.drawable.bg);
Basket = BitmapFactory.decodeResource(getResources(),
R.drawable.basket);
setContentView(View);
}
// /////////////////////////////////////////////////////////////////////////////
@Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
xBasket = event.getX();
yBasket = event.getY();
/*
* switch (event.getAction()) { // ci dice cosa succede
*
* case MotionEvent.ACTION_DOWN:
*
* case MotionEvent.ACTION_UP:
*
* break; }
*/
return true;
}
// ///////////////////////////////////////////////////////////////////////////
@Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
View.pause();
}
// /////////////////////////////////////////////////////////////////////////////
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
View.resume();
}
// ///////////////////////////////////////////////////////////
public class ClasseCanvas extends SurfaceView implements Runnable {
SurfaceHolder Holder;
Thread thread = null;
boolean isRunning = true;
public ClasseCanvas(Context context) {
super(context);
Holder = getHolder();
// TODO Auto-generated constructor stub
}
@Override
public void run() {
// TODO Auto-generated method stub
while (isRunning) {
if (!Holder.getSurface().isValid())
continue;
Canvas canvas = Holder.lockCanvas();
dest = new Rect(0, 0, getWidth(), getHeight());
paint = new Paint();
paint.setFilterBitmap(true);
canvas.drawBitmap(BackG, null, dest, paint);
TextP.setColor(Color.RED);
canvas.drawText(Integer.toString(score), 56, 56, TextP);
TextP.setColor(Color.BLACK);
canvas.drawText("Level " + Integer.toString(level), 115,
56, TextP);
if (xBasket != 0 && yBasket != 0) {
canvas.drawBitmap(Basket, xBasket - Basket.getWidth() / 2,
yBasket - Basket.getHeight() / 2, null);
}
canvas.drawBitmap(Apple, xApple, yApple, null);
if (yApple < canvas.getHeight())
if (score >= 0)
yApple += 5 * level;
else
yApple += 5;
else {
yApple = 0;
score--;
xApple = rnd.nextInt(canvas.getWidth() - Apple.getWidth());
}
if (score > record)
record = score;
if (score == 10) {
level++;
score = 0;
}
if ((xApple >= xBasket - (Basket.getWidth() / 2)
&& xApple + (Apple.getWidth()) <= xBasket
+ (Basket.getWidth() / 2) && yApple >= yBasket && yApple <= yBasket
+ Basket.getHeight())
|| (xApple >= xBasket - (Basket.getWidth() / 2)
&& xApple <= xBasket + (Basket.getWidth() / 2)
&& yApple >= yBasket && yApple <= yBasket
+ Basket.getHeight())
|| (xApple + (Apple.getWidth()) >= xBasket
- (Basket.getWidth() / 2)
&& xApple + (Apple.getWidth()) <= xBasket
+ (Basket.getWidth() / 2)
&& yApple >= yBasket && yApple <= yBasket
+ Basket.getHeight())) {
win = 1;
xApple = rnd.nextInt(canvas.getWidth());
yApple = 0;
score++;
}
Holder.unlockCanvasAndPost(canvas);
}
}
public void pause() {
isRunning = false;
while (true) {
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
break;
}
thread = null;
// TODO Auto-generated method stub
}
public void resume() {
// TODO Auto-generated method stub
isRunning = true;
thread = new Thread(this);
thread.start();
}
}
}
Upvotes: 2
Views: 1145
Reputation: 1459
Dont draw the background image in the onDraw method of SurfaceView. Each time the surfaceView changes, it redraws that entire bitmap.
Your best bet is to add your SurfaceView into a LinearLayout then set the LinearLayout as your ContentView in the onCreate method. Set the background of the linearLayout to R.drawable.bg
so that way its only drawn once.
edit
So your xml file you wrap the SurfaceView in a linear layout and set the bg of the linearlayout. The problem is that you are not using this layout in your onCreate method.
in your XMl, change <SurfaceView
to <com.cris9696.mela.game.ClasseCanvas
. Then in your onCreate method you could do the following:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); // the XML layout you created.
View = (ClasseCanvas) findViewById(R.id.View); // the ClasseCanvas view in your XML file.
View.setOnTouchListener(this);
Font = Typeface.createFromAsset(getAssets(), "TF2.ttf");
TextP.setColor(Color.RED);
TextP.setTextSize(50);
TextP.setTypeface(Font);
xApple = yApple = xBasket = yBasket = 0;
xApple = rnd.nextInt(600);
Apple = BitmapFactory.decodeResource(getResources(), R.drawable.apple);
BackG = BitmapFactory.decodeResource(getResources(), R.drawable.bg);
Basket = BitmapFactory.decodeResource(getResources(),R.drawable.basket);
}
Upvotes: 1
Reputation: 16537
Seems like your application is fillrate - bound. Have you tried to turn off filtering and antialiasing for the background? Also, try to run the app with the profiler and look for drawing background. Compare the time CPU spends on drawing the background to the rest of your game. If it's too high, it means that your device cannot transfer pixels fast enough and you should consider turning filters off, at least for drawing the background.
Upvotes: 0