Here is a project which started for me as an effort to develop a drag and drop object for possible use as a GUI element, or in a game.
A checkers game with checkers which snap-to a board space center on release seemed like a good framework for developing the drag and drop object.
SFML version 1.6 is used here.
A checker will only snap-to a space if a move there is legal, otherwise it snaps back to where it was.
Animation effects include:
1) An animated greeting. (WELCOME appears, then after a couple of seconds it expands and fades out).
2) A fully animated dealing of checkers to the board.
3) Captures, including the split of a captured king into two checkers where captured checkers go, along the board edges.
4) A captured checker is used when a checker is "kinged".
5) Animated winner announcement at end of game.
Screenshots at game start, and midgame:
A link to all source code, images and an executable (so you can try it out right away) is given at the end of this article.
Here is a partial description of the source code.
Drag and drop objects.
Abstract base class: dragDrop
This class is abstract because the shape (round, rectangular) is to be indeterminate in the base class.
Pure virtual methods:
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.
| |
Some of the data members hint at how the object works.
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.
| |
Actually, snap_speed is not in use yet! Snap motions currently occur "instantly" (entire distance in one frame). Try enabling this feature!
A dragDrop object "knows" about its possible anchor points via a data member used to point to an array of anchor points:
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
| |
The array pointed to is declared statically in main.cpp and represents all of the 32 places where a checker can be on the board.
We then have these 3 methods, which are non virtual (ie defined in the dragDrop class):
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
| |
The arguments passed to the release() function provide a list of "prohibited" anchors. If the dragDrop is released over one of these it will return to the homeIdx anchor.
Derived class (base=dragDrop): dragDropRect
It looks like I developed only a class for rectangular dragDrop objects, even though the very purpose of setting up an abstract base was to allow freedom here! Clearly, a circular dragDrop object would be better for
this application. The reader is therefore invited to create and utilize a dragDropCircle object.
In dragDropRect we have just int szX, szY; and definitions for the 3 pv functions in dragDrop.
A bit about the animated motion:
Abstract base class: Leg
This class provides access to functions for use in updating position. The object moved owns the parameter t
for the motion.
1 2 3
|
float period;
virtual float x( float t ) = 0;
virtual float y( float t ) = 0;
| |
Again. the intent with setting up an abstract base is to allow freedom of the path shape.
In this project I added only one derived class. A linLeg supports motion in a straight line between 2 given points at a constant speed. This is the only type of motion used in the game.
Class (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 ); }
| |
There is only one dragDropRect object in use in the game (chObj). This is the checker being moved.
Class: Path
This class is for managing the use of multiple Legs. The class owns the array of Legs which objects may travel on.
Four are in use in the game:
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
| |
In main.cpp you will find these functions which provide the logic in the program.
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.
| |
You will also find button classes, as I tend to do all gui myself.
I hope the above description gives you enough to base an understanding of the code upon.
There are plenty of areas where the program could be extended and/or improved so there is room to tinker.
Download:
I have improved over the last version of this article. The .zip file linked to below includes all source code, all images used, and an executable file which is now statically linked to the SFML libraries used.
The exe should run without any external library files present.
Attachments:
[checkers_stat.zip]