Hi all,
Like everyone else I'm doing a game to learn a bit about the android
platform. I've now reached a point where I need to optimize my draw
function and I'm trying to figure out the pros and cons of different
paths to take. I'm pretty new to graphics (but not programming) so my
questions might seems stupid, and my native language isn't English but
please bear with me. I'll be trying to explain as well as I can and
hopefully giving a bite more info than needed rather than less.
It's simple 2D graphics we're talking about here. Doing frame
animations from a sprite sheet with sequences of movement for
different creatures, so basically I'm painting a portion of the sprite
sheet to the canvas, a little moved each time to make it look it's
walking/driving/running. The game plan is larger than the screen so
there's a view port Rectangle I use to draw what's on screen. I'm
doing this threaded pretty much like the lunar lander example. My
current draw function does:
1. Update physics, set boolean to updated if anything happened
2. Draw global BitMap object containing last frame on the canvas if
nothing has happened, otherwise:
3. Draw the part of the background currently visible, this draws over
everything old
4. Loop through my objects, if any part of them is inside the view
port draw them and let the canvas sort out what's needed and what's
not
5. Store draw the update on the static background
Something like this:
private Bitmap bg = ... the large background image
private Bitmap sprites = ... the animations
private Bitmap screenBM = .. the static image
private Canvas screenC = new Canvas (screenBM);
private boolean noUp = false;
private MyClass creatures = new MyClass[10];
@Override
public void run() {
Canvas c;
while (_run) {
c = null;
try
{
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
updatePhysics (SystemClock.uptimeMillis (), c);
if (noUp)
c.drawBitmap(cp, 0, 0, null); // redraw the old
else
draw (c);
}
}
finally
{
if (c != null)
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
public void draw (Canvas c)
{
screenC.drawBitmap (bgImage, viewPort, mapScreen, null);
Rect trans = new Rect (); // used to transform to the current
view port
for (int i = 0; i creatures.length; i++)
{
if (creatures[i] != null !creatures[i].dead)
{
trans.left = creatures[i].pos.left -
viewPort.left;
trans.right = creatures[i].pos.right -
viewPort.left;
trans.top = creatures[i].pos.top - viewPort.top;
trans.bottom = creatures[i].pos.bottom -
viewPort.top;
if ( trans.left mapScreen.right
trans.right mapScreen.left
trans.top mapScreen.bottom
trans.bottom mapScreen.top)
{
screenC.drawBitmap(creatureAnimBitmap,
frameCoords, trans, null);
}
}
}
co.drawBitmap(screenBM, 0, 0, null);
}
I'm sure this isn't a very effective method for handling this,
especially not when the game physics is demanding and one wants a nice
frame rate. What would be the more effective way to do this? I've
tried figuring out how clipRect (float left, float top, float
right, float bottom, Region.Op op) works but I haven't been very
successful at that, not many examples out there explaining what it
does exactly.
My guess would be that I should keep track of all movement of my
objects and have an int/float based array (to avoid the dreaded GC)
with a rectangle covering the previous position and the current and
just redraw that part.
Or am I looking in the wrong direction? Is
Canvas.save/translate/restore the way to go if I want it to be
efficient? Or is it something completely different I should do?
To sum up my rambling:
1. I understand Rects are inefficient and expensive, is that so?
2. What is the best way to handle things that would completely or
partially be drawn outside the view port?
3. Is clipping, translate or just drawing pos based most efficient?
4. And since you've read through all this a little bonus question: Do
people tend to have two threads, one for synchronized drawing and only
doing that and one for physics or is one large thread doing both the
way to go?
Sorry for the bandwidth, the only thing missing is a 5