ClanLib logo

Simple Game Development with ClanLib 0.8

Part 3

Signals and User Input

    In ClanLib, signals go hand-in-hand with user input, but what is a signal? Signals and Slots are a part of the CL library, and they make event-driven programming possible for games without the need for 'polling' or checking for changes in status of all the possible input devices (is the 'A' button pressed or mouse moving, for example).

    Every time a button on the mouse is pressed, CL sends out a signal (CL_Mouse::sig_key_down). If you want to capture that mouse click and do something with it, you have to create a Slot for the signal and function to handle the signal. Then, you have to connect the Signal and the Slot.

    Including a CL_Slot and a function to handle mouse presses, our TicTacToeGame class looks like this:

    class TicTacToeGame {
    
    public:
    	TicTacToeGame();
    	~TicTacToeGame();
    
    	void loadGraphics();	// Load the game graphics
    	void paint();		// Paint the board and moves
    	void run();		// Game loop
    	void handleMousePress(const CL_InputEvent &key);
    
    private:
    	bool alive;
    	CL_Surface *board, *o, *x, *menu;
    	CL_Slot mousePress;
    };

    Notice that handleMousePress has an extra parameter. Every time CL_Mouse::sig_key_down is fired, that parameter is included. So handleMousePress specifies that parameter to catch it from the signal.

    This isn't mere coincidence, though. The parameters of the handler function must always match those of the signal it's being connected to. Below is the code needed to connect the two. (You can safely ignore the this argument for now.)

    // Constructor
    TicTacToeGame::TicTacToeGame() {
    
    	alive = true;
    	loadGraphics();
    
    	// Connect the mousePress slot to sig_key_down, specifying handleMousePress to call
    	mousePress = CL_Mouse::sig_key_down().connect(this, &TicTacToeGame::handleMousePress);
    }

    An unfortunately long line of code, but very useful. Now, every time the mouse is clicked handleMousePress is executed, with which button was clicked specified in the parameters.

Mouse Location & Handling Input

    Of course, knowing that a button was clicked is usually not enough. We want to know where it was clicked, too. So in the below implementation of handleMousePress I will show how to get the x and y screen coordinates of the mouse click as well as demonstrate how to do simple collision detection to see if the user has clicked 'quit'.

    void TicTacToeGame::handleMousePress(const CL_InputEvent &key) {
    
    	// Since a clicked happened, get the screen coordinates of the mouse
    	// They are included in the 'key' parameter
    	int x = key.mouse_pos.x, y = key.mouse_pos.y;
    
    	// 4 points forming a box around the 'Quit' label
    	int quitX = 300, quitY = 400, quitWidth = 85, quitHeight = 20;
    
    	// See if the x and y mouse coordinates lie inside that box
    	if (x > quitX && x < quitX+quitWidth && y > quitY && y < quitY+quitHeight) {
    		alive = false;
    	}
    }

    That about covers it for signals and input. Now you should be able to connect to signals for input and do something useful with it!

    Download Visual C++ Workspace for Part 3

The Finished Game

    Believe it or not, those are the only ClanLib topics to be covered in the design and coding of our Tic-Tac-Toe example game. You can download the final workspace from the main tutorial page to review the additional code needed to complete the game.

    Return to tutorial main