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;
- }
engine.setDecodeResource(true);
这句,一定要加上,不然会报找不到bitmap的错误
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() 方法改写