Cocos2dx GL SurfaceView截屏 应用层实现
环境:使用Cocosdx进行游戏开发,需要Android实现截屏分享功能,但JNI没有提供截图路径,所以需要Android应用层实现截屏功能
1.使用Activity的截屏方法
public class ScreenShot {
public static Bitmap takeScreenShot(Activity activity) {
// View是你需要截图的View
View view = activity.getWindow().getDecorView();
view.setDrawingCacheEnabled(true);
view.buildDrawingCache();
Bitmap b1 = view.getDrawingCache();
// 获取状态栏高度
Rect frame = new Rect();
activity.getWindow().getDecorView().getWindowVisibleDisplayFrame(frame);
int statusBarHeight = frame.top;
// 获取屏幕长和高
int width = activity.getWindowManager().getDefaultDisplay().getWidth();
int height = activity.getWindowManager().getDefaultDisplay()
.getHeight();
// 去掉标题栏
Bitmap b = Bitmap.createBitmap(b1, 0, statusBarHeight, width, height
- statusBarHeight);
view.destroyDrawingCache();
return b;
}
private static void savePic(Bitmap b, File filePath) {
FileOutputStream fos = null;
try {
fos = new FileOutputStream(filePath);
if (null != fos) {
b.compress(Bitmap.CompressFormat.PNG, 100, fos);
fos.flush();
fos.close();
}
} catch (FileNotFoundException e) {
// e.printStackTrace();
} catch (IOException e) {
// e.printStackTrace();
}
}
public static void shoot(Activity a, File filePath) {
if (filePath == null) {
return;
}
if (!filePath.getParentFile().exists()) {
filePath.getParentFile().mkdirs();
}
ScreenShot.savePic(ScreenShot.takeScreenShot(a), filePath);
}
}
问题:截屏为黑屏。
原因:因为Activity和SurfaceView的页面绘制机制是不用的
2.使用surfaceView的截屏方法
Bitmap bitmap = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
draw(canvas);
问题:截屏为白屏。
原因:因为cocos2dx项目,绘图是由CPP代码执行的,在Cocos2dxGLSurfaceView上绘图,所以不能使用一般SurfaceView的截图方法。
3.应用层。使用org.cocos2dx.lib中的Cocos2dxRenderer类中的GL10转为Bitmap
新建截屏类ShotScreenByGL10 ,将GL10转换为Bitmap
public class ShotScreenByGL10 {
private static int width;
private static int height;
public static GL10 gl;
public static void setWidth(int width) {
ShotScreenByGL10.width = width;
}
public static void setHeight(int height) {
ShotScreenByGL10.height = height;
}
public static void setGl(GL10 gl) {
ShotScreenByGL10.gl = gl;
}
public static Bitmap getShotScreenBitmap() {
ByteBuffer buffer = ByteBuffer.allocateDirect(width * height * 4);
gl.glReadPixels(0, 0, width, height, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, buffer);
// 上下逆なので、上下反転
byte[] tmp1 = new byte[width * 4];
byte[] tmp2 = new byte[width * 4];
int h = (int) height / 2;
for (int y = 0; y < h; y++) {
buffer.position(y * width * 4);
buffer.get(tmp1, 0, tmp1.length);
buffer.position((height - 1 - y) * width * 4);
buffer.get(tmp2, 0, tmp2.length);
buffer.position((height - 1 - y) * width * 4);
buffer.put(tmp1);
buffer.position(y * width * 4);
buffer.put(tmp2);
}
buffer.position(0);
tmp1 = tmp2 = null;
// Bitmapの作成
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
bitmap.copyPixelsFromBuffer(buffer);
// 後片付け
buffer = null;
System.gc();
return bitmap;
}
}
ShotScreenByGL10.setGl(gl);
即对底层每一帧绘画的最新GL10进行保存,以便需要截屏时,将GL10转换成Bitmap
这样就能随时获取到最新的绘画GL10,然后将其转化为Bitmap,从而获取到截屏图片。
成功!!!
4.JNI层。在JNI层调用cocos2dx的截屏功能,将屏幕截取并保存到路径Path中,再将Path传递给JAVA应用层代码,最后在JAVA应用层根据Path获取图片,实现截屏分享功能。
但这样需要JNI那边进行截好图,供应用层调用
一般实现方法。