我正在从这本书中学习Android游戏编程 - 开始Android游戏。我无法理解AndroidFastRenderView
类run()
方法中的代码。
Canvas canvas = holder.lockCanvas();
canvas.getClipBounds(dst);
canvas.drawBitmap(frameBuffer, null, dst, null);
holder.unlockCanvasAndPost(canvas);
代码如何:
canvas.drawBitmap(frameBuffer, null, dst, null);
绘制位图?我理解drawBitmap()
类中的AndroidGraphics
方法是如何工作的(如下所示)。我不明白的是AndroidFastRenderView
中的画布如何能够在AndroidGraphics
中绘制使用Canvas绘制的位图?
AndroidGame
类的代码:
public abstract class AndroidGame extends Activity implements Game {
AndroidFastRenderView renderView;
Graphics graphics;
Audio audio;
Input input;
FileIO fileIO;
Screen screen;
WakeLock wakeLock;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
boolean isLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
int frameBufferWidth = isLandscape ? 480 : 320;
int frameBufferHeight = isLandscape ? 320 : 480;
Bitmap frameBuffer = Bitmap.createBitmap(frameBufferWidth,
frameBufferHeight, Config.RGB_565);
float scaleX = (float) frameBufferWidth
/ getWindowManager().getDefaultDisplay().getWidth();
float scaleY = (float) frameBufferHeight
/ getWindowManager().getDefaultDisplay().getHeight();
renderView = new AndroidFastRenderView(this, frameBuffer);
graphics = new AndroidGraphics(getAssets(), frameBuffer);
fileIO = new AndroidFileIO(this);
audio = new AndroidAudio(this);
input = new AndroidInput(this, renderView, scaleX, scaleY);
screen = getStartScreen();
setContentView(renderView);
PowerManager powerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK, "GLGame");
}
@Override
public void onResume() {
super.onResume();
wakeLock.acquire();
screen.resume();
renderView.resume();
}
@Override
public void onPause() {
super.onPause();
wakeLock.release();
renderView.pause();
screen.pause();
if (isFinishing())
screen.dispose();
}
public Input getInput() {
return input;
}
public FileIO getFileIO() {
return fileIO;
}
public Graphics getGraphics() {
return graphics;
}
public Audio getAudio() {
return audio;
}
public void setScreen(Screen screen) {
if (screen == null)
throw new IllegalArgumentException("Screen must not be null");
this.screen.pause();
this.screen.dispose();
screen.resume();
screen.update(0);
this.screen = screen;
}
public Screen getCurrentScreen() {
return screen;
}
}
AndrodFastRenderView
的代码:
public class AndroidFastRenderView extends SurfaceView implements Runnable{
AndroidGame game;
Bitmap frameBuffer;
Thread renderThread = null;
SurfaceHolder holder;
private volatile boolean running = false;
public AndroidFastRenderView(AndroidGame game, Bitmap frameBuffer) {
super(game);
this.game = game;
this.holder = getHolder();
this.frameBuffer = frameBuffer;
}
public void resume() {
running = true;
renderThread = new Thread(this);
renderThread.start();
}
@Override
public void run() {
Log.d("ANDROIDFASTRENDERVIEW", "CREATING NEW THREAD");
Rect dst = new Rect();
long startTime = System.nanoTime();
while(running) {
if (!holder.getSurface().isValid()) {
continue;
}
long deltaTime = startTime - System.nanoTime();
startTime = System.nanoTime();
game.getCurrentScreen().update(deltaTime);
game.getCurrentScreen().present(deltaTime);
Canvas canvas = holder.lockCanvas();
canvas.getClipBounds(dst);
canvas.drawBitmap(frameBuffer, null, dst, null);
holder.unlockCanvasAndPost(canvas);
}
}
}
AndroidGraphics
的代码:
public class AndroidGraphics implements Graphics {
AssetManager assets;
Bitmap frameBuffer;
Canvas canvas;
Paint paint;
Rect srcRect = new Rect();
Rect dstRect = new Rect();
public AndroidGraphics(AssetManager assets, Bitmap frameBuffer) {
this.assets = assets;
this.frameBuffer = frameBuffer;
canvas = new Canvas(frameBuffer);
this.paint = new Paint();
}
@Override
public Pixmap newPixmap(String fileName, Pixmapformat format) {
Bitmap.Config config = null;
if (format == Pixmapformat.ARGB4444) {
config = Bitmap.Config.ARGB_4444;
} else if(format == Pixmapformat.ARGB8888) {
config = Bitmap.Config.ARGB_8888;
} else if(format == Pixmapformat.RGB565) {
config = Bitmap.Config.RGB_565;
}
BitmapFactory.Options options = new BitmapFactory.Options();
options.inPreferredConfig = config;
InputStream in = null;
Bitmap bitmap = null;
try {
in = assets.open(fileName);
bitmap = BitmapFactory.decodeStream(in);
if (bitmap == null)
throw new RuntimeException("Couldn't load bitmap from asset '" + fileName + "'");
} catch (IOException e) {
throw new RuntimeException("Couldn't load bitmap from asset '" + fileName + "'");
} finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
}
}
}
if (bitmap.getConfig() == Bitmap.Config.RGB_565) {
format = Pixmapformat.RGB565;
}
else if (bitmap.getConfig() == Bitmap.Config.ARGB_4444) {
format = Pixmapformat.ARGB4444;
}
else {
format = Pixmapformat.ARGB8888;
}
return new AndroidPixmap(bitmap, format);
}
@Override
public void drawPixmap(Pixmap pixmap, int x, int y, int scrX, int srcY, int srcWidth, int srcHeight) {
srcRect.top = srcY;
srcRect.left = scrX;
srcRect.right = x + srcWidth -1;
srcRect.bottom = y + srcHeight -1;
dstRect.left = x;
dstRect.top = y;
dstRect.right = x + srcWidth -1;
dstRect.bottom = y + srcHeight -1;
canvas.drawBitmap(((AndroidPixmap)(pixmap)).bitmap, srcRect, dstRect, null);
}
@Override
public void drawPixmap(Pixmap pixmap, int x, int y) {
canvas.drawBitmap(((AndroidPixmap)(pixmap)).bitmap, x, y, null);
}
}