注:请务必结合代码理解!
使用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/