Android App中使用SurfaceView制作多线程动画的实例讲解

2019-12-10 18:06:09王冬梅

精灵类主要是根据当前位置判断行走的方向,然后根据行走的方向更新精灵的位置,再绘制自身的动画。由于精灵的动画是一帧一帧的播放图片,所以这里封装了FrameAnimation.java,源码如下:

public class FrameAnimation{
  /**动画显示的需要的资源 */
  private Bitmap[] bitmaps;
  /**动画每帧显示的时间 */
  private int[] duration;
  /**动画上一帧显示的时间 */
  protected Long lastBitmapTime;
  /**动画显示的索引值,防止数组越界 */
  protected int step;
  /**动画是否重复播放 */
  protected boolean repeat;
  /**动画重复播放的次数*/
  protected int repeatCount;
 
  /**
   * @param bitmap:显示的图片<br/>
   * @param duration:图片显示的时间<br/>
   * @param repeat:是否重复动画过程<br/>
   */
  public FrameAnimation(Bitmap[] bitmaps, int duration[], boolean repeat) {
    this.bitmaps = bitmaps;
    this.duration = duration;
    this.repeat = repeat;
    lastBitmapTime = null;
    step = 0;
  }
 
  public Bitmap nextFrame() {
    // 判断step是否越界
    if (step >= bitmaps.length) {
      //如果不无限循环
      if( !repeat ) {
        return null;
      } else {
        lastBitmapTime = null;
      }
    }
 
    if (null == lastBitmapTime) {
      // 第一次执行
      lastBitmapTime = System.currentTimeMillis();
      return bitmaps[step = 0];
    }
 
    // 第X次执行
    long nowTime = System.currentTimeMillis();
    if (nowTime - lastBitmapTime <= duration[step]) {
      // 如果还在duration的时间段内,则继续返回当前Bitmap
      // 如果duration的值小于0,则表明永远不失效,一般用于背景
      return bitmaps[step];
    }
    lastBitmapTime = nowTime;
    return bitmaps[step++];// 返回下一Bitmap
  }
 
}

FrameAnimation根据每一帧的显示时间返回当前的图片帧,若没有超过指定的时间则继续返回当前帧,否则返回下一帧。
接下来需要做的是让Activty显示的View为我们之前创建的GameView,然后设置全屏显示。

public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
 
   getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
       WindowManager.LayoutParams.FLAG_FULLSCREEN);
   requestWindowFeature(Window.FEATURE_NO_TITLE);
   getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON,
       WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
 
   DisplayMetrics outMetrics = new DisplayMetrics();
   this.getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
   GameSurfaceView.SCREEN_WIDTH = outMetrics.widthPixels;
   GameSurfaceView.SCREEN_HEIGHT = outMetrics.heightPixels;
   GameSurfaceView gameView = new GameSurfaceView(this);
   setContentView(gameView);
 }