关于LGame中的LTextureList


LTextureList,是一个与前例介绍的LTexturePack形似而神异的不同存在。


两者的差异在于:

LTexturePack专注于“分散纹理的统一管理,会将注入当中的所有小图合并为一”。

LTextureList专注于“分散纹理的分散管理,会保留所有小图的引用而分别调用”。

事实上,由于Android中提供个单独程序的图像空间非常有限,无论怎么有效释放,Bitmap都不能同时存在太多。而LTextureList就是专为处理海量图片所准备的,在配置了相关xml文档后,LTextureList将仅在执行对应名称纹理的loadTexture时,才会加载LTexture(也就是所谓的“惰性加载”)。而不会一次性加载完毕,且加载一次后会立即产生缓存,只要不注销资源,即使再次loadTexture也不会重复加载。因此,即使您在xml中填入几万张图片地址也无所谓,完全不必担心实时加载所带来的程序瘫痪。

LTextureList最简单的用法莫过于此:

images.xml配置:

<?xml version="1.0" standalone="yes"?>
<images>
    <ref name="hero">
        <image src="assets/hero_a.png">
        </image>
    </ref>
    <ref name="enemy">
        <image src="assets/enemy_a.png">
        </image>
    </ref>
</images>

对应的java配置如下:

package org.loon.test;

import org.loon.framework.javase.game.GameScene;
import org.loon.framework.javase.game.core.graphics.Screen;
import org.loon.framework.javase.game.core.graphics.opengl.GLColor;
import org.loon.framework.javase.game.core.graphics.opengl.GLEx;
import org.loon.framework.javase.game.core.graphics.opengl.LTextureList;
import org.loon.framework.javase.game.core.input.LTouch;
import org.loon.framework.javase.game.core.input.LTransition;
import org.loon.framework.javase.game.core.timer.LTimerContext;

public class LTextureListTest extends Screen {

    LTextureList list;

    public LTransition onTransition() {
        return LTransition.newEmpty();
    }

    public void onLoad() {
        // 把Screen背景色定为红色
        setBackground(GLColor.red);
        // 从指定xml文档获取LTextureList实例
        list = new LTextureList("assets/images.xml");
    }

    public void alter(LTimerContext timer) {

    }

    public void draw(GLEx g) {
        if (isOnLoadComplete()) {
            g.drawTexture(list.loadTexture("hero"), 32, 32);
            g.drawTexture(list.loadTexture("enemy"), 32, 64);
        }
    }

    public void touchDown(LTouch e) {
    }

    public void touchDrag(LTouch e) {

    }

    public void touchMove(LTouch e) {

    }

    public void touchUp(LTouch e) {

    }

    public void dispose() {
        if (list != null) {
            list.dispose();
            list = null;
        }
    }

    public static void main(String[] args) {
        GameScene game = new GameScene("LTextureListTest", 480, 320);
        game.setShowFPS(true);
        game.setShowLogo(false);
        game.setScreen(new LTextureListTest());
        game.showScreen();
    }
}

运行上述程序后,我们会得到如下显示画面:



此时,如果有一些基本的图像变动,也不需再修改任何程序代码,仅微调xml参数即可,比如,当我们需要hero去掉黑底时,只要进行如下设置:
<?xml version="1.0" standalone="yes"?>
<images>
    <ref name="hero">
        <image src="assets/hero_a.png">
          <mask r="0" g="0" b="0" />
        </image>
    </ref>
    <ref name="enemy">
        <image src="assets/enemy_a.png">
        </image>
    </ref>
</images>

这时,我们在image元素中,加入了<mask r="0" g="0" b="0" />一行,即过滤掉0,0,0像素,这时我们再次执行程序,画面将变为如下所示。


怎么样,大家发现变化了没有?原来【hero系列】的黑底,是否已经消失不见了呢?可惜,这样依旧是一组连续的图片,这样的“英雄连”我们还无法直接在游戏中使用,所以,我们要继续修改xml设置,直到生成的纹理被用户能够接受为止。

<?xml version="1.0" standalone="yes"?>
<images>
    <ref name="hero">
        <image src="assets/hero_a.png" x="0" y="0" w="24" h="24" scale="2">
          <mask r="0" g="0" b="0" />
        </image>
    </ref>
    <ref name="enemy">
        <image src="assets/enemy_a.png">
        </image>
    </ref>
</images>

这次,增加了x="0" y="0" w="24" h="24"这样一行文字,并且添加有scale="2"。这是干什么用的呢?其实在上例讲到LTexturePack时,小弟已经做过了类似的事情,不过是告知系统从一整张图片的x=0,y=0处开始取图,一直取到w=24,h=24处停止罢了(也就是第一个“士兵”的图片位置)。不过这里有处与LTexturePack明显的差别,既LTexturePack中所取得的小图是系统从一整张大纹理中“虚拟”出来的,不会消耗任何额外的内存或显存空间,而LTextureList所取出的小图,对系统而言可是真实纹理,显存中实际存在的一张图像。



当然,LTextureList也可以单纯作为图像List使用,设定统一的setBlendMode改变图像的混图模式,透明度等等,比如:
package org.loon.test;

import org.loon.framework.javase.game.GameScene;
import org.loon.framework.javase.game.core.graphics.Screen;
import org.loon.framework.javase.game.core.graphics.opengl.GL;
import org.loon.framework.javase.game.core.graphics.opengl.GLColor;
import org.loon.framework.javase.game.core.graphics.opengl.GLEx;
import org.loon.framework.javase.game.core.graphics.opengl.LTextureList;
import org.loon.framework.javase.game.core.input.LTouch;
import org.loon.framework.javase.game.core.input.LTransition;
import org.loon.framework.javase.game.core.timer.LTimerContext;

public class LTextureListTest extends Screen {

    LTextureList list;

    public LTransition onTransition() {
        return LTransition.newEmpty();
    }

    public void onLoad() {
        // 把Screen背景色定为红色
        setBackground(GLColor.red);
        list = new LTextureList();
        list.add("assets/hero_a.png", 32, 32);
        list.add("assets/enemy_a.png", 32, 64);
        list.setBlendMode(GL.MODE_COLOR_MULTIPLY);
    }

    public void alter(LTimerContext timer) {

    }

    public void draw(GLEx g) {
        if (isOnLoadComplete()) {
            list.draw(g);
        }
    }

    public void touchDown(LTouch e) {
    }

    public void touchDrag(LTouch e) {

    }

    public void touchMove(LTouch e) {

    }

    public void touchUp(LTouch e) {

    }

    public void dispose() {
        if (list != null) {
            list.dispose();
            list = null;
        }
    }

    public static void main(String[] args) {
        GameScene game = new GameScene("LTextureListTest", 480, 320);
        game.setShowFPS(true);
        game.setShowLogo(false);
        game.setScreen(new LTextureListTest());
        game.showScreen();
    }
}

不过,这样就失去预设定与惰性加载的能力了。


说完了LTextureList,但这种程度的篇幅作为博文来说依旧太短了,所以小弟下面再来谈谈0.3.2中新增的几个辅助类。

关于Session类


LGame中的Session类,是为了在多Screen中传值与保存多值而设计的,RecordStore类(高仿JavaME)的再简化版本,它每次set的可以是唯一的键值对,也可以在同一键下挂多值,在执行dispose函数前,session每次save的数值都将永久保存(JavaSE版保存为本地文件,Android版保存到手机数据库)。

下面是一个非常简单的用例。

package org.loon.test;

import java.util.Calendar;

import org.loon.framework.javase.game.GameScene;
import org.loon.framework.javase.game.core.LSystem;
import org.loon.framework.javase.game.core.graphics.Screen;
import org.loon.framework.javase.game.core.graphics.opengl.GLEx;
import org.loon.framework.javase.game.core.input.LTouch;
import org.loon.framework.javase.game.core.input.LTransition;
import org.loon.framework.javase.game.core.store.Session;
import org.loon.framework.javase.game.core.timer.LTimerContext;

public class SessionTest extends Screen {

    Session session = new Session(SessionTest.class.getName());

    public LTransition onTransition() {
        return LTransition.newEmpty();
    }

    public void onLoad() {

    }

    public void alter(LTimerContext timer) {

    }

    public void draw(GLEx g) {
        g.drawString("save 0 :" + session.get("save", 0), 32, 64);
        g.drawString("save 1 :" + session.get("save", 1), 32, 96);
    }

    public void touchDown(LTouch e) {
    }

    public void touchDrag(LTouch e) {

    }

    public void touchMove(LTouch e) {

    }

    public void touchUp(LTouch e) {

    }

    public void dispose() {
        if (session != null) {
            session.set("save", 0, session.getInt("save", 0) + 1);
            session.set("save", 1, System.currentTimeMillis());
            session.save();
        }
        /**
         * delete session
         *
         * if (session != null)
         * {
         *  session.dispose();
         *  session = null;
         * }
         */
    }

    public static void main(String[] args) {
        GameScene game = new GameScene("SessionTest", 480, 320);
        game.setShowFPS(true);
        game.setShowLogo(false);
        game.setScreen(new SessionTest());
        game.showScreen();
    }
}


关于HttpClient类

HttpClient类是为了保证LGame应用在跨平台时接口一致而构建的,处理简单网页资源浏览的工具类,基本用法如下所示。
    HttpClient webClient = new HttpClient("www.baidu.com");
    webClient.start();
    System.out.println(webClient.doHTML("gb2312"));
    webClient.stop();

除了常规的网页加载外,HttpClient还可以作为下载器使用,基本用例如下所示:
package org.loon.test;

import org.loon.framework.javase.game.GameScene;
import org.loon.framework.javase.game.action.sprite.Label;
import org.loon.framework.javase.game.core.graphics.Screen;
import org.loon.framework.javase.game.core.graphics.component.LButton;
import org.loon.framework.javase.game.core.graphics.component.LProgress;
import org.loon.framework.javase.game.core.graphics.opengl.GLColor;
import org.loon.framework.javase.game.core.graphics.opengl.GLEx;
import org.loon.framework.javase.game.core.input.LTouch;
import org.loon.framework.javase.game.core.input.LTransition;
import org.loon.framework.javase.game.core.timer.LTimerContext;
import org.loon.framework.javase.game.net.HttpClient;
import org.loon.framework.javase.game.net.HttpDownload;
import org.loon.framework.javase.game.net.HttpDownload.HttpDownloadListener;

public class DownloadTest extends Screen {

    public LTransition onTransition() {
        return LTransition.newEmpty();
    }

    public void onLoad() {

        //背景红色
        setBackground(GLColor.red);

        //构建一个字符标签
        final Label label = new Label("State : None", 200, 128);
        label.setColor(GLColor.white);
        add(label);

        //构建HttpClient
        final HttpClient webClient = new HttpClient(
                "http://libgdx.googlecode.com/files/libgdx-0.9.1.zip");

        //构建一个进度条
        final LProgress progress = new LProgress(32, 52, 420, 50);
        progress.setProgressTitle(true);
        add(progress);

        //构建一个下载按钮
        LButton button = new LButton("download", 32, 64, 100, 100) {

            HttpDownload download;

            //设定一个下载标记,避免重复点击
            boolean downloadFlag = false;

            public void downClick() {

                if (!downloadFlag) {

                    downloadFlag = true;

                    //进度监听
                    final HttpDownloadListener listener = new HttpDownloadListener() {

                        public void cancel() {
                            label.setLabel("State : Cancel");
                        }

                        public void completed() {
                            label.setLabel("State : Completed");
                            downloadFlag = false;
                            if (download != null) {
                                download.save("c:\\test.zip");
                                webClient.stop();
                            }
                        }

                        public void downloading(float c) {
                            label.setLabel("State : Downloading");
                            progress.percent((int) c);
                        }

                        public void error(Exception ex) {
                            label.setLabel("State : Error");
                        }

                        public void paused() {
                            label.setLabel("State : Paused");
                        }

                    };

                    Runnable runnable = new Runnable() {
                        public void run() {
                            webClient.start();
                            download = webClient.getHttpDownload();
                            download.setListener(listener);
                            download.start();
                        }

                    };
                    callEvent(runnable);
                }
            }

        };

        add(button);
    }

    public void alter(LTimerContext timer) {

    }

    public void draw(GLEx g) {

    }

    public void touchDown(LTouch e) {
    }

    public void touchDrag(LTouch e) {

    }

    public void touchMove(LTouch e) {

    }

    public void touchUp(LTouch e) {

    }

    public void dispose() {

    }

    public static void main(String[] args) {
        GameScene game = new GameScene("DownloadTest", 480, 320);
        game.setShowFPS(true);
        game.setShowLogo(false);
        game.setScreen(new DownloadTest());
        game.showScreen();
    }
}

效果如下所示:


__________________________

另,在LGame的SVN中,有一个小弟开发中的0.3.3测试版(内含jar及源码,loon-simple.googlecode.com/svn/trunk/),此版本与小弟目前手中的最新版本仅有个别细节处的差异(差的仅为效率问题修正),因为小弟正在集中精力搞C#版的完善与C/C++版的开发,0.3.3正式版暂时不会面世(我会将C/C++、C#、Java版都统一到0.3.3结构下,所以会多用点时间),但小弟会将一些最近的修改发往此处存底,如果大家在使用0.3.2时遇到一些问题,也可以换用0.3.3测试版实验运行,也许相关问题在此版就已经解决了(此LGame-0.3.3-test文件大约每周更新一次,上次更新是三天前)。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值