這是一個我最初嘗試開發可拖放物件,用於可能的 GUI 元素或遊戲中的專案。
一款跳棋遊戲,其中的棋子在釋放時能自動吸附到棋盤格子的中心,這似乎是開發可拖放物件的一個良好框架。
這裡使用的是 SFML 1.6 版本。
只有當移動是合法的時候,棋子才會吸附到格子中心,否則它會回到原來的位置。
動畫效果包括:
1) 動畫歡迎介面。(WELCOME 字樣出現,幾秒鐘後它會展開並淡出)。
2) 一個完整的動畫,將棋子擺放到棋盤上。
3) 俘獲,包括將俘獲的王棋分成兩個棋子,然後將俘獲的棋子沿著棋盤邊緣移動。
4) 當一個棋子被“封王”時,會使用一個被俘獲的棋子。
5) 遊戲結束時的動畫獲勝者宣佈。
遊戲開始和遊戲過程中的截圖
本文末尾提供了一個連結,其中包含所有原始碼、影像和一個可執行檔案(這樣你就可以立即嘗試它)。
以下是原始碼的部分描述。
可拖放物件。
抽象基類:dragDrop
這個類是抽象的,因為形狀(圓形、矩形)在基類中是不確定的。
純虛方法
1 2 3
|
virtual bool hit(void) = 0;// depends on shape ( rect, circle, ? )
virtual bool hitAnchor(int idx) = 0;// test if at a given anchor location
virtual void snap(void) = 0;// carries out snap-to motion in frame logic. Shape dependent.
|
一些資料成員暗示了物件的工作方式。
1 2 3
|
const static int& r_mseX;// track globally updated mouse coordinates
const static int& r_mseY;
static float snap_speed;// all common speed.
|
實際上,snap_speed 尚未投入使用!吸附運動目前“立即”發生(一個幀內完成整個距離)。 嘗試啟用此功能!
dragDrop 物件透過指向錨點陣列的資料成員來“瞭解”其可能的錨點。
1 2 3
|
std::pair<int, int>* p_anchorPos;// array of allowed destination points in drag op.
int Nanchors;// # of pairs in array pointed to by p_anchorPos
int homeIdx;// index to home location among anchor array elements
|
指向的陣列在 main.cpp 中靜態宣告,代表棋子在棋盤上的所有 32 個位置。
然後我們有這 3 個方法,它們是非虛方法(即在 dragDrop 類中定義)
1 2 3
|
bool grab(void);// call on LBUTT down - calls hit()
void drag(void);// call in frame logic
void release( int* p_IdxList, int listSz );// for use when given a sub-list of anchors from a larger array of anchors
|
傳遞給 release() 函式的引數提供了一個“禁止”錨點的列表。 如果 dragDrop 在其中一個上被釋放,它將返回到 homeIdx 錨點。
派生類(base=dragDrop):dragDropRect
看起來我只開發了一個用於矩形 dragDrop 物件的類,即使設定抽象基類的目的就是為了允許這裡的自由度! 顯然,圓形 dragDrop 物件更適合於
這個應用程式。 因此,邀請讀者建立和使用 dragDropCircle 物件。
在 dragDropRect 中,我們只有 int szX, szY; 以及 dragDrop 中 3 個 pv 函式的定義。
關於動畫運動的一點說明
抽象基類:Leg
此類提供對用於更新位置的函式的訪問。 移動的物件擁有運動的引數 t
for the motion.
1 2 3
|
float period;
virtual float x( float t ) = 0;
virtual float y( float t ) = 0;
|
同樣,設定抽象基類的目的是為了允許路徑形狀的自由度。
在這個專案中,我只添加了一個派生類。linLeg 支援在 2 個給定點之間以恆定速度直線運動。 這是遊戲中使用的唯一型別的運動。
類 (base=Leg):linLeg
1 2 3 4
|
float posix, posiy;
float velix, veliy;
virtual float x( float t ) { return( posix + velix*t ); }
virtual float y( float t ) { return( posiy + veliy*t ); }
|
遊戲中只使用了一個 dragDropRect 物件 (chObj)。 這是正在移動的棋子。
類:Path
此類用於管理多個 Leg 的使用。 該類擁有物件可能在其上移動的 Legs 陣列。
遊戲中有四個在使用
1 2 3 4
|
Path wh_dealPath( 12, 50, 3, 400.0f, -40.0f );// 12 linLegs. One for each checker on deal.
Path bk_dealPath( 12, 50, 3, 400.0f, 620.0f );
Path aniPath( 1, 0, 0, 100.0f, 100.0f );// for general single checker motion
Path kingMePath( 1, 0, 0, 100.0f, 100.0f );// for "king me" animations
|
在 main.cpp 中,您會找到這些在程式中提供邏輯的函式。
1 2 3 4 5 6 7 8 9
|
void gameLogic(void);// called in main(). Logic branches from here.
void gameCapture_SplitAniLogic(void);// specific for capture and checker split (captured king into 2 normal checkers in the capture pool).
void gameKingMeAniLogic(void);
void gameDraw(sf::RenderWindow& rApp);// all drawing calls here
void gameHitDown(void);// event handling for the game
void gameHitUp(void);
bool menuHitDown(void);// returns false if file I/O error
void menuHitUp(void);// event handling for the buttons.
|
您還會找到按鈕類,因為我傾向於自己完成所有 gui。
我希望上面的描述能為您理解程式碼提供足夠的基礎。
程式有很多可以擴充套件和/或改進的地方,因此有空間進行修改。
下載
我比這篇文章的最後一個版本有所改進。 下面連結的 .zip 檔案包含所有原始碼、所有使用的影像以及一個可執行檔案,該檔案現在靜態連結到使用的 SFML 庫。
exe 應該在沒有任何外部庫檔案存在的情況下執行。
附件: [checkers_stat.zip]