【Android游戏开发二十二】(图文详解)游戏中灵活实现动画播放!

简介:

    由于写书的缘故,博文更新缓慢,大家体谅,今天针对群内常提出动画实现的问题来进行一个详细讲述;

    此章节适合没有做过游戏开发的同学学习!

    做过Android软件的童鞋们,在学习游戏开发的时候,思维总是被固定在了Android系统组件上!比如动画实现总想着利用BitmapDrawable、Animation等系统提供的类和方法来实现!

    其实在本人以前做J2me开发的时候,J2me Api从MIDP2.0开始提供和封装了Sprite类,通名:精灵类!这个类的几种构造的时候只需要提供图片的大小、宽高、等,就可以生成一个精灵了,因为精灵类提供了碰撞检测、动画播放等方法,让开发者在开发游戏中很是方便。那么其实在制作一些较为复杂的、或者网游开发中,公司内都不会利用这个精灵类来去做,抛开机型不说,因为每个公司都会有其引擎和各种编辑器等等、那么肯定需要扩展,如果利用sprite来开发不仅扩展不方便、不灵活之外而且和编辑器、引擎搭配开发也不适合。但是一般而言,精灵类足够用!但是一般还是利用MIDP1.0自定义完成这个2.0提供的Spirte类,这样更容易维护和自定义扩展!

    而且J2me提供的游戏开发包也是一个现成好用的引擎!所以这也可以理解为什么在Android游戏开发中,大家很多时候还总会看到Sprite类的影子!还有很多做过me的同学会看到类似的代码,总说“你这Android游戏开发不还是J2me的那套东西么!”,呵呵,没错,但是请童鞋们先想一下,Android现在SDK 升级到了2.3 了,有听说哪个版本中提供了类似meAPi中的“Game”专用于开发游戏的开发包?答案是肯定没有。而且能把自己在me中的游戏框架拿到android来,更快的进入开发也是很好的,当然这里不是推荐把j2me的那几个游戏扩展包直接拿来用,这种属于移植 - -。反而更加浪费游戏的效率!

    总结一句:不是大家不想抛开me的架构来做原生态的Android游戏!而是Android现在没有更好的适合游戏的开发包;

     不多说别的了,今天主要为各位童鞋讲解在游戏中如何实现动画!

     实现动画,我们一般都是自己去利用图片数组、切片的变换形成的动画。那么下面给大家简单介绍两种实现方式:

     第一种: 利用图片数组,不断改变画在画布上的图片数组下标,从而实现动画的形成!(每张图片是动画的一帧)

注意:下面这一段写的是演示代码!请自行整理; 

 

   
   
  1.  变量:  
  2.  Bitmap bmp0,bmp1,bmp2;  
  3.  Bitmap[] bmp_array = new Bitmap[3];  
  4.  int bmpIndex;  
  5.    
  6. 初始化中:  
  7. bmp0 = BitmapFaxxxxxxxx;  
  8. bmp1 = BitmapFaxxxxxxxx;  
  9. bmp2 = BitmapFaxxxxxxxx;  
  10. bmp_array[0] =bmp0;  
  11. bmp_array[1] =bmp1;  
  12. bmp_array[2] =bmp2;  
  13.       
  14. 画布中://一直在刷新画布  
  15. canvas.drawBitmap(bmp_array[bmpIndex]);  
  16.      
  17. 逻辑中: //线程中一直在执行逻辑  
  18. bmpIndex++;  
  19. if(bmpIndex>=bmp_array.length)  
  20.    bmpIndex = 0

 

     逻辑中一直让bmpIndex++,为了让图片数组下标能向着下一张图片索引,这样一来在画布中,就形成了动画了。

    有的童鞋说如何控制动画的播放速度呢?有的说改变线程的休眠时间!!?

    游戏开发中一般都只要一个线程来控制,那么如果你为了控制动画的快慢而轻率的去改变线程的休眠时间,那就大错特错了。我们不应该去动主线程的刷新时间(休眠时间)而是想着去针对动画去想办法,这样别的地方不会受到影响!

    一般情况下,刷新时间(线程休眠时间)很快,童鞋们肯定是嫌动画播放太快,那么我们可以自定义一个计时器。 比如我们定义一个变量去消耗掉一些时间!看以下代码:

    此段代码仍然是演示代码,请注意自行整理; 

 

   
   
  1.  变量:  
  2.  Bitmap bmp0,bmp1,bmp2;  
  3.  Bitmap[] bmp_array = new Bitmap[3];  
  4.  int bmpIndex;  
  5.  int time;  
  6. 初始化中:  
  7. bmp0 = BitmapFaxxxxxxxx;  
  8. bmp1 = BitmapFaxxxxxxxx;  
  9. bmp2 = BitmapFaxxxxxxxx;  
  10. bmp_array[0] =bmp0;  
  11. bmp_array[1] =bmp1;  
  12. bmp_array[2] =bmp2;  
  13.       
  14. 画布中://一直在刷新画布  
  15. canvas.drawBitmap(bmp_array[bmpIndex]);  
  16.      
  17. 逻辑中: //线程中一直在执行逻辑  
  18. time++;  
  19. if(time%10==0){  
  20.   bmpIndex++;  
  21. }  
  22. if(bmpIndex>=bmp_array.length)  
  23.    bmpIndex = 0

 

     这段代码和之前那一段唯一的差别就是新增加了一个变量 time ,我们假定我们刷新时间(线程休眠时间)为 100毫秒,那么time++;

    当if(time%10==0)成立的时候理论上肯定就是正好是一秒钟,【10(time)*100(线程休眠时间)=1000(正好1秒)】这样一来就OK,解决了!

     第二种:利用切片来实现动画;(所有帧数都放在同一张图片中)

开发过游戏的肯定很熟悉下面这两张图:

图1 : 

图2:

     图1,是个规则的帧数组成的一张图片,图2则是动作编辑器生成的图片。

    游戏中一般常用的是规则的如图1一样的图片,这样的图片比我们第一种实现动画的方式为内存剩下了不少,那么图2由动作编辑器生成的当然更省! 这里针对图2这个我就先不多讲了。因为关联到编辑器等、大家可以自行百度下;

     我们来看图1,如果经常看我博客的会发现图1很熟悉,嘿嘿,对的,这个是《【Android游戏开发之四】Android简单游戏框架》中一个人物行走的demo,第四章我讲解的是一个人物行走的demo,但是关于细节代码当时没有做特别注释和说明,今天正好用在这里,为各位童鞋详解讲解下:

 先上段代码: 


  
  
  1. /**  
  2.  *@author Himi  
  3.  *   
  4.     //为了让童鞋们更容易理解,我这里是把图片分割出来,  
  5.     //分为上下左右四个人物方向的数组  
  6.     private int animation_up[] = { 3, 4, 5 };      
  7.     private int animation_down[] = { 0, 1, 2 };      
  8.     private int animation_left[] = { 6, 7, 8 };      
  9.     private int animation_right[] = { 9, 10, 11 };   
  10. public void draw() {      
  11.         canvas = sfh.lockCanvas();      
  12.         canvas.drawRect(0, 0, SW, SH, p);    
  13.         canvas.save();    
  14.         canvas.drawText("Himi", bmp_x-2, bmp_y-10, p2);      
  15.          //这里的clipRect是设置可视区域,记得要 canvas.save();   canvas.restore();  
  16.         //如果不懂请看【Android游戏开发之四】 ,这里我主要介绍canvas.clipRect()   
  17.         //以及canvas.drawBitmap()两个方法中的几个参数!  
  18.         canvas.clipRect(bmp_x, bmp_y, bmp_x + bmp.getWidth() / 13, bmp_y+bmp.getHeight());   
  19.         //bmp_x:图片的x坐标  
  20.         //bmp_y:图片的y坐标  
  21.         //bmp_x + bmp.getWidth() / 13 :图片的x坐标+每一帧的宽度  
  22.         //bmp_y+bmp.getHeight()  :图片的y坐标+每一帧的高度   
  23.         if (animation_init == animation_up) {      
  24.             canvas.drawBitmap(bmp, bmp_x - animation_up[frame_count] * (bmp.getWidth() / 13), bmp_y, p);   
  25.             //bmp:有很多帧在一起的这张图片(图1)  
  26.             //bmp_x - animation_up[frame_count] * (bmp.getWidth() / 13) :  
  27.             //图片的x坐标 - 每一帧的X坐标(这里看备注1)  
  28.             //bmp_y:图片的y坐标  
  29.             //p:画笔  
  30.         } else if (animation_init == animation_down) {      
  31.             canvas.drawBitmap(bmp, bmp_x - animation_down[frame_count] * (bmp.getWidth() / 13), bmp_y, p);      
  32.         } else if (animation_init == animation_left) {      
  33.             canvas.drawBitmap(bmp, bmp_x - animation_left[frame_count] * (bmp.getWidth() / 13), bmp_y, p);      
  34.         } else if (animation_init == animation_right) {      
  35.             canvas.drawBitmap(bmp, bmp_x - animation_right[frame_count] * (bmp.getWidth() / 13), bmp_y, p);      
  36.         }      
  37.         canvas.restore();  //备注3    
  38.         sfh.unlockCanvasAndPost(canvas);      
  39.     }      
  40.     public void cycle() {      
  41.         if (DOWN) {      
  42.             bmp_y += 5;      
  43.         } else if (UP) {      
  44.             bmp_y -5;      
  45.         } else if (LEFT) {      
  46.             bmp_x -5;      
  47.         } else if (RIGHT) {      
  48.             bmp_x += 5;      
  49.         }      
  50.         if (DOWN || UP || LEFT || RIGHT) {      
  51.             if (frame_count < 2) {      
  52.                 frame_count++;      
  53.             } else {      
  54.                 frame_count = 0;      
  55.             }      
  56.         }      
  57.         if (DOWN == false && UP == false && LEFT == false && RIGHT == false) {      
  58.             frame_count = 0;      
  59.         }      
  60.     }     
  61.     */  

     备注1:解释为什么要 “图片的x坐标 - 每一帧的X坐标”:

大家先看下图:

 

    假设:我们现在把可视区域设定在(0,0)点,可是区域大小正好是图片每一帧的宽高;那么此时我们先在可视区域中显示下标为0的帧,我们只要把整张图片画在(0,0)即可,如上图中画的一样,现在只有第一帧能看到,那么我们如果想看第二张呢?当然是用图片的x坐标 - 每一帧的X坐标,就能看到下标为1的这一帧!如下图;  

     OK,这里我要强调一下:一定要理解这种思路,因为我们这里图1的高正好是每帧的高,可能以后有高宽都不一样!所以这里我在向大家介绍这种思路,千万要学以致用!!!OK,今天就讲到这,继续忙着写书啦。谢谢大家一直的支持!

 Thx everybody! 娃哈哈~










本文转自 xiaominghimi 51CTO博客,原文链接:http://blog.51cto.com/xiaominghimi/606930,如需转载请自行联系原作者
目录
相关文章
|
Android开发 开发者
Android利用SVG实现动画效果
本文介绍了如何在Android中利用SVG实现动画效果。首先通过定义`pathData`参数(如M、L、Z等)绘制一个简单的三角形SVG图形,然后借助`objectAnimator`实现动态的线条绘制动画。文章详细讲解了从配置`build.gradle`支持VectorDrawable,到创建动画文件、关联SVG与动画,最后在Activity中启动动画的完整流程。此外,还提供了SVG绘制原理及工具推荐,帮助开发者更好地理解和应用SVG动画技术。
599 30
|
Android开发 UED 计算机视觉
Android自定义view之线条等待动画(灵感来源:金铲铲之战)
本文介绍了一款受游戏“金铲铲之战”启发的Android自定义View——线条等待动画的实现过程。通过将布局分为10份,利用`onSizeChanged`测量最小长度,并借助画笔绘制动态线条,实现渐变伸缩效果。动画逻辑通过四个变量控制线条的增长与回退,最终形成流畅的等待动画。代码中详细展示了画笔初始化、线条绘制及动画更新的核心步骤,并提供完整源码供参考。此动画适用于加载场景,提升用户体验。
703 5
Android自定义view之线条等待动画(灵感来源:金铲铲之战)
|
API Android开发 开发者
Android颜色渐变动画效果的实现
本文介绍了在Android中实现颜色渐变动画效果的方法,重点讲解了插值器(TypeEvaluator)的使用与自定义。通过Android自带的颜色插值器ArgbEvaluator,可以轻松实现背景色的渐变动画。文章详细分析了ArgbEvaluator的核心代码,并演示了如何利用Color.colorToHSV和Color.HSVToColor方法自定义颜色插值器MyColorEvaluator。最后提供了完整的源码示例,包括ColorGradient视图类和MyColorEvaluator类,帮助开发者更好地理解和应用颜色渐变动画技术。
384 3
|
Android开发 开发者
Android SVG动画详细例子
本文详细讲解了在Android中利用SVG实现动画效果的方法,通过具体例子帮助开发者更好地理解和应用SVG动画。文章首先展示了动画的实现效果,接着回顾了之前的文章链接及常见问题(如属性名大小写错误)。核心内容包括:1) 使用阿里图库获取SVG图形;2) 借助工具将SVG转换为VectorDrawable;3) 为每个路径添加动画绑定属性;4) 创建动画文件并关联SVG;5) 在ImageView中引用动画文件;6) 在Activity中启动动画。文末还提供了完整的代码示例和源码下载链接,方便读者实践操作。
568 65
|
存储 Shell Android开发
基于Android P,自定义Android开机动画的方法
本文详细介绍了基于Android P系统自定义开机动画的步骤,包括动画文件结构、脚本编写、ZIP打包方法以及如何将自定义动画集成到AOSP源码中。
1027 2
基于Android P,自定义Android开机动画的方法
|
XML Java Maven
Android线条等待动画JMWorkProgress(可添加依赖直接使用)
这是一篇关于Android线条等待动画JMWorkProgress的教程文章,作者计蒙将其代码开源至GitHub,提升可读性。文章介绍了如何通过添加依赖库使用该动画,并详细讲解了XML与Java中的配置方法,包括改变线条颜色、宽度、添加文字等自定义属性。项目已支持直接依赖集成(`implementation &#39;com.github.Yufseven:JMWorkProgress:v1.0&#39;`),开发者可以快速上手实现炫酷的等待动画效果。文末附有GitHub项目地址,欢迎访问并点赞支持!
375 26
|
XML Android开发 数据格式
Android中SlidingDrawer利用透明动画提示效果
本文介绍了在Android中使用`SlidingDrawer`实现带有透明动画提示效果的方法。通过XML布局配置`SlidingDrawer`的把手(handle)和内容(content),结合Activity中的代码实现动态动画效果。最终实现了交互性强、视觉效果良好的滑动抽屉功能。
169 1
Android中SlidingDrawer利用透明动画提示效果
|
XML Java Android开发
Android 动画之帧动画 + 补间动画 + 属性动画
本文介绍了Android开发中的三种动画类型:帧动画、补间动画和属性动画。帧动画通过依次播放一系列静态图片实现动态效果,支持Java代码与XML两种实现方式。补间动画基于起始和结束位置自动生成过渡效果,涵盖透明度、位移、旋转、缩放及组合动画等多种形式,并可搭配插值器优化动画过程。属性动画则通过改变对象属性实现动画,支持透明度、位移、旋转、缩放及组合动画,灵活性更高且适用于更复杂的场景。文中提供了详细的代码示例,帮助开发者快速上手。
581 15
|
Android开发 开发者
Android自定义view之围棋动画(化繁为简)
本文介绍了Android自定义View的动画实现,通过两个案例拓展动态效果。第一个案例基于`drawArc`方法实现单次动画,借助布尔值控制动画流程。第二个案例以围棋动画为例,从简单的小球直线运动到双向变速运动,最终实现循环动画效果。代码结构清晰,逻辑简明,展示了如何化繁为简实现复杂动画,帮助读者拓展动态效果设计思路。文末提供完整源码,适合初学者和进阶开发者学习参考。
226 0
Android自定义view之围棋动画(化繁为简)

热门文章

最新文章