【课程内容】
今天我们将利用昨天搭建好得游戏框架来实现一个简单的动画效果。
【源代码下载地址】http://download.csdn.net/detail/elong_2009/6444787
1、动画的简单原理
实现动画的原理很简单,就是利用人眼的视觉暂留,将一系列相差不多的图片按顺序显示,就会在大脑里留下连续动作的印象。
在android中,要实现动画效果,要么通过循环调用canvas.draw系统方法,要么通过调用OpenGL ES中的GLSurfaceView.Renderer实现方法onDrawFrame方法。
canvas画图确实要简单得多,但要实现更好的性能最好还是调用OpenGL ES方法,因为它的性能相对来说要好一些。本课程使用OpenGL ES的方法。
实现动画的关键就是实现GLSurfaceView.Renderer接口内的方法,最重要的一个就是onDrawFrame,这个方法大体的原理是开起一个线程,在此线程内不断的调用onDrawFrame,以实现动画效果。因此onDrawFrame的主要作用就是将不同的图片显示出来就可以了。
2、动画素材
在昨天的课程中,我们将多个素材集中在同一个图片文件中,然后通过设置纹理顶点来获取不同的素材。
今天我们使用另外一种方法。因为,从天天爱消除的res文件夹中,我们能直接得到十张(loading_01.png ~ loading_10.png)用于动画效果的图片,而该图片背景是透明的,用PhotoShop加工时,分辨率不好控制,导致最后显示效果不是很好。
有一点需要注意的是,loading_xx.png的分辨率是280x150,并不是OpenGL ES要求的2的n次方,因此,如果在运行今天的程序时,如果你发现显示不正常,很有可能就是这个原因造成的,你需要手工将图片转换成满足要求的分辨率,如 256x128。不过目前大多数手机都不会受这个约束限制,因此您可能并不会遇到这个问题。但考虑到兼容性,您在获取素材时,还是考虑这个问题比较好!
3、设计渲染类 DrawLoading
DrawLoading 的作用是显示正在加载的动画效果。公共方法draw实现对该动画效果的渲染。
以下是纹理坐标的定义,与昨天的情况不同,由于不需要根据witch来确定纹理顶点坐标,因此给出的定义非常简单:
float textureCoors[]=new float[]//顶点纹理S、T坐标值数组
{
0,0,
0,1,
1,1,
1,1,
1,0,
0,0
};
在draw方法中,通过绑定不同的纹理来实现绘制不同的图片:
gl.glBindTexture(GL10.GL_TEXTURE_2D,textureId[witch]);//为画笔绑定指定ID纹理
4、动画效果控制
如前所述,要实现动画效果,其实就是不停地绘制不同的图片。在DrawLoading 类的构造函数里面,启用了一个线程,每隔100ms对witch进行递增,witch代表了要绘制哪一张图片。这样,在 onDrawFrame 重绘画面时,就会根据witch来渲染,动画效果就出来了。
public DrawLoading(int[] textureId)
{
this.textureId=textureId;
initVertexBuffer(); //根据col,row初始化顶点坐标
initTextureBuffer(); //初始化纹理顶点数据
if (!bThreadRun)//防止重复创建Thread
{
bThreadRun = true;
new Thread()
{
public void run()
{
while(true)
{
try
{
witch++;
if (witch >= 10) witch = 0;
Thread.sleep(100);//休息100ms
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
}.start();
}
}
最后的效果如下图: