java-universal-tween-engine
ibgdx的ui库可以实现一些动画效果,但是做游戏来说可能有些不足。Universal Tween Engine是一个纯java实现的动画库。
地址:http://code.google.com/p/java-universal-tween-engine/
只要能够用float表示的一切java对象它可以让它动画化,可以使用于Libgdx、Android、Swing等等。
Universal Tween Engine使用一般流程
使用Universal Tween Engine最重要的一个步骤就是实现TweenAccessor接口,这个接口定义了getValues和setValues方法。
然后Engine中注册对应的接口。然后定义一些动画效果并添加到管理器中。最后用update方法更新时间。
具体的可以参考一下Wiki:http://code.google.com/p/java-universal-tween-engine/wiki/GetStarted
在libgdx中实现简单动画
我比较喜欢使用Stage,所以下面的例子都是Stage中的。
首先实现TweenAccessor接口,我没有区分对待,比如给Image写一个,再给Button写个啥的。我直接给Actor写了一个,这样都可以用。
getValues和setValues中我定义了3中操作:只修改X值;只修改Y值;修改X和Y值。
123 | public static final int POSITION_X = 1;public static final int POSITION_Y = 2;public static final int POSITION_XY = 3; |
这里注意一下getValues的返回值,你修改或者操作了几个值就返回几。
代码如下:
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 | package com.cnblogs.htynkn;import aurelienribon.tweenengine.TweenAccessor;import com.badlogic.gdx.scenes.scene2d.Actor;public class ActorAccessor implements TweenAccessor {public static final int POSITION_X = 1;public static final int POSITION_Y = 2;public static final int POSITION_XY = 3;@Overridepublic int getValues(Actor target, int tweenType, float[] returnValues) {switch (tweenType) {case POSITION_X:returnValues[0] = target.x;return 1;case POSITION_Y:returnValues[0] = target.y;return 1;case POSITION_XY:returnValues[0] = target.x;returnValues[1] = target.y;return 2;default:assert false;return -1;}}@Overridepublic void setValues(Actor target, int tweenType, float[] newValues) {switch (tweenType) {case POSITION_X:target.x = newValues[0];break;case POSITION_Y:target.y = newValues[0];break;case POSITION_XY:target.x = newValues[0];target.y = newValues[1];break;default:assert false;break;}}} |
然后来写具体的动画和绘制部分。为了方便演示我编写一个随着点击移动的小图标的例子。
我的图标是
。声明image和stage的绘制和原来一样。先声明一个动画管理器
1 | private TweenManager tweenManager = new TweenManager(); |
然后将我们的Image注册一下
1 | Tween.registerAccessor(Image.class, new ActorAccessor()); |
同时实现InputProcessor接口以接收触碰事件。
在touchDown方法中添加
123456789 | @Overridepublic boolean touchDown(int x, int y, int pointer, int button) {Vector3 vector3 = new Vector3(x, y, 0);stage.getCamera().unproject(vector3);Tween.to(image, ActorAccessor.POSITION_XY, 1.0f).ease(Bounce.OUT).target(vector3.x, vector3.y).start(tweenManager);return false;} |
说明一下,因为Stage的坐标和默认的Input的坐标不一致,所以通过unproject转化一下。
Tween.to(image, ActorAccessor.POSITION_XY, 1.0f)代表操作image对象移动。target(vector3.x, vector3.y)代表移动的目标。
ease(Bounce.OUT)声明了缓冲效果,具体的效果可以参考http://robertpenner.com/easing/easing_demo.html
start(tweenManager)启动管理器。
在render方法中添加
1 | tweenManager.update(Gdx.graphics.getDeltaTime()); |
让管理器的时间更新。
完整代码:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 | package com.cnblogs.htynkn;import aurelienribon.tweenengine.Tween;import aurelienribon.tweenengine.TweenManager;import aurelienribon.tweenengine.equations.Bounce;import com.badlogic.gdx.ApplicationListener;import com.badlogic.gdx.Gdx;import com.badlogic.gdx.InputMultiplexer;import com.badlogic.gdx.InputProcessor;import com.badlogic.gdx.graphics.GL10;import com.badlogic.gdx.graphics.g2d.TextureAtlas;import com.badlogic.gdx.math.Vector3;import com.badlogic.gdx.scenes.scene2d.Stage;import com.badlogic.gdx.scenes.scene2d.ui.Image;public class App implements ApplicationListener, InputProcessor {Stage stage;private TweenManager tweenManager = new TweenManager();Image image;@Overridepublic void create() {stage = new Stage(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(),true);TextureAtlas atlas = new TextureAtlas("packer/test.pack");image = new Image(atlas.findRegion("news"));image.x = 20;image.y = 20;stage.addActor(image);Tween.registerAccessor(Image.class, new ActorAccessor());InputMultiplexer multiplexer = new InputMultiplexer();multiplexer.addProcessor(this);multiplexer.addProcessor(stage);Gdx.input.setInputProcessor(multiplexer);}@Overridepublic void dispose() {}@Overridepublic void render() {tweenManager.update(Gdx.graphics.getDeltaTime());Gdx.gl.glClearColor(1, 1, 1, 1);Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);stage.act(Gdx.graphics.getDeltaTime());stage.draw();}@Overridepublic void resize(int width, int height) {}@Overridepublic void pause() {}@Overridepublic void resume() {}@Overridepublic boolean keyDown(int keycode) {// TODO Auto-generated method stubreturn false;}@Overridepublic boolean keyUp(int keycode) {// TODO Auto-generated method stubreturn false;}@Overridepublic boolean keyTyped(char character) {// TODO Auto-generated method stubreturn false;}@Overridepublic boolean touchDown(int x, int y, int pointer, int button) {Vector3 vector3 = new Vector3(x, y, 0);stage.getCamera().unproject(vector3);Tween.to(image, ActorAccessor.POSITION_XY, 1.0f).ease(Bounce.OUT).target(vector3.x, vector3.y).start(tweenManager);return false;}@Overridepublic boolean touchUp(int x, int y, int pointer, int button) {// TODO Auto-generated method stubreturn false;}@Overridepublic boolean touchDragged(int x, int y, int pointer) {// TODO Auto-generated method stubreturn false;}@Overridepublic boolean touchMoved(int x, int y) {// TODO Auto-generated method stubreturn false;}@Overridepublic boolean scrolled(int amount) {// TODO Auto-generated method stubreturn false;}} |
因为是动画效果,这里就不贴出了,文章末尾会有一个小视频的。
使用TimeLine实现更多动画效果
上面只是一个简单的移动效果,但就动画而言这个显然是不够的。如果希望实现一个渐渐显示的效果怎么办?
还是想想TweenAccessor接口,只要float类型的值就行了。所以同样的我们可以实现修改透明程度、大小等等实现更多的效果。
我最终选用了六种效果:
123456 | public static final int POS_XY = 1;public static final int CPOS_XY = 2;public static final int SCALE_XY = 3;public static final int ROTATION = 4;public static final int OPACITY = 5;public static final int COLOR = 6; |
实现修改X和Y值,修改X和Y值(包括对象自身大小),修改缩放,修改旋转,修改透明,修改颜色。
代码如下:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 | package com.cnblogs.htynkn;import aurelienribon.tweenengine.TweenAccessor;import com.badlogic.gdx.graphics.Color;import com.badlogic.gdx.scenes.scene2d.Actor;public class ActorAccessor implements TweenAccessor {public static final int POS_XY = 1;public static final int CPOS_XY = 2;public static final int SCALE_XY = 3;public static final int ROTATION = 4;public static final int OPACITY = 5;public static final int TINT = 6;@Overridepublic int getValues(Actor target, int tweenType, float[] returnValues) {switch (tweenType) {case POS_XY:returnValues[0] = target.x;returnValues[1] = target.y;return 2;case CPOS_XY:returnValues[0] = target.x + target.width / 2;returnValues[1] = target.y + target.height / 2;return 2;case SCALE_XY:returnValues[0] = target.scaleX;returnValues[1] = target.scaleY;return 2;case ROTATION:returnValues[0] = target.rotation;return 1;case OPACITY:returnValues[0] = target.color.a;return 1;case TINT:returnValues[0] = target.color.r;returnValues[1] = target.color.g;returnValues[2] = target.color.b;return 3;default:assert false;return -1;}}@Overridepublic void setValues(Actor target, int tweenType, float[] newValues) {switch (tweenType) {case POS_XY:target.x = newValues[0];target.y = newValues[1];break;case CPOS_XY:target.x = newValues[0] - target.width / 2;target.y = newValues[1] - target.height / 2;break;case SCALE_XY:target.scaleX = newValues[0];target.scaleY = newValues[1];break;case ROTATION:target.rotation = newValues[0];break;case OPACITY:Color c = target.color;c.set(c.r, c.g, c.b, newValues[0]);target.color = c;break;case TINT:c = target.color;c.set(newValues[0], newValues[1], newValues[2], c.a);target.color = c;break;default:assert false;}}} |
因为Actor中的color是final,所以不能修改,自己改一下源代码吧。
TimeLine是Universal Tween Engine中的一大利器,可以实现平行和顺序动画。
比如
123456 | Timeline.createSequence().beginSequence().push(Tween.to(image, ActorAccessor.POS_XY, 1.0f).target(100,100)).push(Tween.to(image, ActorAccessor.POS_XY, 1.0f).target(200,20)).start(tweenManager); |
就表示先移动到100,100处在移动到200,20处。
再比如
1234567 | Timeline.createParallel().beginParallel().push(Tween.to(image, ActorAccessor.CPOS_XY, 1.0f).target(vector3.x, vector3.y)).push(Tween.to(image, ActorAccessor.ROTATION, 1.0f).target(360)).push(Tween.to(image, ActorAccessor.SCALE_XY, 1.0f).target(1.5f, 1.5f)).end().start(tweenManager); |
实现的就是一般移动一般旋转和放大的效果。
更多相关文章
- [安卓开发Android][叠层 层叠 卡片效果]RecyclerView与CardView
- Android(安卓)RecyclerView 滑动到指定item(position)并加动画
- LCD:LCD常用接口原理篇
- Android(安卓)-- Property Animation
- Android创建旋转箭头-不恢复原位-旋转动画的使用
- Android框架保证View更新必须在主线程的解读
- Android(安卓)读取扫码枪的内容,可以读取条形码 ,二维码
- Android:TextView的垂直滚动效果,和上下滚动效果
- Android中的Parcelable序列化对象