转自:http://www.apkbus.com/android-60053-1-1.html
本讲源代码下载:
- edu.nju.wsj.libgdx.rar(3.78 MB, 下载次数: 131)
我们在第十讲中给大家介绍了Action的用法,并且用一个MoveTo(继承自AnimationAction)给大家演示了一下一个Button的移动过程。但单单一个简单的移动太过于简单,我们也不会满足于仅仅用这么一个效果来作为我们Actor的动作。那么我们今天来看看AnimationAction中的其他几个方法,我们从RotateTo入手。
我们看看官方文档中对RotateTo的介绍:
我们发现,RotateTo和我们在第十讲中介绍的MoveTo的方法是一模一样的,获取实例的方法也是一样的,都是调用静态方法并返回一个实例。那我们用第十讲中同样的方法来构造这么一个RotateTo对象,并且加入Actor的动作之中,看看有什么效果。
我们将在第十讲后的源代码上进行修改,我们将第十讲中加入的MoveTo对象删除,添加RotateTo对象:
- RotateTo rotate;
同样的,我们在show()函数中做出相应的修改:
- rotate=RotateTo.$(60, 1f);
- rotate.setInterpolator(AccelerateDecelerateInterpolator.$());
- rotate.setCompletionListener(new OnActionCompleted(){
- @Override
- public void completed(Action arg0) {
- // TODO Auto-generated method stub
- System.out.println("RotateTo Complete!");
- }
- });
我们在这里设置了一个监听函数,在RotateTo这个Action结束的时候会打印一句话:
- "RotateTo Complete!"
通知我们动作已经结束。
最后别忘了将这个RotateTo和Button绑定起来:
- button.action(rotate);
我们来运行一下,看看效果如何。
很奇怪,没有任何效果。我们看一看输出:
很奇怪,输出是有的,说明这个RotateTo成功执行结束了,那为什么我们没有看到旋转的效果呢?我们再回过头来看看Actor中的成员变量:
红色的部分告诉我们,Actor有一个成员为rotation,从名字可以看出它是表征Actor的转动角度的,那么我们现在就要利用这个rotation来看看我们这个RotateTo是否对我们的Actor有影响。我们在MyGame.java的render()函数中添加这样一段语句:
- System.out.println(button.rotation);
即我们随时打印button的rotation值,检查是不是有什么变化。我们运行一下,来看看输出:
令人庆幸的是,确实存在着输出,也就是说Button(别忘了,这也是一个Actor)的rotation在不断的改变,说明RotateTo确实可以改变它所绑定的Actor的属性,但这里为什么不能直接在绘制中体现出来呢?
那么我们在第十讲中的MoveTo为什么又能体现出效果?我们猜测,MoveTo应该和RotateTo的原理一样,也是改变了所绑定的Actor的x和y值,而且Button的draw()函数中(所有Actor都通过这个函数绘制,还记得我们自定义Actor时自己实现的draw()方法吗)应该是根据x,y绘制的,而并没有根据rotation这个值来绘制,因此虽然RotateTo改变了rotation的值,但我们并没有在绘制函数draw()函数中将其表现出来,因此我们就没有看到旋转的效果了。
为了确认我们的观点,我们来看看libgdx中Button的源码。
这里插一句话,我们在下载好的libgdx包中的sources文件夹下找到对应的源码,除了直接导入jar查看源码,我们还可以直接通过改后缀名将jar改成rar并直接解压缩得到不同的包中的源码。
Button.java在com.badlogic.gdx.scenes.scene2d.ui.Button下。
找到Button的源代码,我们直接来看看Button的draw函数:
- public void draw (SpriteBatch batch, float parentAlpha) {
- float offsetX = 0, offsetY = 0;
- if (isPressed) {
- setBackground(style.down == null ? style.up : style.down);
- offsetX = style.pressedOffsetX;
- offsetY = style.pressedOffsetY;
- } else {
- if (style.checked == null)
- setBackground(style.up);
- else
- setBackground(isChecked ? style.checked : style.up);
- offsetX = style.unpressedOffsetX;
- offsetY = style.unpressedOffsetY;
- }
- validate();
- for (int i = 0; i < children.size(); i++) {
- Actor child = children.get(i);
- child.x += offsetX;
- child.y += offsetY;
- }
- super.draw(batch, parentAlpha);
- for (int i = 0; i < children.size(); i++) {
- Actor child = children.get(i);
- child.x -= offsetX;
- child.y -= offsetY;
- }
- }
从中我们没有看到任何和rotation有关的地方。只有一语句可能含有rotation参数:
- super.draw(batch, parentAlpha);
我们又知道,Button的继承树的最顶端(Actor除外,因为Actor是一个虚类,它的draw()函数是空的)是Group。
那么我们再来看看Group源码中的draw()函数:
- public void draw (SpriteBatch batch, float parentAlpha) {
- if (debug && debugTexture != null && parent != null)
- batch.draw(debugTexture, x, y, originX, originY, width == 0 ? 200 : width, height == 0 ? 200 : height, scaleX, scaleY,rotation, 0, 0, debugTexture.getWidth(), debugTexture.getHeight(), false, false);
- if (transform) applyTransform(batch);
- drawChildren(batch, parentAlpha);
- if (transform) resetTransform(batch);
- }
其他地方我们并不需要过多的关注,我们找重点,其中有一段代码:
- batch.draw(debugTexture, x, y, originX, originY, width == 0 ? 200 : width, height == 0 ? 200 : height, scaleX, scaleY,rotation, 0, 0, debugTexture.getWidth(), debugTexture.getHeight(), false, false);
即是将Group根据x,y来绘制出来。由此我们知道了RotateTo改变了Actor的rotation的值却不能在动画上体现出来了。也就是说Action只负责改变Actor的属性参数,但实际用这些参数绘制出动画,需要我们添加自己的代码(初看起来是很麻烦,但实际上是给了我们更多的空间,可以用少数的参数的变化绘制出多种多样的动画)。
那如果我们要让Actor根据RotateTo修改后的rotation旋转我们该怎么办呢?我们可以修改源码,但是出于开源代码的习惯,我们一般不会直接修改源码,我们可以自己写一个Actor并在其中的draw()函数中将rotation参数在绘制中体现出来,这样就有转动的效果了。
我们可以修改我们工程中的AnimalActor.java,让AnimalActor在绘制的时候根据转动角度rotation来绘制。AnimalActor原来的绘制代码是这样的:
- //以(0,0)绘制为起点(左下角为0,0)画出动画,大小128*128
- arg0.draw(currentFrame,0, 0,128*power,128*power);
我们改用另外一个方法,将rotation这个参数在绘制中体现出来:
- arg0.draw(currentFrame, 0, 0, 64*power, 64*power, 128*power, 128*power, 1, 1, this.rotation, true);
第一个参数即是当前帧currentFrame,第二第三个参数是动画旋转的原点,这里要配合第四第五个参数起作用,第四个第五个参数是旋转点的x,y偏置,比如我们设置旋转原点为(0,0),偏置也设为(0,0),那么实际上的旋转点就是(0,0),即动画绕着屏幕左下角旋转,如果要绕着中心转该怎么办呢?我们就将原点设置为(0,0),并将偏置点设在动画的中心,这样实际的原点就在动画的中心了。我上面就是这么做的。
第六第七个参数是绘制的区域,第八第九是缩放的倍数,我们这里设置成1,即不缩放。第十个参数就是我们要表现的参数了,Actor的旋转角度rotation。第十一个参数是按顺时针还是逆时针绘制(注意,不是指旋转方向的顺时针或者逆时针,旋转方向都是逆时针的,对物理学有一些了解的人都知道,物理中很多量都是以逆时针旋转为正的,true和false的区别大家可以自己修改尝试看看区别。)
我们来修改代码,我们修改过AnimalActor后,我们先将MyGame.java内所有关于RotateTo的代码删除,然后我们在Progress.java(即游戏界面)中添加一个RotateTo:
- RotateTo roll;
同样在show()函数中进行初始化和绑定,这里我们将roll这个动作绑定在animal上
:
- roll=RotateTo.$(360, 5f);
- animal.action(roll);
我们运行一下看看效果:
为什么起初的AnimalActor是竖着的呢?这个其实想一下就能明白,顺时针和逆时针法来计算角度的起点是在我们适中的十二点方向,而且我们起初的角度是0,因此绘制出来就是竖着的。如果我们要让一开始绘制的时候动物是横着的,我们可以将Actor的rotation的初始值置为
90.
我们在接下来的教程中将进行复杂的动画搭配和混合,欢迎大家有不懂的问题和我交流交流。