相信有Android手机的人都玩过一款Kuba的游戏(没玩过的我推荐去玩一下),里面用手指接触到屏幕后产生的爆炸效果确实增加了游戏的不少色彩。那么这个是怎么做出来的呢?
很明显,这个效果应该是一个动画序列图实现的,即Frame-by-Frame动画。Android实现Frame-by-Frame动画我会的有两种方法:
1、animation-list配置,预先将一个动画按照每帧分解成的多个图片所组成的序列。然后再在Android的配置文件中将这些图片配置到动画里面。
<animation-list xmlns:android="http://schemas.android.com/apk/res/android"
android:oneshot="false">
<item android:drawable="@drawable/explode1" android:duration="50" />
<item android:drawable="@drawable/explode2" android:duration="50" />
<item android:drawable="@drawable/explode3" android:duration="50" />
<item android:drawable="@drawable/explode4" android:duration="50" />
</animation-list>
但是由此带来的不便也是显而易见的:drawable目录下拥挤了过多的动画帧文件。如果游戏大起来,动画效果丰富,那么drawable目录下将拥有数量庞大的图片文件,这将是开发人员的灾难(见下图)。
2、AnimationDrawable动画。其实我们发现,我们完全可以将同一动画序列的每帧图片都合并到一个大的图片中去,然后读取图片的时候按照约定好的宽、高去读就能准确的将该帧图片精确的读出来了。下图是小雪行走序列图。
将序列图读出并且转化为动画的核心代码为
animationDrawable = new AnimationDrawable();
Bitmap[] bitmaps = new Bitmap[PlayerConst.PLAYER_XIAOXUE_WALK_FRAME];
for (int frame = 0; frame < bitmaps.length; frame++) {
Bitmap bitmap = Bitmap.createBitmap(xiaoxueWalkSerBitmap,
frame*PlayerConst.PLAYER_XIAOXUE_WALK_WIDTH,
lay*PlayerConst.PLAYER_XIAOXUE_WALK_HEIGHT,
PlayerConst.PLAYER_XIAOXUE_WALK_WIDTH,
PlayerConst.PLAYER_XIAOXUE_WALK_HEIGHT);
animationDrawable.addFrame(new BitmapDrawable(bitmap),100);
}// for,每层有 PLAYER_XIAOXUE_WALK_FRAME 帧
animationDrawable.setOneShot(false);
setBackgroundDrawable(animationDrawable);
具体例子可以从附件中找到。
3、SurfaceView动画。也许你很快就发现,前两个动画都必须依赖View才能展示,并且每个View只能展示一个动画。而在游戏中不可能只有一动画,更恐怖的是很多动画都是随机产生的,并不是事先约定好的,而动态创建/删除View的代价非常高,并不适合做高性能的游戏。这个时候你需要的是SurfaceView。
在SurfaceView中的动画有一点是和前边两种动画有区别的:那就是画布上所有的一切都必须自己亲自打理。在前边几个基于Animation的动画你只需关心当前动画的序列即可,其他都由系统帮你处理完毕。而在SurfaceView中,你就是那个处理程序,所有的一切包括背景都必须有你来亲自打理。
为此我写了一个框架专门来处理这个琐事,框架只有两个类:AnimationDraw和DrawRunning。其中AnimationDraw则是一个动画类,它负责描述当前动画元素的位置、当前播放到第几帧、每帧的延时是多少、是否重复播放等。
import java.util.Date;
import android.graphics.Bitmap;
/**
* 动画绘画元素
* @author vlinux
*
*/
public class AnimationDraw {
protected float x;
protected float y;
protected Bitmap[] bitmaps;
protected long duration;
protected Long lastBitmapTime;
protected int step;
protected boolean repeat;
/**
* 动画构造函数-for静态图片
* @param x:X坐标<br/>
* @param y:Y坐标<br/>
* @param bitmap:显示的图片<br/>
* @param duration:图片显示的时间<br/>
*/
public AnimationDraw(float x, float y, Bitmap bitmap, long duration) {
Bitmap[] bitmaps = {bitmap};
this.x = x;
this.y = y;
this.bitmaps = bitmaps;
this.duration = duration;
this.repeat = true;
lastBitmapTime = null;
step = 0;
}
/**
* 动画构造函数
* @param x:X坐标<br/>
* @param y:Y坐标<br/>
* @param bitmap:显示的图片<br/>
* @param duration:图片显示的时间<br/>
* @param repeat:是否重复动画过程<br/>
*/
public AnimationDraw(float x, float y, Bitmap[] bitmaps, long duration, boolean repeat) {
this.x = x;
this.y = y;
this.bitmaps = bitmaps;
this.duration = duration;
this.repeat = repeat;
lastBitmapTime = null;
step = 0;
}
public Bitmap nextFrame() {
if (step >= bitmaps.length) {
// 判断step是否越界
if( !repeat ) {
return null;
} else {
lastBitmapTime = null;
}//if
}// if
if (null == lastBitmapTime) {
// 第一次执行
lastBitmapTime = new Date().getTime();
return bitmaps[step = 0];
}// if
// 第X次执行
long nowTime = System.currentTimeMillis();
if (nowTime - lastBitmapTime <= duration) {
// 如果还在duration的时间段内,则继续返回当前Bitmap
// 如果duration的值小于0,则表明永远不失效,一般用于背景
return bitmaps[step];
}// if
lastBitmapTime = nowTime;
return bitmaps[step++];// 返回下一Bitmap
}
public float getX() {
return x;
}
public float getY() {
return y;
}
}
DrawRunning则是一个负责画图的线程,它是程序的核心。
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
/**
* 绘画线程
*
* @author vlinux
*
*/
public class DrawRunning implements Runnable {
private List<AnimationDraw> animationDraws;//所有需要画动画的集合
private List<AnimationDraw> buffers;//缓存前台传入需要展示的动画
private SurfaceHolder surfaceHolder;
private boolean running;
public DrawRunning(SurfaceHolder surfaceHolder) {
this.surfaceHolder = surfaceHolder;
animationDraws = new ArrayList<AnimationDraw>();
buffers = new ArrayList<AnimationDraw>();
running = true;
}
@Override
public void run() {
// TODO Auto-generated method stub
while (running) {
synchronized (surfaceHolder) {
Canvas canvas = null;
try {
canvas = surfaceHolder.lockCanvas(null);
doDraw(canvas);
} finally {
if (null != canvas) {
surfaceHolder.unlockCanvasAndPost(canvas);
}// if
}// try
}// syn
}// while
}
private void doDraw(Canvas canvas) {
synchronized(this) {
//检查缓存中是否有需要加入的动画
if( !buffers.isEmpty() ) {
animationDraws.addAll(buffers);//加入animationDraws
buffers.clear();//清空缓存
}//if
}//syn
if( animationDraws.isEmpty() ) {
return;//如果animationDraws里面是空的那就不用画了
}//if
//---这里开始绘画
Iterator<AnimationDraw> bombIt = animationDraws.iterator();
while (bombIt.hasNext()) {
AnimationDraw bomb = bombIt.next();
Bitmap nextFrame = bomb.nextFrame();
if (null == nextFrame) {
//下一Frame为null,说明动画序列已经结束
//该动画已经完成,从动画集合中删除
bombIt.remove();
continue;//while
}// if
canvas.drawBitmap(nextFrame, bomb.getX(), bomb.getY(), null);
}// while
}
public void addAnimationDraw(AnimationDraw bomb) {
synchronized(this) {
//尽量减少这个的同步响应时间,因为这个方法是前台响应的
//多0.1秒都会直接反应到用户感知
buffers.add(bomb);//将需要显示动画的内容加入到缓存
}//syn
}
public void stopDrawing() {
running = false;
}
}
值得注意的是,我用了一个缓存和两个synchronized来提高前台的响应以及确保对集合类、SurfaceHolder的正确操作。
例子可以见附件。
- 大小: 8 KB
- 描述: 小雪行走序列图
- 大小: 38 KB
分享到:
相关推荐
在Android开发中,帧动画(Frame Animation)是一种常见的动态效果实现方式,尤其在用户界面设计中,能够增加应用的互动性和吸引力。帧动画是通过连续播放一系列静态图像来创建动态效果,类似于传统的电影制作原理。...
在Android开发中,帧动画(Frame Animation)是一种常见的动态效果实现方式,它通过连续播放一系列静态图像来模拟连续动作,类似于传统的电影制作原理。在本示例中,“Android帧动画demo”将展示如何在Android应用中...
Frame动画是Android中用于创建序列动画的一种方法,类似于传统的电影制作,通过连续播放多帧静态图片来形成连续的视觉效果。与Tween动画不同,Tween动画是通过对对象属性(如平移、旋转、缩放等)进行平滑过渡来实现...
Frame动画基于一系列连续的静态图像,每张图像是动画中的一个帧,通过快速连续播放这些帧,人眼会将它们融合成动态画面,形成连续的动画效果。在Android中,我们可以使用`AnimationDrawable`类来实现Frame动画。 **...
在Android开发中,帧动画(Frame Animation)是一种常见的动画效果,它通过连续播放一系列静态图像来模拟动态效果。本文将深入探讨如何在Android项目中应用帧动画,包括使用`AnimationDrawable`和`ImageView`实现这...
在Android平台上,动画是应用程序中不可或缺的一部分,可以增强用户体验并为用户提供吸引人的视觉效果。其中,"逐帧动画"(Frame Animation)是一种简单且常用的技术,适用于创建一系列连续的静态图像来模拟动态效果...
在Android开发中,动画是提升用户体验的关键因素之一。帧动画(Frame Animation)是Android提供的一种简单而直观的动画实现方式,适用于实现一系列静态图片按顺序播放的效果,类似于传统的动画胶片。本篇将深入探讨...
通过阅读“Android 游戏开发之使用AnimationDrable实现Frame动画”相关资料,你可以深入理解`AnimationDrawable`的工作原理,并学习如何将其应用到实际项目中。而`Drawableframe`可能包含了具体的帧动画图片资源,...
在本文中,我们将深入探讨Android中的Frame动画,并通过源码分析了解其实现原理。 首先,让我们理解一下什么是Frame动画。在Android中,Frame动画是由`AnimationDrawable`类实现的。这个类是一个可绘制对象,可以...
在Android开发中,动画是提升用户体验的关键因素,它能让应用变得更加生动有趣。本文将深入探讨两种主要的动画类型:帧动画(Frame Animation)和补间动画(Tween Animation),并提供相应的代码实现示例。 帧动画...
首先,我们要知道在Android中,动画主要分为两种类型:补间动画(Tween Animation)和帧动画(Frame Animation)。抖动动画属于补间动画的一种,因为它涉及到对象的位置、大小或透明度等属性的变化。补间动画是通过...
在Android开发中,动画是提升用户体验的关键因素之一。Android提供了两种主要类型的动画:Frame Animation(帧动画)和Tween Animation(补间动画)。本篇将深入探讨这两种动画的原理、使用方式以及源码分析。 **一...
在Android开发中,动画是提升用户体验的关键因素之一。"android气泡动画实现"是指在Android应用中创建一种独特的视觉效果,即用户点击屏幕任意位置后,该位置会呈现出气泡爆炸的效果。这种动画通常用于吸引用户的...
总结一下,本项目中的"简单的Frame动画"展示了如何使用Android的`AnimationDrawable`来创建一个由6张图片组成的帧动画。在实际开发中,开发者可以根据需求调整图片数量、帧间隔时间,以及如何在代码中控制动画的播放...
Frame动画在Android开发中是一种常见的动画形式,它主要用于创建序列帧动画,比如常见的 GIF 图片效果。这种动画机制是通过连续显示一系列预先定义好的图片来实现动态效果的。本篇文章将深入探讨Frame动画的工作原理...
这篇博文"玩转Android---2D图形及动画---Frame动画"显然会深入探讨如何在Android平台上创建和管理帧动画。帧动画是一种将一系列静态图像连续播放以产生动态效果的技术,常见于游戏和应用程序中的过渡效果。 首先,...
在Android开发中,序列帧动画(Frame Animation)是一种常见的动态效果实现方式,它通过连续播放一系列静态图片来创建动画效果,类似于电影胶片的工作原理。本Demo主要关注如何在Android中实现序列帧动画,并添加...
在Android开发中,帧动画(Frame-by-Frame Animation)是一种常用的技术,用于创建连续的图像序列,模拟视频或gif动图的效果。这种动画通常适用于简单的移动、旋转或渐变效果,比如按钮按下反馈、加载指示器等。接...
在Android开发中,帧动画(Frame Animation)是一种常见的动态效果实现方式,它通过连续播放一系列静态图片来模拟动画效果。这种技术尤其适用于那些不需要复杂交互和高性能要求的简单动画场景。接下来,我们将深入...