`

android实现动画效果的方法onDrawFrame

阅读更多
在android中,要实现动画效果,要么通过循环调用canvas.draw系统方法,要么通过调用opengl es中的GLSurfaceView.Renderer实现方法onDrawFrame方法。
canvas画图确实要简单得多,但要实现更好的性能最好还是调用opengl方法,因为它的性能相对来说要好一些。
实现动画的关键就是实现GLSurfaceView.Renderer接口内的方法,最重要的一个就是onDrawFrame,这个方法大体的原理是开起一个线程,在此线程内不断的调用onDrawFrame,以实现动画效果。因此onDrawFrame的主要作用就是将不同的图片显示出来就可以了。
在此先谈一个额外的话题,那就是怎么去控制onDrawFrame调用的频率,比如1秒钟执行几次?从本人找到的资料看,还没有谁这么做过,细节情况则取决于GLSurfaceView这个类的实现,但这类相当复杂,看了一下没有看懂,最后就放弃了。但我可以知道每秒执行了多少次吧?这个功能可以自己实现,而且还比较简单,先写一个实现类:
public class FPSCounter {
    long startTime = System.nanoTime();
    int frames = 0;
    
   /**
    * 计算每秒执行了多少次
    */
    public void logFrame() {
        frames++;
        if(System.nanoTime() - startTime >= 1000000000) {
            Log.d("FPSCounter", "fps: " + frames);
            frames = 0;
            startTime = System.nanoTime();
        }
    }
}


然后在onDrawFrame中调用即可。
经过上述操作后就可以在日志文件中查看到每秒钟会执行多少次onDrawFrame方法了。

至于怎么在onDrawFrame方法中实现动画效果这个可能相对来说要麻烦一点,比如拿上一篇博客中的jumper为例,作者自已实现了一个动画类:
public class Animation {
    public static final int ANIMATION_LOOPING = 0;
    public static final int ANIMATION_NONLOOPING = 1;
    
    final TextureRegion[] keyFrames;
    final float frameDuration;
    
    public Animation(float frameDuration, TextureRegion ... keyFrames) {
        this.frameDuration = frameDuration;
        this.keyFrames = keyFrames;
    }
    
    public TextureRegion getKeyFrame(float stateTime, int mode) {
        int frameNumber = (int)(stateTime / frameDuration);
        
        if(mode == ANIMATION_NONLOOPING) {
            frameNumber = Math.min(keyFrames.length-1, frameNumber);            
        } else {
            frameNumber = frameNumber % keyFrames.length;
        }        
        return keyFrames[frameNumber];
    }
}

这个类中有两个主要的参数,keyFrames用于存储动画播放的连续图片,而frameDuration则用于图片更新的时间间隔。而getKeyFrame则根据不同的时间取出不同的图片,然后onDrawFrame调用getKeyFrame方法获得图片将其画出,这样就实现了游戏的单个角色的动画效果。具体实现可见上一篇博客中的jumper代码。

游戏确实是一张一张图画上去的,但要通过opengl来画,却还有些规则,这也是opengl难用的主要原因-----规则太多。举个简单点的例子,如高分排行榜,除了先画个游戏背景外,还得在背景下画些数字出来,则就会用到两种不同的显示设置:
public void present(float deltaTime) {
        GL10 gl = glGraphics.getGL();        
        gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
        guiCam.setViewportAndMatrices();
        
        gl.glEnable(GL10.GL_TEXTURE_2D);
        
        batcher.beginBatch(Assets.background);
        batcher.drawSprite(160, 240, 320, 480, Assets.backgroundRegion);
        batcher.endBatch();
        
        gl.glEnable(GL10.GL_BLEND);
        gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
        
        batcher.beginBatch(Assets.items);
        batcher.drawSprite(160, 360, 300, 33, Assets.highScoresRegion);
        
        float y = 240;
        for(int i = 4; i >= 0; i--) {
            Assets.font.drawText(batcher, highScores[i], xOffset, y);
            y += Assets.font.glyphHeight;
        }
        
        batcher.drawSprite(32, 32, 64, 64, Assets.arrow);
        batcher.endBatch();
        
        gl.glDisable(GL10.GL_BLEND);
    }

可以看到,画背景时使用的是GL10.GL_TEXTURE_2D模式,而在背景上画文字或角色时使用融合模式GL10.GL_BLEND。

关于游戏画面及动画的主要部分就是这些了,opengl 里面的需要注意的东西还很多,以后有时间的话再讲讲其它方面的。
分享到:
评论

相关推荐

    Android opengl渲染yuv420例子

    Android下使用OpenGL渲染yuv420p图像并显示。例子中提供了两种类型,一种使用GLSurfaceView在onDrawframe中调用native方法绘制,另外一种使用EGL,直接在native层完成渲染和显示功能。

    Android下Opengl ES

    Android下Opengl ES导引 -第一部分 设置OpenGL ES观察 GLSurfaceView GLSurfaceView.Renderer onSurfaceCreated onDrawFrame onSurfaceChanged 把这些都穿连到一起 全屏显示 -第二部分 建立多边形 ...

    Self_CameraSquare:正方形预览的Camera,纯java实现,通过GLSurfaceView实现

    使用GLSurfaceView实现预览,在onDrawFrame()中对SurfaceView的尺寸做裁剪。 更改hal层config.ftbl.common_raw.h文件,由驱动层处理。 以MIUI9 拥有的方形预览为例,接下来分析各种方法的实现: ##1.使用遮罩,盖住...

    Android下Opengl ES导引

    onDrawFrame onSurfaceChanged 把这些都穿连到一起 全屏显示 -第二部分 建立多边形 顶点(Vertex) 边(Edge) 面(Face) 顺序的关系 多边形(Polygon) 演播器(Render) 什么是演播的原始风格...

    cube-rotation:在 OpenGL 中相对于世界坐标旋转立方体

    立方体旋转在 OpenGL 中相对于世界坐标旋转立方体顶点/片段着色器在res.raw CubeSurfaceView包含渲染立方体的渲染器。 此类还处理用于操作多维数据集的触摸事件。... onDrawFrame()是绘制发生的地方。

    opengl教程

    onSurfaceCreated、onDrawFrame、onSurfaceChanged

    opengl es2.0 -YUV-RGB互转+显示到手机屏幕 DEMO

    opengl es2.0 读取位图 先用opengl转换成yuv然后再转回rgb最后输出到显示屏上

    GLSurfaceView 线程交互 queueEvent

    GLSurfaceView.Renderer 有三个方法: onSurfaceCreated() :在开始渲染的时候被调用,无论什么...onDrawFrame():每帧的时候该方法都会被调用,这个用于画场景是可靠的。你完全可以通过调用glClear方法开清楚帧缓存

Global site tag (gtag.js) - Google Analytics