by AlexQ (email alexq_andr@163.com)
工程托管在此:GitHub-粒子特效
What's libGDX?
libGDX is a cross-platform Java game development framework based on OpenGL (ES) that works on Windows, Linux, Mac OS X, Android, your WebGL enabled browser and iOS.
好久不见!
本周末参加了GMTC大会,收获颇多,尤其是微信团队叶润桂关于弱网处理的介绍,真是开了眼界,他们是真正的开发者在做改变世界改变互联网的事情,更觉技术无边界,潜心修炼内功,努力实践是多么重要,激发自己也要不断创新、总结,自己也要把这前做的东西深入深入再深入,那么就从这篇libgdx在原生应用中的特效综合笔记开始吧!!!
进入正题啦
距离上一次发表四篇文章《Android FrameWork 基于libGDX实现高性能动画特效(粒子特效/烟花效果篇)》《libGDX 入门精要》《Box2D 入门简要》《Android FrameWork 基于libGDX实现高性能动画特效(Box2D/物理碰撞 篇)》,过去很久了,这段时间对于libgdx技术的使用有了一点点新的认识和应用。借着这篇文章的机会和大家分享一下吧。虽然有了些新的代码和好玩儿效果,但是基本上也是复用了我们之前的技术、框架上没有大的飞跃和改变,也体现出这个框架在输出产生新效果时,改动小效果佳的特性。
这段时间特效仓库有什么变化
解决触控层级问题
在《Android FrameWork 基于libGDX实现高性能动画特效(粒子特效/烟花效果篇)》中“设置透明以及层级”中提到的层级问题,用以下方式可以完美解决:通过InterceptableViewGroup替换原有普通的layout容器解决,让我看一下这个实现比较简单。
public class InterceptableViewGroup extends RelativeLayout {
private boolean intercept = false;
public InterceptableViewGroup(Context context) {
super(context);
}
public InterceptableViewGroup(Context context, AttributeSet attrs) {
super(context, attrs);
}
public InterceptableViewGroup(Context context, AttributeSet attrs, int
defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (intercept)
return true;
return super.onInterceptTouchEvent(ev);
}
public void setIntercept(boolean intercept) {
this.intercept = intercept;
}
}
通过这个实现,我们可以将现在的libgdxfragment放在任何层级,而不影响app的触控行为。good!!!
利用粒子效果实现点赞飘动的效果
这个DEMO(GitHub-粒子特效)
利用粒子效果改造一下就可以了,实现中主要有几点需要关注一下:
调试粒子轨迹文件***.p这个文件的编辑,让这种飘动效果看起来自然有一定的随机效果
-
增加用代码控制的方式,设置几个libgdx粒子效果参数,这样的好处是:
- 控制比.p文件灵活,例如可以增加一些随机数值等等,定制化比较强的逻辑;
- 由于.p文件中计量单位都是像素,这样设置出来的效果在不同分辨率的手机看起来效果不同,举个例子移动速度在.p文件中设置为100像素每秒的话,在高分屏幕上看起来就要比低分屏幕上移动的慢,如果用代码设置的话,你可以实现一个dp转px的方法,这样以相对距离单位这样在不同手机上看到的效果基本上就相同了。如下这部分代码所示:
//创建粒子系统
//放大系数
float scale_lowMin = Utils.DpToPx(0);
float scale_lowMax = Utils.DpToPx(0);
float scale_highMin = Utils.DpToPx(43);
float scale_highMax = Utils.DpToPx(48);
//移动系数
float move_lowMin = Utils.DpToPx(15);
float move_lowMax = Utils.DpToPx(25);
float move_highMin = Utils.DpToPx(95);
float move_highMax = Utils.DpToPx(125);
//设置放大缩小效果
try{
mParticle.getEmitters().get(0).getScale().setLow(scale_lowMin,
scale_lowMax);
mParticle.getEmitters().get(0).getScale().setHigh(scale_highMin,
scale_highMax);
}
catch (Exception e){
e.printStackTrace();
}
//设置发生器发射速度
try {
mParticle.getEmitters().get(0).getVelocity().setLow(move_lowMin,
move_lowMax);
mParticle.getEmitters().get(0).getVelocity().setHigh(move_highMin,
move_highMax);
}
catch (Exception e){
e.printStackTrace();
}
利用Box2D碰撞实现礼物掉落效果
这个例子是Box2D(GitHub-Box2D碰撞特效,"dianzan"这个分支上)上加以改造完成的。
需要关注的是:
- Texture的图片的加载要在libgdx生命周期的函数内完成,这个其实在之前粒子效果那篇文章中已经用到了,但是有一阵子没写libgdx相关代码,居然自己都忘记了。我这里是把创建逻辑放在了libgdx生命周期的create方法内,如下所示:
<code><pre>
@Override
public void create() {
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
for (int i=1; i < size; i++)
m_giftTextures.add( new Texture(Gdx.files.internal("gifts/"+i
+".png")));
m_starTextures.add(new Texture(Gdx.files.internal("star.png")));
m_starTextures.add(new Texture(Gdx.files.internal("star_self.png")));
......省略其他逻辑......
}
</code></pre>
如果你没明白的话,你可以试着把加载图片逻辑封住一个public单独的方法,在外部直接调用,不管你是在什么线程上调用,图片都无法加载成功,现象时图片会显示为一个个小黑方块,这点真的值得注意。
两种特效一同使用
问题:在同一个显示区域或者说同一个activity中,我想同时使用两种特效(粒子特效和box2d碰撞特效)有问题吗?
因为目前粒子效果和box2d是封装在两个继承自AndroidFragmentApplication的fragment中,如果你直接使用两个fragment层叠的话,处于下层的那个fragment是看不到的。
问题:如何解决?
需要合并代码,合并哪些代码呢,首先外层是用同一个继承自AndroidFragmentApplication的fragment,由于此fragment中核心代码不多,基本上此部分原有的两个fragment相似度95%,只有部分业务接口不同,取并集就可以了,比较简单。另外继承自ApplicationListener的view要合并,核心是要在同一个render上完成两类效果的绘制就可以了,此部分代码由于量比较大,需要开发者要使用一定的设计模式更好的设计结构就可以了,没有什么其他太多的技术难点。
思考与改进
libgdx还能做什么
如果你熟练掌握了我介绍的这套知识和框架,那么你在一些特效实现上可能多了一个不错的选择。最近我也在结识更多的libgdx开发者,大家相互探讨,如果你有兴趣,可以发邮件email给我哦,相互学习一下。
另外多看libgdx的源码营养充分,了解他内部结构知识,对于学习OpenGL很有帮助。
框架改进
目前在项目中使用这个框架有个问题就是对于那些在乎包大小的工程是个问题,我也在努力研究看是否能够裁剪框架,重新编译一个精简版本。但是这个仅仅作为预研内容,毕竟libgdx本身还在不断改进,这种裁剪可能会对后续升级有很大限制。
一点点感受总结
长话短说,此次libgdx之旅,这两点我感触比较深吧:
- 理论从"书"中得来,实战+产品化才能补齐框架短板;
- 脑洞大开,不设天花板,落实到键盘上,得到的比预想的要多;