[案例研究]—superJumper 1.程序入口与初始化资源,加载配置信息

注:请务必结合代码理解!

superJumper是作者使用libgdx制作的一款跳跃动作类游戏,游戏的工程和源代码可以在作者的网页上找到,简单的说一下游戏的玩法。游戏中你将操作一个小人,它碰到版块会不断的往上跳,你可以操作小人左右移动,然后在往上跳的过程中,收集尽可能多的金币,同时要避开飞在空中的蜜蜂,直到到达最顶部的城堡,才进入下一关。下面是游戏运行时的截图:
[案例研究]—superJumper  1.程序入口与初始化资源,加载配置信息 - tonmyWu - tonmyWu
 


使用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,如下:
(注:背景色是后来加上去的这看的比较清楚,原本背景是透明的)
[案例研究]—superJumper  1.程序入口与初始化资源,加载配置信息 - tonmyWu - tonmyWu
可以看到,大部分游戏中需要用到的素材图片都被整合到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/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值