天天看點

超級瑪麗制作揭秘14爆炸效果,金币

 大家的支援就是我的動力。

子彈每次攻擊到效果,都會顯示一個爆炸效果。隻涉及圖檔顯示,它的結構很簡單。如下:

struct MapObject

{

 int x;

 int y;

 int w;

 int h;

 int id;

 int iframe;

 int iframemax;//最大幀數

 int show; //是否顯示

};

存儲問題。

爆炸效果仍然使用數組加遊标的方法,如下:

 struct MapObject BombArray[MAX_MAP_OBJECT];

 int iBombNum;

生成。

當子彈和小怪碰撞後,生成。

函數:void GAMEMAP::ClearEnemy(int i)

代碼部分:

 //生成

BombArray[iBombNum].show=1;

 BombArray[iBombNum].id=ID_ANI_BOMB;

 BombArray[iBombNum].iframe=0;

 BombArray[iBombNum].x=MapEnemyArray[i].x-BOMB_XOFF;

 BombArray[iBombNum].y=MapEnemyArray[i].y-BOMB_YOFF;

 //修改數組遊标

 iBombNum=(iBombNum+1)%MAX_MAP_OBJECT;

顯示。

和子彈、小怪的顯示方法相同。

函數:void GAMEMAP::ShowAniObj(MYANIOBJ & bmobj)

代碼部分:

 for(i=0;i<MAX_MAP_OBJECT;i++)

 {

  if (BombArray[i].show)

  {

   ystart=BombArray[i].y;

   xstart=BombArray[i].x;

   bmobj.DrawItem(xstart,ystart,BombArray[i].id, BombArray[i].iframe); 

  }

 }

幀重新整理。

和子彈、小怪的幀重新整理方法相同。

函數:void GAMEMAP::ChangeFrame(int itimeclip)

代碼部分:

for(i=0;i<MAX_MAP_OBJECT;i++)

 {

  if(BombArray[i].show)

  {

   BombArray[i].iframe++;

//當第四張圖檔顯示完畢,設定為不可見。

   if(BombArray[i].iframe>3)

   {

    BombArray[i].show=0;

   }

  } 

 }

碰撞檢測:爆炸效果不涉及碰撞檢測。

消失:如上所述,爆炸效果在動畫結束後消失。

金币。

金币的處理比小怪更簡單。當玩家和金币碰撞後,金币消失,增加金錢數量。

存儲問題。

用數組加遊标的方法(下一個版本中封裝起來),如下:

 struct MapObject MapCoinArray[MAX_MAP_OBJECT];

 int iCoinNum;

金币的生成。

和小怪相似,從地圖檔案中加載。以第二關為例,地圖檔案中的金币資料是:

6 5 32 32 3    

7 5 32 32 3    

8 5 32 32 3    

9 5 32 32 3    

18 4 32 32 3   

19 4 32 32 3   

20 4 32 32 3

資料依次表示橫坐标,縱坐标,寬,高,圖檔id

函數:int GAMEMAP::LoadMap()

代碼部分:

 while(temp[0]!='#' && !feof(fp))

 {

  sscanf(temp,"%d %d %d %d %d",

   &MapCoinArray[i].x,

   &MapCoinArray[i].y,

   &MapCoinArray[i].w,

   &MapCoinArray[i].h,

   &MapCoinArray[i].id);   

  MapCoinArray[i].show=1;

  MapCoinArray[i].iframe=0;

  //坐标轉換,乘以32

  MapCoinArray[i].x*=32;

  MapCoinArray[i].y*=32;

  //設定這個動畫元件的最大幀

  switch(MapCoinArray[i].id)

  {

  case ID_ANI_COIN:

   MapCoinArray[i].iframemax=4;

   break;

  }

  i++;

  iCoinNum++;

  //讀取下一行資料

  FGetLineJumpCom(temp,fp); 

 }

金币顯示:

和小怪的顯示方法相同.

函數:void GAMEMAP::ShowAniObj(MYANIOBJ & bmobj)

代碼:

 //顯示金币,和其他物品

 for(i=0;i<iCoinNum;i++)

 {

  ystart=MapCoinArray[i].y;

  xstart=MapCoinArray[i].x;

  bmobj.DrawItem(xstart,ystart,MapCoinArray[i].id, MapCoinArray[i].iframe); 

 }

金币幀重新整理:

和小怪的幀重新整理方法相同.

函數:void GAMEMAP::ChangeFrame(int itimeclip)

代碼:

 for(i=0;i<MAX_MAP_OBJECT;i++)

  {

   //如果金币可見,幀加一

   if(MapCoinArray[i].show)

   {       MapCoinArray[i].iframe=(MapCoinArray[i].iframe+1)%MapCoinArray[i].iframemax;

   }

  }

金币碰撞檢測:

和小怪的碰撞檢測方法相似,差別在于:金币的碰撞檢測沒有判斷是否可見,隻要金币位于螢幕中,和玩家碰撞,則金币消失,金錢數量iMoney增加。

函數:int GAMEMAP::CheckAni(int itimeclip)

代碼:

 for(i=0;i<iCoinNum;i++)

 {

  tempx=MapCoinArray[i].x;

  tempy=MapCoinArray[i].y;

  if ( IN_AREA(tempx, viewx-32, VIEWW) )

  {

   //玩家坐标是rmain.xpos rmain.ypos

   if( RECT_HIT_RECT(rmain.xpos,

    rmain.ypos,

    32,32,

    tempx,

    tempy,

    MapCoinArray[i].w,MapCoinArray[i].h)

    )

   {

    switch(MapCoinArray[i].id)

    {

    case ID_ANI_COIN:

     //增加金錢數量

     iMoney+=10; 

     //金币消失

     ClearCoin(i);

     break;

    }    

    return 0;

   }  

  }

 } // end of for

金币消失:

和小怪的消失不一樣.不需要設定show為0, 而是直接删除元素.即數組移動的方法.

函數:void GAMEMAP::ClearCoin(int i)

代碼:

 //檢查合法性

 if(i<0 || i>=iCoinNum)

  return;

 //減少一個金币,或者減少一個其他物品

 for(;i<iCoinNum;i++)

 {

  MapCoinArray[i]=MapCoinArray[i+1];

 }

 //修改數量

 iCoinNum--;

由此可見,直接删除元素,省去了是否可見的判斷。但凡事都有兩面性,移動數組顯然比單個元素的設定要慢(實際上不一定,可以優化)。方法多種多樣,這就是程式的好處,永遠有更好的答案。

所有的動态元素都介紹完了。所謂動态元素,就是有一個生成、運作、銷毀的過程。隻不過,有的複雜一些,如子彈、旋風、蘑菇兵、火圈,有些元素簡單一些,如爆炸效果、金币。方法都大同小異,要強調的是,這不是最好的方法。碰到金币後,會出現‘+10’的字樣,怎麼做呢?這個問題會再次說明,方法多種多樣。且聽下回分解。

附:

超級瑪麗第一版源碼連結:http://download.csdn.net/source/497676

超級瑪麗增強版源碼連結:http://download.csdn.net/source/584350