androidandengine 是一款开源的2d游戏引擎,功能还是强大的,但是用它写游戏还是有诸多不足之处。其中一个就是如题 资源的加密问题。对于一个公司或者个人来说,资源的保护非常的总要的。看来微云有,u3d有。为什么我的andengine 就没有。经过一段时间对andengine的架构解剖。嘿嘿。屌丝版加密就出来了。。下面我具体道来。
我用的是master 版的andengine Z这个是前提。
1)在Engine.java 中添加如下代码
//是否解码
private boolean isDecodeResource = false;
public boolean isDecodeResource() {
return isDecodeResource;
}
public void setDecodeResource(boolean isDecodeResource) {
this.isDecodeResource = isDecodeResource;
}
2)在IGameInterface.java 中添加一个解码的方法.你 游戏的activity 必须实现它。
public interface IGameInterface {
// ===========================================================
// Final Fields
// ===========================================================
// ===========================================================
// Methods
// ===========================================================
public Engine onLoadEngine();
public void onLoadResources();
public void onUnloadResources();
public Scene onLoadScene();
public void onLoadComplete();
public void onPauseGame();
public void onResumeGame();
//解码方法
public InputStream decodeResource(InputStream in);
}
3)改写AssetBitmapTextureAtlasSource.java 中的构造方法public AssetBitmapTextureAtlasSource(final Context pContext, final String pAssetPath, final int pTexturePositionX, final int pTexturePositionY) 和 public Bitmap onLoadBitmap(final Config pBitmapConfig) 这两方法
public AssetBitmapTextureAtlasSource(final Context pContext, final String pAssetPath, final int pTexturePositionX, final int pTexturePositionY) {
super(pTexturePositionX, pTexturePositionY);
this.mContext = pContext;
this.mAssetPath = pAssetPath;
final BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
decodeOptions.inJustDecodeBounds = true;
InputStream in = null;
try {
in = pContext.getAssets().open(pAssetPath);
final BaseGameActivity context = (BaseGameActivity)this.mContext;
if(context.getEngine().isDecodeResource()){
in = context.decodeResource(in);
}
BitmapFactory.decodeStream(in, null, decodeOptions);
} catch (final IOException e) {
Debug.e("Failed loading Bitmap in AssetBitmapTextureAtlasSource. AssetPath: " + pAssetPath, e);
} finally {
StreamUtils.close(in);
}
this.mWidth = decodeOptions.outWidth;
this.mHeight = decodeOptions.outHeight;
}
@Override
public Bitmap onLoadBitmap(final Config pBitmapConfig) {
InputStream in = null;
try {
final BitmapFactory.Options decodeOptions = new BitmapFactory.Options();
decodeOptions.inPreferredConfig = pBitmapConfig;
in = this.mContext.getAssets().open(this.mAssetPath);
final BaseGameActivity context = (BaseGameActivity)this.mContext;
if(context.getEngine().isDecodeResource()){
in = context.decodeResource(in);
}
return BitmapFactory.decodeStream(in, null, decodeOptions);
} catch (final IOException e) {
Debug.e("Failed loading Bitmap in " + this.getClass().getSimpleName() + ". AssetPath: " + this.mAssetPath, e);
return null;
} finally {
StreamUtils.close(in);
}
}
为什么在这个类中加入呢。
1.构造方法中要知道图片的宽和高。
2.onLoadBitmap 被BitmapTextureAtlas 中的writeTextureToHardware(final GL10 pGL) 方法调用加入到底层opengl es 中去。所以在被生产为Bitmap 之前。我们把他/它给解码咯。。以便引擎调用。
4)生成新的jar 包
如果你保存你的android master 版的项目。在bin文件夹里会生成一个jar包。如果不放心是否是新的包,可以删除bin文件夹下的jar包。反正它会自动生成一个新的jar ^ ^ !
5)编码自己的资源文件
自己写个Java app 程序就搞定
public static void encrImg(File src, File dest) throws Exception {
ImageInputStream fis = new FileImageInputStream(src);
ImageOutputStream fos = new FileImageOutputStream(dest);
int read;
while ((read = fis.read()) > -1) {
fos.write(read ^ XOR_CONST);
}
fos.flush();
fos.close();
fis.close();
}
public static final int XOR_CONST = 0X99; //密钥
public static void main(String[] args) {
// encrImg("E:\\项目\\TowerDefense\\图片\\人物\\3d图\\peasant1.png", "E:\\项目\\TowerDefense\\图片\\人物\\3d图\\peasant1c.png");
// encrImg("E:\\项目\\TowerDefense\\图片\\人物\\3d图\\peasant1c.png", "E:\\项目\\TowerDefense\\图片\\人物\\3d图\\peasant12.png");
}
可参考这篇文章 :Android简单加密保护自有图片资源
6)游戏中解码
@Override
public InputStream decodeResource(InputStream in){
List<Byte> list = new ArrayList<Byte>();
int read;
byte[] arr = null;
try {
while ((read = in.read()) > -1) {
read = read ^ XOR_CONST;
list.add((byte) read);
}
arr = new byte[list.size()];
int i = 0;
for (Byte item : list) {
arr[i++] = item;
}
} catch (Exception e) {
// TODO: handle exception
}
InputStream iis = new ByteArrayInputStream(arr);
return iis;
}
主 activity 中重写 decodeResource(InputStream in) 和 onLoadEngine() 中设置可以编码
@Override
public Engine onLoadEngine() {
instance = this;
Engine engine = AndEnviroment.createEngine(ScreenOrientation.LANDSCAPE,
true, true);
// Attempt to set up multitouch support
try {
if (MultiTouch.isSupported(this)) {
engine.setTouchController(new MultiTouchController());
}
} catch (final MultiTouchException e) {
}
engine.setDecodeResource(true);
return engine;
}
onLoadResources()方法中还是那样 直接用就可以了 是不是非常有用呢!
BitmapTextureAtlas tex = new BitmapTextureAtlas(pTextureWidth,
pTextureHeight, TextureOptions.NEAREST_PREMULTIPLYALPHA);
TextureRegion texReg = BitmapTextureAtlasTextureRegionFactory
.createFromAsset(tex, AndEnviroment.getInstance().getContext(),
pName, 0, 0);
AndEnviroment.getInstance().getEngine().getTextureManager()
.loadTexture(tex);
以上的解码方式适合放在assets 文件下的图片资源。
要修改其他加载方式的请看下图 大同小异啦。。
1.res 目录下的
类ResourceBitmaXXXXXXXSource.java FileBitmapXXXXXSource.java 中的 onLoadBitmap 方法改写
2.texturepacker 扩展
TexturePackParser.java 中 parsetexture 方法中onGetInputStream() 方法改写