libgdx示例-SuperJumper分析 1. 程序入口与初始化资源,加载配置信息

SuperJumper是libgdx作者写的Demo项目,是一款跳跃动作类游戏,源代码包含在libgdx里,可以在http://code.google.com/p/libgdx/上找到。简单的说一下游戏的玩法,游戏中你将操作一个小人,它碰到版块会不断的往上跳,你可以操作小人左右移动,然后在往上跳的过程中,收集尽可能多的金币,同时要避开飞在空中的蜜蜂,直到到达最顶部的城堡,才进入下一关。下面是游戏运行时的截图:



使用Eclipse 导入工程后,找到java 工程唯一的包下面的SuperJumperDeskstop类,代码如下:

public class SuperJumperDesktop {
    public static void main(String[] argv) {
        new JoglApplication(new SuperJumper(), "Super Jumper", 320, 480, false);
    }
}

可以看出这个就是程序的入口,也就是说其中的 SuperJumper 类,就是游戏实现的入口。打开SuperJumper 类,代码如下:
public class SuperJumper extends Game {
    boolean firstTimeCreate = true;

    @Override
    public Screen getStartScreen() {
        return new MainMenuScreen(this);
    }

    @Override
    public void create() {
         Settings.load();
         Assets.load();
         super.create();
    }
}

这里看到SuperJumper并不是像以前的例子那样实现了ApplicationListener接口,而是继承了Game类。打开Game类,代码如下:|
public abstract class Game implements ApplicationListener {
    Screen screen;

    public void setScreen (Screen helpScreen2) {
        screen.pause();
        screen.dispose();
        screen = helpScreen2;
    }

    public abstract Screen getStartScreen();

    @Override public void create () {
        screen = getStartScreen();
    }

    @Override public void resume () {
        screen.resume();
    }

    @Override public void render () {
        screen.update(Gdx.graphics.getDeltaTime());
        screen.present(Gdx.graphics.getDeltaTime());
    }

    @Override public void resize (int width, int height) {
    }

    @Override public void pause () {
        screen.pause();
    }

    @Override public void dispose () {
        screen.dispose();
    }
}

发现Game已经实现了ApplicationListener接口,并把复写了接口的方法。同时它还内置了一个Screen类型的成员变量,并为其提供了set方法,还定义了一个返回值类型为Screen的getStartScreen()抽象方法。这样就是为什么SuperJumper类会复写了一个 getStartScreen()的原因。

这里可以说明一下思路,Game类其实作用与ApplicationListener是一样的,都是在游戏开始的时候被注入,其中不同的一点就是:对于ApplicationListener,无法在游戏中切换;而Game类,可以通过改变内置的Screen类来达到改变游戏场景的效果。
而Screen其实就是一个个游戏场景的具体类,比如 主菜单,设置菜单,还有主游戏界面等等。可以调用Game类的setScreen来改变游戏中的场景。
也就是说同一时间,Game类只会显示一个Screen,而Screen的基本函数其实Application是一样的,也就包含了完整的生命周期。

注:在实际的libgdx库中,作者已经把Game抽象类和 Screen 接口 加入到jar包中,可以直接使用,具体的不同请参阅API帮助文档。

再回到SuperJumper类中,
public class SuperJumper extends Game {
    boolean firstTimeCreate = true;

    @Override
    public Screen getStartScreen() {
        return new MainMenuScreen(this);
    }

    @Override
    public void create() {
         Settings.load();
         Assets.load();
         super.create();
    }
}

现在就明白了,在SuperJumper的create方法中,调用了父类,也就是Game类的create方法,而Game类的create又调用了子类实现的getStartScreen方法,该方法中生成并返回一个MainMenuScreen 对象,将其赋给父类Game中Screen 成员变量,所以这个就是主菜单界面。这里的逻辑有点复杂,请仔细琢磨。

同时,我们发现create方法中还分别调用了Setting类和Assets类的静态load()方法,这里其实就是加载配置信息和初始化资源。

先说一下Setting类,Setting类主要就是实现了对于配置信息的读取和保存,同时还有记录最高分的功能。在这个游戏中,配置信息就只有一个:是否打开声音。而最高分需要保存前五名的分数。作者把它们都记录在同一个外部文件中,操作的方法结合的标准的JAVA IO  还有libgdx的文件读取机制,读取后都记录在Setting类的成员变量中,供后面程序的使用。比如读取的方法:
    public static void load() {
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(Gdx.files.external(file).read()));
            soundEnabled = Boolean.parseBoolean(in.readLine()); //是否打开声音
            for(int i = 0; i < 5; i++) {
                highscores[i] = Integer.parseInt(in.readLine()); //最高分
            }
        } catch (Throwable e) {
            // :( It's ok we have defaults
        } finally {
            try {
                if (in != null)
                    in.close();
            } catch (IOException e) {
                //
            }
        }
    }

这里 Gdx.files.external(file).read() 表示使用libgdx的文件读取机制,根据file所指定的位置生成一个InputStream ,那么其他操作就和JAVA IO 一样了。
注:对于设置信息的存储,可以使用Android 的SharedPreference 来实现,这样可能会更简便。

再来就是Assets类,顾名思义就是资源类.同样的作者把所有需要用到的资源同及集中在这个类中处理,包括:图片,动画,背景音乐和音效。在说图片资源加载之前先看一下items.png,如下:
(注:背景色是后来加上去的这看的比较清楚,原本背景是透明的)



可以看到,大部分游戏中需要用到的素材图片都被整合到itmes.png中。作者先使用Texture将整个items.png加载进来,然后使用TextureRegion(x,y,width,height) 的构造方法,根据素材图片位置大小的不同来加载不同的图片,这样既可以减少素材图片的数量,也可以提高性能。
再来就是说说Animation类,也就是动画类。libgdx构造动画的方法很简单,只需要设定每一帧动画持续的时间,然后将动画的具体帧(TextureRegion)传递给构造函数既可,例如,上面items.png中金币的旋转动画,如下:
    public static Animation coinAnim;
    coinAnim = new Animation(0.2f,     //每帧持续0.2秒                 
             new TextureRegion(items, 128, 32, 32, 32), //第一帧
             new TextureRegion(items, 160, 32, 32, 32), //第二帧
             new TextureRegion(items, 192, 32, 32, 32), //```
             new TextureRegion(items, 160, 32, 32, 32)
    );

对于音频文件,在libgdx中只有两种:一种是较长的,比如背景音乐;另一种是就是较短的,比如爆炸音效。那么对应过来的就是Music类和Sound类。不管是哪种音频文件,都可以直接调用play() 和 stop () 进行播放和停止。不同的是,Muisic可以调用pause()进行暂停操作,还可以调用setLooping(boolean)方法来设置是否循环播放。同时libgdx推荐使用ogg作为音效文件。

至于音频的加载则是使用Gdx类内置的audio成员变量来加载,如下:
    public static Music music;
    public static Sound jumpSound;

    music = Gdx.audio.newMusic(Gdx.files.internal("data/music.mp3"));    //加载背景音乐
    music.setLooping(true);  //设置背景音乐循环播放
    music.setVolume(0.5f);   //设置音量
    if (Settings.soundEnabled)
        music.play();        //播放背景音乐

    jumpSound = Gdx.audio.newSound(Gdx.files.internal("data/jump.ogg")); //加载跳跃时候的音效

看完了上面图片和音频文件的加载,会发现,所有的操作都涉及到Gdx这个类,下面就来看一下Gdx类,如下:
public class Gdx {
    public static Application app;
    public static Graphics graphics;
    public static Audio audio;
    public static Input input;
    public static Files files;

    public static GLCommon gl;
    public static GL10 gl10;
    public static GL11 gl11;
    public static GL20 gl20;
    public static GLU glu;
}

这个类看起来非常的简单,但却是libgdx运行的核心所在。所有的关键组件的实例都会在Libgdx初始化时被注入Gdx这个类对应的静态变量中,比如Files的实例files就是用于文件读取的操作,而Audio的实例audio就是负责音频文件的创建和管理。
另外,对于OpenGL接口的实例,也被注入到这个类里面。所以,在实际游戏开发中应该使用Gdx类中的静态变量来完成相关的操作,这也是作者所提倡的。

至此游戏的初始化部分就完成了。
 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值