tangdeqing / loon-simple

Automatically exported from code.google.com/p/loon-simple
0 stars 0 forks source link

关于图片的outofmemory #21

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
对于手机开发没什么经验。感觉android的内存很吃紧啊?
鹏凌兄可否介绍些图片的使用经验?
我先是仿照你的连连看的例子,建了一个Images的单例类,在��
�造函数中使用了getCacheSubImage将一个55k的jpg分解为一个LImage的
数组。
在screen中我需要同时出现几十张分解后的可以拖动的LImage,��
�是通过LPicture的loadimage封装,但是只是new了二十个不到的LPict
ure就outofmemory了。
请问我除了修改游戏设计和缩小游戏图片(55k的jpg还有缩小��
�空间吗外),有什么其他优化的办法吗?而且,按理说LPictur
e只是封装引用LImage的话,应该不会额外分配太多内存吧?…�
��恳请鹏凌兄再次赐教!谢谢

Original issue reported on code.google.com by sunny...@gmail.com on 17 Oct 2010 at 2:39

GoogleCodeExporter commented 8 years ago
sunnylqm兄您好,以目前的Android系统来讲,分配给独立APK的资��
�普遍不足,至多只能容纳16MB内存资源,8MB图像资源(以实际
内存为主,虚拟的Android环境会更低一些,刚启动时平均只有1
MB-6MB)。

另外,这个问题很久以前国外的技术站有人讨论过(http://www.
javagaming.org/index.php/topic,22166.0.html)。

不过,大家得出的方案除了使用RGB565格式(LGame默认为此),
缩小图片,以及释放不用的图片资源外,并没有什么特别简��
�的选择。因此,在Android系统中,如果要实现复杂的图形绘制
,确实需要进行一些手动优化。

具体到LGame中,当您getCacheSubImage之后,由于内存中已经有了��
�存的图形,所以原有的LImage已经没用,不需要的话务必dispose
了它。

而对于复杂的游戏显示,建议不要使用LGame组件中的LPicture,�
��应采用精灵中的Picture。原因在于,LGame中的LPicture虽然使用�
��单,但是其简便性是以较高的资源损耗为代价的(看一下源
码,您会发现它的父类其实挺庞大),基本上建立一个LPicture
的资源约等于两个Picture。

而假如图像太多的话(同时显示的小图超过40张以上),个人
建议直接在draw中利用drawBitmap或者drawImage切分显示指定图像到
指定区域(具体实现可参照JavaSE或JavaME游戏的切图显示方式��
�LGame中能够彻底照搬),而不要使用实际的分图,这样也可��
�节省不小的图像空间(当然,代价是降低显示速度)。

Original comment by loontest@gmail.com on 17 Oct 2010 at 3:40

GoogleCodeExporter commented 8 years ago
非常宝贵的建议。我换用了Picture,可以画的图确实多了一些�
��但还是不够。直接draw的话,我不太明白的地方是,如何去��
�用这些draw出来的图以响应触摸等交互事件呢?

Original comment by sunny...@gmail.com on 17 Oct 2010 at 9:06

GoogleCodeExporter commented 8 years ago
再具体一点吧,这里有小弟之前写的一个网页小游戏
http://gymbeta.appspot.com
我想把它移植到android上熟悉一下android开发。WVGA上同时绘制��
�么多可以拖动的图是否不太现实?

Original comment by sunny...@gmail.com on 17 Oct 2010 at 9:14

GoogleCodeExporter commented 8 years ago
 sunnylqm兄您好,以Android的默认性能来说,仅仅分解显示此六张人民币小图是不会有问题的(同样的图贴到屏幕上N多张只能减低速度,不会造成溢出),至于溢出的原因,您应该是每个货币角度都创建了一张新图,或者在循环中重复创建图像资源了吧?最好您能贴一下加载图像部分的代码(包括加载事件写在了那个函数中)。

Original comment by loontest@gmail.com on 17 Oct 2010 at 1:55

GoogleCodeExporter commented 8 years ago
理论上讲,添加3、40个Picture图像是没有问题的,建议您在onLo
ad中用GraphicsUtils.getSplitImages("人民币图地址",223,108,false)获得��
�部货币的LImage数组(6张图),然后根据需要通过数组索引分
别将这六张图注入创建的Picture中,并且add到Screen,其它什么�
��不要做,看看显示有没有问题(先不要考虑多角度)。

Original comment by loontest@gmail.com on 17 Oct 2010 at 2:06

GoogleCodeExporter commented 8 years ago
Images.java:
public class Images {
    private static Images imagefactory;
    private static LImage money[];
    private Images() {
        LImage all = GraphicsUtils.loadImage("res/money.jpg");
        money = new LImage[6];
        money[0] = all.getCacheSubImage(0, 0, 223, 109);
        money[1] = all.getCacheSubImage(0, 108, 223, 109);
        money[2] = all.getCacheSubImage(0, 216, 223, 109);
        money[3] = all.getCacheSubImage(222, 0, 223, 109);
        money[4] = all.getCacheSubImage(222, 108, 223, 109);
        money[5] = all.getCacheSubImage(222, 216, 223, 109);
        all.dispose();
    }

    public LImage getImage(int i) {
        return money[i];
    }

    public static synchronized Images getInstance() {
        if (imagefactory != null) {
            return imagefactory;
        } else {
            imagefactory = new Images();
            return imagefactory;
        }
    }

}

Original comment by sunny...@gmail.com on 17 Oct 2010 at 2:10

GoogleCodeExporter commented 8 years ago
Screen的onload:
public void onLoad() {
        setBackground(LColor.white);
        initvalue = new int[6];
//rnd是一随机函数,生成6种面额各自的数量
        initvalue[0] = rnd(7,11);
        initvalue[1] = rnd(7,10);
        initvalue[2] = rnd(6,9);
        initvalue[3] = rnd(6,8);
        initvalue[4] = rnd(5,7);
        initvalue[5] = rnd(5,6);

        int i,a,b,c,d,e,f,xindex,yindex,zindex,rotation;
        int count =initvalue[0]+initvalue[1]+initvalue[2]+initvalue[3]+initvalue[4]+initvalue[5];

        mpic = new Picture[count];
        i=0;
        for(a=0;a<initvalue[0];a++,i++)
        {
                xindex = rnd(80,780);
                yindex = rnd(40,400);
                rotation = rnd(0,360);
                mpic[i] = new Picture(Images.getInstance().getImage(0),xindex, yindex,rotation);
                //mpic[i] = new Picture(Images.getInstance().getImage(0),xindex, yindex);
                //mpic[i].setLayer(i+1);
                add(mpic[i]);

        }
        ...//后面是b-f同样的5个循环
    }

Original comment by sunny...@gmail.com on 17 Oct 2010 at 2:14

GoogleCodeExporter commented 8 years ago
Picture有作如下修改,以自定义角度
    public Picture(LImage image, int x, int y,int degree) {
        this.setImage(image);
        this.setLocation(x, y);
        this.visible = true;
        this.matrix = new Matrix();
        matrix.setRotate(degree, x, y);
    }

    public void createUI(LGraphics g) {
        if (visible) {
            //g.drawImage(image, x(),y());
            g.drawImage(image, matrix);
        }
    }

Original comment by sunny...@gmail.com on 17 Oct 2010 at 2:16

GoogleCodeExporter commented 8 years ago
内牛满面。。。我错了。我直接套用你的AVG的sample时,在title
screen中注释掉了fade效果,然后一并注释掉了init信号量。然后
LButton就在不停的循环被add中。。。于是各种诡异的outofmemory��
�。。。
太粗心了,耽误了你的时间,实在不好意思!
再次感谢你的热心帮助!嘿嘿  
可能以后还会忍不住来骚扰。。。

Original comment by sunny...@gmail.com on 17 Oct 2010 at 4:21