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

来源:互联网 发布:淘宝店怎么才能靠前 编辑:程序博客网 时间:2024/04/30 04:45

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类中的静态变量来完成相关的操作,这也是作者所提倡的。

至此游戏的初始化部分就完成了。

转自: http://tonmly.blog.163.com/blog/static/17471285620116282742324/
 
原创粉丝点击