大家的支援就是我的動力。
子彈每次攻擊到效果,都會顯示一個爆炸效果。隻涉及圖檔顯示,它的結構很簡單。如下:
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