linux shell google Windows java 程序员 apache 微软 Firefox Ubuntu php nginx 编程 Python 开源 wordpress mysql centos Android 云计算

【ANDROID遊戲開發二十二】(圖文詳解)遊戲中靈活實現動畫播放!簡述J2ME的遊戲類庫與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

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

变量:  

Bitmap bmp0,bmp1,bmp2;  

Bitmap[] bmp_array = new Bitmap[3];  

int bmpIndex;  

  

初始化中:  

bmp0 = BitmapFaxxxxxxxx;  

bmp1 = BitmapFaxxxxxxxx;  

bmp2 = BitmapFaxxxxxxxx;  

bmp_array[0] =bmp0;  

bmp_array[1] =bmp1;  

bmp_array[2] =bmp2;  

      

画布中://一直在刷新画布  

canvas.drawBitmap(bmp_array[bmpIndex]);  

    

逻辑中: //线程中一直在执行逻辑  

bmpIndex++;  

if(bmpIndex>=bmp_array.length)  

   bmpIndex = 0;

邏輯中一直讓bmpIndex++,為了讓圖片數組下標能向著下一張圖片索引,這樣一來在畫布中,就形成了動畫了。

有的童鞋說如何控制動畫的播放速度呢?有的說改變線程的休眠時間!!?

遊戲開發中一般都只要一個線程來控制,那麽如果你為了控制動畫的快慢而輕率的去改變線程的休眠時間,那就大錯特錯了。我們不應該去動主線程的刷新時間(休眠時間)而是想著去針對動畫去想辦法,這樣別的地方不會受到影響!

一般情況下,刷新時間(線程休眠時間)很快,童鞋們肯定是嫌動畫播放太快,那麽我們可以自定義一個計時器。 比如我們定義一個變量去消耗掉一些時間!看以下代碼:

此段代碼仍然是演示代碼,請註意自行整理;

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

变量:  

Bitmap bmp0,bmp1,bmp2;  

Bitmap[] bmp_array = new Bitmap[3];  

int bmpIndex;  

int time;  

初始化中:  

bmp0 = BitmapFaxxxxxxxx;  

bmp1 = BitmapFaxxxxxxxx;  

bmp2 = BitmapFaxxxxxxxx;  

bmp_array[0] =bmp0;  

bmp_array[1] =bmp1;  

bmp_array[2] =bmp2;  

      

画布中://一直在刷新画布  

canvas.drawBitmap(bmp_array[bmpIndex]);  

    

逻辑中: //线程中一直在执行逻辑  

time++;  

if(time%10==0){  

  bmpIndex++;  

}  

if(bmpIndex>=bmp_array.length)  

   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

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

/**

*@author Himi

*  

    //为了让童鞋们更容易理解,我这里是把图片分割出来,

    //分为上下左右四个人物方向的数组

    private int animation_up[] = { 3, 4, 5 };    

    private int animation_down[] = { 0, 1, 2 };    

    private int animation_left[] = { 6, 7, 8 };    

    private int animation_right[] = { 9, 10, 11 };  

public void draw() {    

        canvas = sfh.lockCanvas();    

        canvas.drawRect(0, 0, SW, SH, p);  

        canvas.save();  

        canvas.drawText("Himi", bmp_x-2, bmp_y-10, p2);    

         //这里的clipRect是设置可视区域,记得要 canvas.save();   canvas.restore();

        //如果不懂请看【Android游戏开发之四】 ,这里我主要介绍canvas.clipRect()  

        //以及canvas.drawBitmap()两个方法中的几个参数!

        canvas.clipRect(bmp_x, bmp_y, bmp_x + bmp.getWidth() / 13, bmp_y+bmp.getHeight());  

        //bmp_x:图片的x坐标

        //bmp_y:图片的y坐标

        //bmp_x + bmp.getWidth() / 13 :图片的x坐标+每一帧的宽度

        //bmp_y+bmp.getHeight()  :图片的y坐标+每一帧的高度  

        if (animation_init == animation_up) {    

            canvas.drawBitmap(bmp, bmp_x - animation_up[frame_count] * (bmp.getWidth() / 13), bmp_y, p);  

            //bmp:有很多帧在一起的这张图片(图1)

            //bmp_x - animation_up[frame_count] * (bmp.getWidth() / 13) :

            //图片的x坐标 - 每一帧的X坐标(这里看备注1)

            //bmp_y:图片的y坐标

            //p:画笔

        } else if (animation_init == animation_down) {    

            canvas.drawBitmap(bmp, bmp_x - animation_down[frame_count] * (bmp.getWidth() / 13), bmp_y, p);    

        } else if (animation_init == animation_left) {    

            canvas.drawBitmap(bmp, bmp_x - animation_left[frame_count] * (bmp.getWidth() / 13), bmp_y, p);    

        } else if (animation_init == animation_right) {    

            canvas.drawBitmap(bmp, bmp_x - animation_right[frame_count] * (bmp.getWidth() / 13), bmp_y, p);    

        }    

        canvas.restore();  //备注3  

        sfh.unlockCanvasAndPost(canvas);    

    }    

    public void cycle() {    

        if (DOWN) {    

            bmp_y += 5;    

        } else if (UP) {    

            bmp_y -= 5;    

        } else if (LEFT) {    

            bmp_x -= 5;    

        } else if (RIGHT) {    

            bmp_x += 5;    

        }    

        if (DOWN || UP || LEFT || RIGHT) {    

            if (frame_count < 2) {    

                frame_count++;    

            } else {    

                frame_count = 0;    

            }    

        }    

        if (DOWN == false && UP == false && LEFT == false && RIGHT == false) {    

            frame_count = 0;    

        }    

    }    

    */

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

大家先看下图:

假設:我們現在把可視區域設定在(0,0)點,可是區域大小正好是圖片每一幀的寬高;那麽此時我們先在可視區域中顯示下標為0的幀,我們只要把整張圖片畫在(0,0)即可,如上圖中畫的一樣,現在只有第一幀能看到,那麽我們如果想看第二張呢?當然是用圖片的x坐標 – 每一幀的X坐標,就能看到下標為1的這一幀!如下圖;

 

OK,這裏我要強調一下:一定要理解這種思路,因為我們這裏圖1的高正好是每幀的高,可能以後有高寬都不一樣!所以這裏我在向大家介紹這種思路,千萬要學以致用!!!OK,今天就講到這,繼續忙著寫書啦。謝謝大家一直的支持!

延伸阅读

    评论