Presentation is loading. Please wait.

Presentation is loading. Please wait.

OOSDL 靜宜大學資工系 蔡奇偉 副教授 2006-2007.

Similar presentations


Presentation on theme: "OOSDL 靜宜大學資工系 蔡奇偉 副教授 2006-2007."— Presentation transcript:

1 OOSDL 靜宜大學資工系 蔡奇偉 副教授

2 內容大綱 前言 組成類別 CPoint, CRect, CSurface CScreen CSDLApp, CGameApp 範例

3 前言 Object-Oriented SDL 把一些 SDL 資料型態封裝成類別,使其更容易使用。
提供 Game Programming Framework,以簡化遊戲程式的開發。

4 組成類別 基本型態: CPoint: 二維的點座標,主要用於儲存位置資訊。 CRect: 封裝 SDL_Rect 型態的矩形類別。
CSurface: 封裝 SDL_Surface 型態的繪圖頁類別。 CJoysticks: 封裝 SDL_Joystick 型態的搖桿類別。 Clock & Timer 時鐘與定時器 Framework: CSDLApp: 簡單 SDL 應用程式的 framework CGameApp: 基本的遊戲程式 framework CScreen: 遊戲螢幕

5 CPoint 類別 struct DECLSPEC CPoint {
CPoint (Sint16 x = 0, Sint16 y = 0); void Set (Sint16 x, Sint16 y); bool operator== (const CPoint &pt); bool operator!= (const CPoint &pt); bool InsideRect (CRect &r); };

6 CRect 類別 class DECLSPEC CRect : public SDL_Rect 成員函式
CRect (Sint16 x = 0, Sint16 y = 0, Uint16 w = 0, Uint16 h = 0); void Set (Sint16 x, Sint16 y, Uint16 w, Uint16 h); bool operator== (const CRect &r); bool operator!= (const CRect &r); bool IsEqualSize (const CRect &r); bool IsNonEqualSize (const CRect &r); bool ContainPoint (CPoint &pt);

7 Sint16 Left (); Sint16 Top (); Sint16 Right (); Sint16 Bottom (); Uint16 width (); Uint16 Height (); Left Right Top Botom Width Height

8 CSurface CSurface (); CSurface (SDL_Surface *pSurface);
CSurface (CSurface &cs); // Copy construction ~CSurface () operator SDL_Surface * () const; SDL_Surface * GetSDLSurfacePtr () const; CSurface& operator= (const CSurface &cs); CSurface& operator= (SDL_Surface *pSurface);

9 // Create a blank surface.
bool Create (Uint32 flags, int width, int height, int depth =32, Uint32 Rmask = SDL_RMASK, Uint32 Gmask = SDL_GMASK, Uint32 Bmask = SDL_BMASK, Uint32 Amask = SDL_AMASK); // Create a CSurface from pixel data. bool Create (void *pixels, int width, int height, int pitch, int depth = 32, // Load an image file bool LoadImage (const char *file, bool bDisplayFormat = true); // Save CSurface to a BMP file int SaveBMP (const char *file);

10 int Width (); int Height (); bool Lock (); void Unlock (); Uint32 GetPixel (int x, int y); void PutPixel (int x, int y, Uint32 pixel);

11 // Color conversion Uint32 MapRGB (Uint8 r, Uint8 g, Uint8 b); Uint32 MapRGBA (Uint8 r, Uint8 g, Uint8 b, Uint8 a); void GetRGB (Uint32 pixel, Uint8 &r, Uint8 &g, Uint8 &b); void GetRGBA (Uint32 pixel, Uint8 &r, Uint8 &g, Uint8 &b, Uint8 &a);

12 // Colorkey bool SetColorKey (Uint32 key, bool useRLE = true) bool SetColorKey (Uint8 r = 0, Uint8 g = 0, Uint8 b = 0, bool useRLE = true) bool ClearColorKey (); bool HasColorKey (); // Alpha bool SetAlpha (Uint8 alpha, bool useRLE = true) bool ClearAlpha () bool HasAlpha ()

13 // Clipping CRect void SetClipRect (CRect &rect); void ResetClipRect (); void GetClipRect (CRect &rect); // Fill surface bool Fill (Uint32 color); bool Fill (Uint8 r, Uint8 g, Uint8 b); // Fill part of surface bool FillRect(CRect &rect, Uint32 color); bool FillRect(CRect &rect, Uint8 r, Uint8 g, Uint8 b);

14 // Blit this surface to another surface
bool Blit (SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect); CPoint &position); bool Blit (CSurface &dst, Sint16 x, Sint16 y); // Blit this surface to the screen surface bool Show (CRect &srcrect, CRect &rect); bool Show (CRect &srcrect, CPoint &position); bool Show (CRect &srcrect, Sint16 x, Sint16 y); bool Show (Sint16 x, Sint16 y);

15 CScreen 類別 CScreen (int width, int height, int bpp, Uint32 flags);
virtual bool Show (CSurface &surface, SDL_Rect *srcrect, SDL_Rect *dstrect); virtual bool Present (); bool isDirty (); void SetDirty (); void ResetDirty (); void SetBackgroundColor (Uint32 color); void SetBackgroundColor(m_pSurface->MapRGB(r,g,b)); void Clear (); void Clear (Uint32 color);

16 CSDLApp void SetScreen (CScreen *pScreen = NULL);
若參數為 NULL,則使用預設的螢幕物件(640x480x32, 軟性螢幕繪圖頁, 視窗畫面)。 void SetCaption (const char *title, const char *icon = NULL); 若採用視窗螢幕,此函式可用來設定視窗的標題與 icon。 void GetCaption(char **title, char **icon); 若採用視窗螢幕,此函式可用來取得視窗的標題與 icon 。

17 virtual bool InitializeSDL (
Uint32 flags = SDL_INIT_VIDEO); 初始化 SDL 函式庫。預設的旗標值只啟動 Video 子系統。此成員函式必須是第一個被呼叫的函式。 virtual bool InitializeApp (); 你應該改寫此成員函式,在其中加入所需的應用程式初始化設定。 virtual void BeforePollEvent (); 如果你的應用程式在處理事件之前,需做某些計算,你可以改寫此成員函式。 virtual bool AppMain (); 遊戲迴圈中的主要程式碼。 virtual bool QuitApp (); 改寫此成員函式來處理結束程式前的清理動作。

18 事件處理的相關成員函式 virtual bool ProcessNextEvent ();
virtual void SetApplication (void *pTheApp);

19 virtual void OnKeyDown (const SDL_keysym &keysym);
virtual void OnKeyUp (const SDL_keysym &keysym); virtual void OnMouseMotion (Uint8 state, Uint16 x, Uint16 y, Sint16 xrel, Sint16 yrel); virtual void OnMouseButtonDown (Uint8 button, Uint16 x, Uint16 y); virtual void OnMouseButtonUp (Uint8 button, virtual void OnUser (Uint8 type, int code, void *data1, void *data2); virtual void OnQuit ();

20 // Joystick events virtual void OnJoyAxis (Uint8 which, Uint8 axis, Sint16 value); virtual void OnJoyButtonDown (Uint8 which, Uint8 button); virtual void OnJoyButtonUp (Uint8 which, virtual void OnJoyHat (Uint8 which, Uint8 hat, Uint8 value); virtual void OnJoyBall (Uint8 which, Uint8 ball, Sint16 xrel, Sint16 yrel);

21 virtual void OnActiveEvent (Uint8 gain, Uint8 state);
virtual void OnResize (int w, int h); virtual void OnExpose (); virtual void OnSysWM ();

22 void PumpEvents (); int WaitEvent (); int PeepEvents (int numevents, SDL_eventaction action, Uint32 mask); int PollEvent (); int PushEvent (SDL_Event *event); void SetEventFilter (SDL_EventFilter filter); SDL_EventFilter GetEventFilter (); Uint8 EventState (Uint8 type, int state);

23 Uint8 EnableEvent (Uint8 type);
Uint8 DisableEvent (Uint8 type); Uint8 QueryEvent (Uint8 type); Uint8 *GetKeyState (int *numkeys); SDLMod GetModState (); void SetModState (SDLMod modstate); char *GetKeyName (SDLKey key); int EnableUNICODE (); int DisableUNICODE (); int QueryUNICODE ();

24 int EnableKeyRepeat ( int delay = SDL_DEFAULT_REPEAT_DELAY, int interval = SDL_DEFAULT_REPEAT_INTERVAL); int DisableKeyRepeat (); Uint8 GetMouseState (int *x, int *y); Uint8 GetRelativeMouseState (int *x, int *y); Uint8 GetAppState (); int JoystickEventState (int state);

25 CSDLApp 的遊戲迴圈(Game Loop)
InitializeApp(); while (!m_bQuit) { BeforePollEvent(); m_bQuit = ProcessNextEvent(); if (m_bQuit) break; AppMain(); } QuitApp();

26 最簡單的 OOSDL 程式 #include "oosdl.h“ CSDLApp myApp;
int main (int argc, char* argv[]) { myApp.InitializeSDL(); myApp.SetScreen(); myApp.Run(); return EXIT_SUCCESS; }

27 使用 CSDLApp 的步驟 宣告一個繼承 CSDLApp 的類別,在其中依所需,改寫相關的成員函式,譬如:
class CMyApp : public CSDLApp { // 宣告本類別所需的成員函式與資料成員 // 依所需地改寫 CSDLApp 中的成員函式 };

28 範例: oosdl04.cpp class CMySDLApp : public CSDLApp { protected:
virtual bool InitializeApp (); private: CSurface background, ball; }; bool CMySDLApp::InitializeApp () background.LoadImage ("bkg01.bmp"); ball.LoadImage ("ball.bmp"); background.Show(0, 0); ball.SetColorKey(0, 0, 0); ball.Show(192, 112); return true; } 改寫以加入本程式所需的初始化設定 本程式所需的資料成員

29 在主函式中,定義一個 CMyApp 的物件,譬如:
int main( int argc, char* argv[] ) { CMySDLApp myApp; // 其他項目 }

30 在主函式中,開始呼叫 CMySDLApp 的成員函式 InitializeSDL(),譬如:
int main( int argc, char* argv[] ) { CMySDLApp myApp; myApp.InitializeSDL(); // 其他項目 }

31 接下來呼叫 CMySDLApp 的成員函式 SetScreen(),譬如:
int main( int argc, char* argv[] ) { CMySDLApp myApp; myApp.InitializeSDL(); myApp.SetScreen(); // 其他項目 }

32 SetScreen() 將選擇 640x480 的視窗為螢幕物件。你可以用以下的方式將螢幕設成 1024x768 的視窗:
myApp.SetScreen(new CScreen(1024,768,0, SDL_SWSURFACE | SDL_ANYFORMAT)); CScreen 建構函式的宣告如下: CScreen::CScreen (int width, int height, int bpp, Uint32 flags); 其中的參數意義和 SDL_SetVideoMode() 相同。

33 最後呼叫 CMySDLApp 的成員函式 Run(),譬如:
int main( int argc, char* argv[] ) { CMySDLApp myApp; myApp.InitializeSDL(); myApp.SetScreen(); // 其他項目 myApp.Run(); return EXIT_SUCCESS; }

34 範例: 加入事件的處理 (oosdl07.cpp)
class CMySDLApp : public CSDLApp { protected: virtual bool InitializeApp (); virtual bool AppMain (); // Events virtual void OnKeyDown (const SDL_keysym &keysym); virtual void OnKeyUp (const SDL_keysym &keysym); private: CSurface background, ball; int ball_x, ball_y; int ball_xvel, ball_yvel; int ball_speed, ball_speed_inc; };

35 bool CMySDLApp::InitializeApp ()
{ background.LoadImage("bg.png"); ball.LoadImage("ball.png"); ball.SetColorKey(0, 0, 0); ball_x = (SCREEN_WIDTH - BALL_WIDTH) /2; ball_y = (SCREEN_HEIGHT - BALL_HEIGHT) /2; ball_xvel = 0; ball_yvel = 0; ball_speed = 1; ball_speed_inc = 0; background.Show(0, 0); ball.Show(ball_x, ball_y); return true; }

36 inline void restrict (int &x, int min, int max)
{ if (x < min) x = min; else if (x > max) x = max; } bool CMySDLApp::AppMain () if (ball_speed_inc != 0) ball_speed += ball_speed_inc; if (ball_speed < 1) ball_speed = 1;

37 if (ball_xvel != 0 || ball_yvel !=0)
{ int x_old = ball_x, y_old = ball_y; ball_x += ball_xvel; ball_y += ball_yvel; restrict(ball_x, 0, SCREEN_WIDTH - BALL_WIDTH); restrict(ball_y, 0, SCREEN_HEIGHT - BALL_HEIGHT); if (ball_x != x_old || ball_y != y_old) background.Show(0, 0); ball.Show(ball_x, ball_y); } return true;

38 void CMySDLApp::OnKeyDown (const SDL_keysym &keysym)
{ switch (keysym.sym) case SDLK_UP: ball_yvel = -ball_speed; break; case SDLK_DOWN: ball_yvel = ball_speed; break; case SDLK_LEFT: ball_xvel = -ball_speed; break; case SDLK_RIGHT: ball_xvel = ball_speed; break; case SDLK_EQUALS: ball_speed_inc = 1; break; case SDLK_MINUS: ball_speed_inc = -1; break; case SDLK_HOME: ball_x = (SCREEN_WIDTH - BALL_WIDTH) /2; ball_y = (SCREEN_HEIGHT - BALL_HEIGHT) /2; break; default: CMySDLApp::OnKeyDown(keysym); }

39 void CMySDLApp::OnKeyUp (const SDL_keysym &keysym)
{ switch (keysym.sym) case SDLK_UP: if (ball_yvel < 0) ball_yvel = 0; break; case SDLK_DOWN: if (ball_yvel > 0) ball_yvel = 0; case SDLK_LEFT: if (ball_xvel < 0) ball_xvel = 0; case SDLK_RIGHT: if (ball_xvel > 0) ball_xvel = 0; case SDLK_EQUALS: if (ball_speed_inc > 0) ball_speed_inc = 0; case SDLK_MINUS: if (ball_speed_inc < 0) ball_speed_inc = 0; }

40 int main( int argc, char* argv[] )
{ CMySDLApp myApp; myApp.InitializeSDL(); myApp.SetScreen(); myApp.SetCaption(WINDOW_TITLE); myApp.Run(); return EXIT_SUCCESS; }

41 CGameApp 繼承 CSDLApp,並加入以下的修改 其中呼叫 SDL_Init (SDL_EVERYTHING) 加入遊戲時鐘與定時器
預設為 Fixed Frame Rate,每秒約為 30 張畫格 可用下面的方法改為 Variable Frame Rate: CMyGameApp myGameApp(false);

42 範例: oosdl13.cpp class BallObj : public CSurface { public:
BallObj () : CSurface(), m_x(0), m_y(0) {} void SetPosition (Uint16 x, Uint16 y) m_x = x; m_y = y; } bool Show() { return CSurface::Show(m_x, m_y); } private: Uint16 m_x, m_y; // ball screen position };

43 class CMyGameApp : public CGameApp
{ public: CMyGameApp() : CGameApp() {} ~CMyGameApp () {} protected: virtual bool InitializeApp (); virtual bool AppMain (); private: BallObj redball, blueball; };

44 bool CMyGameApp::InitializeApp ()
{ m_pScreen->SetBackgroundColor(0, 0, 0); redball.SetPosition(0, 0); redball.LoadImage("redball.png"); redball.SetColorKey(0, 0, 0); blueball.SetPosition((SCREEN_WIDTH-BALL_WIDTH)/2, (SCREEN_HEIGHT-BALL_HEIGHT)/2); blueball.LoadImage("blueball.png"); blueball.SetColorKey(0, 0, 0); return true; }

45 bool CMyGameApp::AppMain ()
{ const float PERIOD = 6.0; // period in second const float RADIUS = 200; // in pixels // angular increment double angle_inc = 2.0*M_PI* m_pGameClock->GetFrameDefaultTime()/PERIOD; int nFrame = m_pGameClock->GetFrameNumber()-1; int x = RADIUS * cos(nFrame*angle_inc) - BALL_WIDTH/2 + SCREEN_WIDTH/2; int y = RADIUS * sin(nFrame*angle_inc) - BALL_HEIGHT/2 + SCREEN_HEIGHT/2; // Update ball position and then show it. redball.SetPosition(x, y); m_pScreen->Clear(); redball.Show(); blueball.Show(); return true; }

46 int main( int argc, char* argv[] )
{ CMyGameApp myGameApp; myGameApp.InitializeSDL(); myGameApp.SetScreen(); myGameApp.SetCaption(WINDOW_TITLE); myGameApp.Run(); return EXIT_SUCCESS; }


Download ppt "OOSDL 靜宜大學資工系 蔡奇偉 副教授 2006-2007."

Similar presentations


Ads by Google