ClanLibbing Part 1: Getting Started
by Michael DePalatis

Introduction

Ah, ClanLib. When I first began to program games, ClanLib was one of the first things I used to make simple games. It’s low-level enough to give the programmer complete control over almost everything on a computer, while at the same time being much simpler than other SDKs, such as DirectX. ClanLib is also distributed under GNU, so anyone can modify the source code and add features to it as they see fit, and as a result, it is very actively maintained. But the one feature that sets ClanLib apart is it’s portability: It’s source can be compiled under Linux, Windows, and BeOS without any change in the code (except that BeOS support had lagged in the past, but it’s catching up now).

In this series of articles I will demonstrate how ClanLib is used and what can be done with it. In the end, I will even write a complete game using nothing but ClanLib. Before we get started, you need to head over to http://clanlib.org and get ClanLib 0.4.x or higher (all the examples in this use the 0.4.x tree, so compatibility is not guaranteed with the 0.5.x tree), in addition to the other libs that ClanLib requires. I have 0.4.4 as I am writing this, though all of the examples I give should work with anything from 0.4.x (assuming the version you have doesn’t have any bugs in it). I will not go into detail on what you need and how to install as the site tells you everything that you will need for this. You will also need a basic understanding of C++.

Okay, now that you have ClanLib installed (you do have it now, right?), we can proceed…

C++ Exception Handling

Although it is not required, the makers of ClanLib recommend that you use C++ exception handling to catch any errors (no pun intended <G>). Even if you aren’t going to use this in your ClanLib apps, you should still understand it, as it is helpful when reading source code from ClanLib apps, and some of ClanLib’s source itself.

For creating your own apps, you will be using the try {} and catch {} statements, but I’ll cover the throw statement too in case you run in to it (or are just curious). To put simply, try {} tries ever statement in the code block (hmmm, imagine that…), and catch {} catches any errors that were thrown (with throw {} inside functions) from within the try {} statement. Sound confusing? Well, it isn’t, I just felt like making it sound that way <BG>. Take a look at the following example that would be placed in the regular main() function:

try { the_function(); std::cout << "the_function() is fine"; } catch(char *msg) { std::cout << msg; }

Okay, first of all, take a look at the std:: thing in front of cout. Now, not all compilers require this, but the ClanLib guys like to just to be safe on as many platforms as possible. I couldn’t agree more. So just get used to it. Moving on…

In the try {} statement, we execute the_function(), and if it works, it’s all good. If not, we use the catch {} statement to get the error that occurred (in this case in char * format) and do some output or whatever else you’d want to do. But how do you catch the error? Well, I’m glad you asked! Take a look at the definition for the_function():

void the_function() { if(!ptr) // test a global pointer throw "Not a valid pointer"; else return; }

Here, you have a pointer (cleverly named ptr) that is obviously global. We test to make sure it is a valid pointer, and if not, we throw the message with the throw statement. That’s all there is to it. Now, if you wanted some real good exception handling, you’d probably want to make your own error classes, but I’ll leave that up to you.

Oh yes. This has nothing to do with exception handling, really, but in case you were unaware of this before, you should always set up sentinels in your header files to prevent compiler errors. Take a look:

#ifndef WHATEVER_U_WANT #define WHATEVER_U_WANT // all your .h stuff goes here #endif // don’t forget this!!!

If you look at any of the ClanLib headers, you’ll see that they all have this on them. I recommend you do this with all of your headers as well, as it is often a lot easier than simply not including a header in one or more source files.

A Basic ClanLib Application

Because ClanLib is a cross-platform SDK, and various platforms have different types of main functions (for example, in Win32 you use WinMain()), the makers of ClanLib devised a clever way to deal with this problem. Instead of describing it beforehand, I’ll show it to you first:

#include <ClanLib/core.h> class ClanGameApp: public CL_ClanApplication { public: virtual char *get_title() { return "Title goes here"; } virtual void init_modules() { CL_SetupCore::init(); } virtual void deinit_modules() { CL_SetupCore::deinit(); } virtual int main(int, char **) { return 0; } } app;

Assuming you have installed ClanLib and read the readme files, you should know about core.h, and you may have already seen some setup similar to what you see above. But let me explain it anyway <G>. The first function simply puts a title on the title bar, or wherever else titles may be displayed on your OS. The next two functions are where you put the code to initialize and deinitialize modules, respectively. (These functions are not used in the 0.5.x tree. Instead, you just place all the initialization and deinitialization code inside main()). The last function is where the actual game is, and is the same as the standard int main().

Before we go any further, let’s discuss the ClanLib naming system a little (not that it’s too complicated, but just so you know what’s what). First of all, you have probably already noticed that all ClanLib classes begin with a CL_ extension. DO NOT do that with any of your classes, just to be certain that you don’t cause any problems. Also, any macros that you may encounter begin with a cl_ prefix. As for functions, they are all in lower case with underscores separating words. There are a few more rules, but you really don’t need to worry about them too much, unless you plan to help develop ClanLib. If you want to know what the other rules are, read the documentation that comes with ClanLib.

Moving on, you also notice that instead of creating an instance of a class, :: is used often instead (e.g., CL_SetupCore::deinit()). All I can say about this is, just do it <BG>. Okay, now that we have all this basic crap out of the way, we can move on to a program that actually does something. Take a look at ClanSimple.cpp, which is a simple ClanLib application that will load and display a PCX image (note that although most ClanLib users prefer TGA and PCX files, this is not a requirement at all). You will also need the pic.pcx file (or you could just make your own 640 x 480 8 bpp PCX picture if you really felt the urge to do so). I will not go into detail on what each function does, as I have pretty much everything commented. If you have trouble compiling or running this demo, please read the ClanLib FAQ, as it is impossible for me to know every possible problem for all three OS’s (especially when I only have one of them at the moment). If the FAQ doesn’t help you, send e-mail to the ClanLib user mailing list, a link to which can be found below.

Wrapping It Up

Well, that’s it for the first part in this series. Next time I will cover surfaces more in-depth and go over some basic input as well. But until then, if you’d like to do some ClanLibbing, take a look at the documentation and examples that come with ClanLib. The documentation isn’t always up to date (don’t get me wrong, it’s still plenty useful), but the examples are great. If you still have questions about it, subscribe to the ClanLib user mailing list at clanlib-user-subscribe@dark.x.dtu.dk, and once you’ve subscribed, send all your messages to clanlib-user@dark.x.dtu.dk. If you ever have a problem and can’t find the solution to it yourself, this is the first place you should go, as somebody will probably respond to you fairly quickly. In addition to covering surfaces and basic input next time, I will also cover the datafile compiler, a handy tool that lets you compile all your resources (be they sounds, fonts, pictures, or otherwise) into a nice .dat file. If you have any problems compiling the example in this part, feel free to send me an e-mail at CmndrM@i-techuk.net. Until next time, happy ClanLibbing!

Discuss this article in the forums


Date this article was posted to GameDev.net: 11/2/2000
(Note that this date does not necessarily correspond to the date the article was written)

See Also:
General

© 1999-2011 Gamedev.net. All rights reserved. Terms of Use Privacy Policy
Comments? Questions? Feedback? Click here!