本文非面向libGDX入门用户,仅为个人日常记录。
相关关键词:Skin-Composer, gdx-vfx
绕不开的控件Skin-Composer
虽然我用着gdx-lml很舒服,但是想要深度定制自己的界面终究还是绕不开使用Skin-Composer。这玩意真的太折磨了,但是又不能不用,gdx-lml基本上都是从skin里取样式的。
一堆的Bug,真是被恶心的不要不要的,包括但不限于:
- 动不动就有些资源对不上——例如删了个资源,原来配置好的使用了这个资源的属性值就变空了,导出skin时也不报错,到游戏运行的时候就报错了,还好libGDX的skin解析报错还算合理,不然就要死了。
- 有些控件(指Skin-Composer自己的控件),例如设置一个颜色的rgb值的输入框,必须在任何时刻保证是个数字,我特么就是想删掉输入一个新的数字——对不起,全部删掉之后不能解析成数字了,于是Skin-Composer crash了!
- 有些控件之间的style有parent关系,在libGDX读取skin的时候会一边解析配置一边关联parent关系,而如果继承style的控件在json中先于parent的控件出现,对不起,游戏启动crash了,他妈的报找不到parent的那个类型。Skin-Composer不会对style的继承关系进行管理,每次export出去还得手动改下json里的位置,经过这波摧残我是真的受不了了,直接不要使用Style的继承保住心智,不然要发疯了。
- 虽然Skin-Composer的官方GIthub页面上 有说哪些不错Skin可以下载,但是有些(多数)Skin是从老版本制作的,那些Skin下载下来之后直接倒进去9成是要出错的,那时候反而更加麻烦,还不如直接用vis-ui的皮肤先临时用着。但是vis-ui的默认皮肤文件里面东西很多,atlas里面的素材也很乱,根本不知道哪个是哪个,最后还是自己从0开始做个皮肤好了。这也是下一小节的内容。
- 反正还有些其他的bug,就是崩的莫名其妙,总之就是一定要制作一个scmp项目来管理皮肤,频繁保存,绝对不能在游戏读取的json上改!
Skin的定制还是应该从0开始
其实从0开始最大的好处就是我其实根本用不到所有的控件,所以如果上来给我贴全部皮肤的样式我会直接懵逼的。我甚至不知道那些控件的属性要放什么,反而加大了我配置皮肤的难度。
所以,个人认为自制libGDX皮肤最好的方法是,首先写使用默认的样式写好你自己的应用的基本UI界面,之后把读取的skin换成一个空的skin,启动游戏,报错里面缺哪个Style就加哪个Style,就从默认的样式里把这个样式加进来。经过一次一次的报错,就可以把所有需要定制的样式全部写完。
Skin的TTF支持
虽然这libGDX官网有介绍怎么在gwt下使用TTF,但是Skin文件里是不带TTF字体配置支持的,而Skin-Composer倒是在导入TTF文件的界面有个指引,算是个加分项吧。这里把类贴一下吧,避免下次自己什么时候忘了。
public class TtfSupportSkin extends Skin {
public TtfSupportSkin(FileHandle skinFile) {
super(skinFile);
}
@Override
protected Json getJsonLoader(final FileHandle skinFile) {
Json json = super.getJsonLoader(skinFile);
final Skin skin = this;
json.setSerializer(FreeTypeFontGenerator.class, new Json.ReadOnlySerializer<FreeTypeFontGenerator>() {
@Override
public FreeTypeFontGenerator read(Json json,
JsonValue jsonData, Class type) {
String path = json.readValue("font", String.class, jsonData);
jsonData.remove("font");
FreeTypeFontGenerator.Hinting hinting = FreeTypeFontGenerator.Hinting.valueOf(json.readValue("hinting",
String.class, "AutoMedium", jsonData));
jsonData.remove("hinting");
Texture.TextureFilter minFilter = Texture.TextureFilter.valueOf(
json.readValue("minFilter", String.class, "Nearest", jsonData));
jsonData.remove("minFilter");
Texture.TextureFilter magFilter = Texture.TextureFilter.valueOf(
json.readValue("magFilter", String.class, "Nearest", jsonData));
jsonData.remove("magFilter");
FreeTypeFontGenerator.FreeTypeFontParameter parameter = json.readValue(FreeTypeFontGenerator.FreeTypeFontParameter.class, jsonData);
parameter.hinting = hinting;
parameter.minFilter = minFilter;
parameter.magFilter = magFilter;
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(skinFile.parent().child(path));
BitmapFont font = generator.generateFont(parameter);
skin.add(jsonData.name, font);
if (parameter.incremental) {
generator.dispose();
return null;
} else {
return generator;
}
}
});
return json;
}
}gdx-vfx屏幕特效踩坑
这个项目gdx-vfx其实看着还挺帅的,所以拿来试了一下,效果是杠杠滴。不过内置的这些特效都太夸张了,只能用来预览效果,实际使用还是要自己做修改。
于是在试玩的过程中就有一些小发现:
- Stage的root actor最好是Window类,否则,在某些Viewport下窗口缩放时会有奇怪的现象,例如在ExtendViewport中以table为root时,对窗口做缩放会出现奇怪的偏移,貌似是Window类有一些特殊的置于屏幕中的定位逻辑。(虽然这个跟gdx-vfx没关系)、
- gdx-vfx貌似不兼容FitViewport的Stage,至少我试了所有的Viewport,只有FitViewport会在窗口缩放的时候控件会出现一些奇怪的裁剪。
- Shader在编译的时候居然会优化掉一些不用的参数,导致我想做一个通用的效果类型来做传参用途行不通(因为参数不存在了),不过这个可以通过设置
ShaderProgram.pedantic = false,让他不需要强行要求所有参数都存在。不过既然默认这么要求肯定是有道理的,估计是为了性能着想,毕竟跟渲染有关系的东西,那么就整通用的呗。
最近的就这些吧。
这几天(主要界面的)UI基本上画好了,接下来可以狠狠地写代码实现了。真是个奇怪的习惯,应该是从安卓开发时期落下的,只当有了完整的设计图我才有开发动力,希望这周能实现个最最最粗略能跑的DEMO.


Leave a Reply