SDL系列教程15:精靈引擎2
作者;akinggw
前言
最近,一直有朋友向我要文章,都出現忠實讀者了。我真的很感謝你們對我文章的支持,有人問為什麼精靈引擎一直沒有下文,看來大家很關心這個問題。
其實,最近一直很忙,忙于寫GUI和服務器端的調試。所以一直沒時間。並且我寫的精靈引擎也需要修改,現在的精靈引擎用5個類實現,可以顯示各種各樣的精靈了。但在精靈數據端還需要修改,比如,象地圖中的動的噴泉,活的樹木還有許多的房屋,這些東西雖然是同地圖一起加載進來的,但還是需要在這裡顯示。
當然,這就需要我們將地圖結構寫好以後來改這些東西。不過現在的精靈引擎能完全滿足你的需要。
結構

上面就是我寫的這個精靈引擎的結構,共使用了5個類。它們不存在繼承關系,全是獨立的。我先來演示一下其工作。
首先,你建立一個精靈管理類,它主要就是對精靈圖片和精靈數據進行管理。(有人懷疑是否這裡應該加入對數據的管理,因為它用于顯示的數據來自于我們的大廳鏈表和地圖數據中,是否應該分開管理??)
對于這個問題,我也不知道。但這根精靈數據鏈表卻是始終需要的,這顯然是肯定的,不然,你就沒法顯示。:)
或許這個精靈引擎應該全部劃給地圖,因為它使用的所有數據基本來子地圖(除了角色為全局的外)。
下面是其類的實現:
精靈圖片類:
class Sprite
{
public:
Sprite(int id);
~Sprite(void);
int GetSpritId(void){return spr_id;}
bool LoadSprite(char* filename);
bool DisplaySprite(SDL_Surface *scr,int x,int y,int sta_w,int sta1_h);
bool SetSprite(int width,int hight);
private:
int spr_id;
SDL_Surface* spr;
SDL_Rect flip[16];
int state1_w,state2_h;
};
主要完成的工作就是精靈圖片的導入和分割。這個類很容易擴展,我這裡只是顯示四個方向的精靈,但很容易就可以擴展到8個方向或更多的方向,也可以顯示靜止的精靈,比如房屋。
精靈圖片鏈表類:
class SpriteList
{
public:
std::vector sprite;
SpriteList(void);
~SpriteList(void);
bool InsertSprite(Sprite *spr);
bool DelAllSprite(void);
bool DelSprite(int id);
Sprite* SearchSprite(int id);
};
這個類使用了STL中的VECTOR容器來裝載圖片,它主要的任務就是裝載我們要用到的所有精靈圖片。當然這些精靈圖片必須有唯一確定的ID。
精靈數據類:
class CPlayer
{
public:
CPlayer(int y);
~CPlayer(void);
void BroadSprite(Sprite *spr,SDL_Surface *scr);
int m_iPosY;
int m_iPosX;
int jiaose;
int m_iFrame;
int m_iChar;
};
這個類基本上由兩部分構成:1)用于顯示的數據,比如坐標,相對應的精靈圖片的ID號,精靈所面向的方向和當前顯示的禎數;2)顯示函數,通過上面的數據到相應的地方顯示精靈。
而我們用到的第一部分的數據可以來自大廳鏈表的玩家信息,也可以來自地圖的精靈信息。所以這裡應該是一個共同體結構:
union 精靈
{
樹木;
房屋;
瀑布;
怪獸;
仙女;
……
};
當然,我這裡的結構只包含其主要的數據。
精靈數據鏈表:
class SpriteDateList
{
public:
std::vector player;
SpriteDateList(void);
~SpriteDateList(void);
bool DelSpriteDate(int id);
bool DelAllSpriteDate(void);
bool InsertSpriteDate(CPlayer *sd);
void Sort(void);
};
同樣,這裡使用STL的VECTOR容器來進行存儲,它的任務就是插入數據,刪除數據和按照精靈的Y坐標進行排序。這裡的鏈表必須是有續鏈表,Y值最小的在前面,而且要有續。至于為什麼,可以去找本書看看或來信問我akinggw@126.com
最後,就剩下精靈管理類了:
class SpriteManager
{
private:
SpriteDateList *sdl;
SpriteList *sl;
public:
SpriteManager(void);
~SpriteManager(void);
bool InsertSpritePic(Sprite *spr);
bool InsertSpriteDate(CPlayer *sd);
bool DeleteSpritePic(int id);
bool DeleteSpriteDate(int id);
bool DisplaySprite(SDL_Surface *scr);
};
這個類用于對精靈圖片數據和精靈數據進行管理,比如精靈圖片的插入,根據ID號的刪除。精靈數據的插入和刪除。最後就是按照精靈數據鏈表中的數據顯示所有精靈。(當然這些數據現在是有序的,不會出現人物站在樹木或房屋上)
到現在為止,我們的精靈引擎還沒完,雖然,它可以顯示大量的精靈,似乎有《傳奇》的味道了,但不然,這時你將看見屏幕上的精靈行動也實在太迅速了吧,有點像卡通片,但我們不需要卡通片,我們需要的是遊戲,所以必須讓時間延遲。
#define SDL_TIMER_EVENT ( SDL_USEREVENT + 0 )
const int TIMER_INTERVAL = 80;
Uint32 TimerCallback(Uint32 interval)
{
SDL_Event event;
event.type = SDL_TIMER_EVENT;
SDL_PeepEvents( &event, 1, SDL_ADDEVENT, 0 );
return TIMER_INTERVAL;
}
這些數據可以放在遊戲全局變量裡。下面那個用于設置延遲的時間,數值越大,圖片顯示越慢。
SDL_SetTimer( TIMER_INTERVAL, TimerCallback );
這個函數用于在遊戲中生效。
case SDL_TIMER_EVENT:
{
engine->Draw();
}
最後,就是看執行的效果了。
真沒想到,我寫了一個星期的精靈引擎,短短5頁就完了。也許我沒有講清楚或你也許有更好的東東,歡迎來信給我。我也很想知道你是如何寫的哦!
關于更多內容請訪問金橋科普網站( )遊戲開發欄目,如果你需要遊戲開發方面的書籍請參考金橋書城遊戲頻道(http://book.jqcq.com/category/1_70_740.html )。 如果你在閱讀本篇文章時有什麼好的建議請來信給我,我的E_mail: akinggw@126.com. 如果你在使用SDL時有什麼問題,請到金橋科普網站( )遊戲開發欄目,我將詳細地為你解答。
|