Irrlicht: Creating a Basic Template Application

Packt Publishing

With your C++ skills and our writers’ know-how, you’re well on your way to using the Irrlicht Engine for your 2D and 3D applications. No prior knowledge of Irrlicht needed – this book goes from installation to deployment.

Creating a new empty project

Let's get started by creating a new project from scratch. Follow the steps that are given for the IDE and operating system of your choice.

Visual Studio

Open Visual Studio and select File | New | Project from the menu. Expand the Visual C++ item and select Win32 Console Application. Click on OK to continue:

In the project wizard click on Next to edit the Application Settings. Make sure Empty project is checked. Whether Windows application or Console application is selected will not matter. Click on Finish and your new project will be created:

Let's add a main source file to the project. Right-click on Source Files and select Add New Item...|. Choose C++ File(.cpp) and call the file main.cpp:

CodeBlocks

Use the CodeBlocks project wizard to create a new project as described in the last chapter. Now double-click on main.cpp to open this file and delete its contents. Your main source file should now be blank.

Linux and the command line

Copy the make file of one of the examples from the Irrlicht examples folder to where you wish to create your new project. Open the make file with a text editor of your choice and change, in line 6, the target name to what you wish your project to be called.

Additionally, change, in line 10, the variable IrrlichtHome to where you extracted your Irrlicht folder. Now create a new empty file called main.cpp.

Xcode

Open Xcode and select File | New Project. Select Command Line Tool from Application. Make sure the type of the application is set to C++ stdc++:

When your new project is created, change Active Architecture to i386 if you are using an Intel Mac, or ppc if you are using a PowerPC Mac.

Create a new target by right-clicking on Targets, select Application and click on Next. Target Name represents the name of the compiled executable and application bundle:

The target info window will show up. Fill in the location of the include folder of your extracted Irrlicht package in the field Header Search Path and make sure the field GCC_ PREFIX_HEADER is empty:

Right-click on the project file and add the following frameworks by selecting Add Existing Frameworks...|:

Cocoa.framework

Carbon.framework

IOKit.framework

OpenGL.framework

Now, we have to add the static library named libIrrlicht.a that we compiled in Chapter 1, Installing Irrlicht. Right-click on the project file and click on Add | Existing Frameworks.... Now click on the button Add Other... and select the static library.

Delete the original compile target and delete the contents of main.cpp.

Time for action – creating the main entry point

Now that our main file is completely empty, we need a main entry point. We don't need any command-line parameters, so just go ahead and add an empty main() method as follows:

int main(){ return 0;}

If you are using Visual Studio, you need to link against the Irrlicht library. You can link from code by adding the following line of code:

#pragma comment(lib, "Irrlicht.lib")

This line should be placed between your include statements and your main() function.

If you are planning to use the same codebase for compiling on different platforms, you should use a compiler-specific define statement, so that this line will only be active when compiling the application with Visual Studio.

The scene namespace-as the name suggests-covers everything that has to do with scene management.

video

Anything that has to do with 2D and 3D rendering or accessing the video driver is found in the video namespace.

io

If you would need to load or save data from files such as XMLs or packaged archives from your local hard drive, you would need to use methods from the io namespace.

Make sure to add: #include at the top of your main source file.

And to make the function calls shorter, we'll add the following using directives to the previously mentioned namespaces. This way we don't need to specify the namespace whenever we want to call a function from that namespace:

using namespace irr;using namespace core;using namespace video;

But you should be aware that using such a using namespace is considered bad practice according to some coding standards. Because exposing all the names from the root namespace can cause some confusions, for example, what if two different namespaces contain a function with the same name? That's why using only the top-level namespace is encouraged and the low-level namespace developers should use the full qualified name. But in this chapter, we'll just use this way to make our code shorter.

Irrlicht device

The Irrlicht device is the core object that we need to interact with the Irrlicht engine. It is created using the device driver of choice such as Direct3D, OpenGL, and so on. Basically, it's an interface to the actual underlying graphics hardware. So, we need to create a device first to be able to draw anything on the screen.

Time for action – creating an Irrlicht device

Creating a device in Irrlicht is as easy as calling a single function. If you have prior experience with graphics APIs such as Direct3D or OpenGL, you will know there's a lot of code involved to set up and create a device. So let's create an Irrlicht device.

What just happened?

At the moment, a new window with the specified parameters of createDevice will be created, but will be instantly closed. If there is a problem with the created device, the application will receive the return 1 code.

The Irrlicht device handles everything that has to do with creating and using the window that we need to draw anything on the screen.

The createDevice method

The createDevice has seven parameters. The first one is the renderer that we will be using. Because we want our application to be platform-independent, we are going to use OpenGL, which is available for Windows, Linux, and Mac OS X.

You can also use the DirectX 8 renderer with EDT_DIRECT3D8 or the DirectX 9 renderer with EDT_DIRECT3D9 on Windows. Irrlicht also provides two software renderers that are EDT_ SOFTWARE and EDT_BURNINGSVIDEO. If the first parameter is set to EDT_NULL, there won't be any window created.

The second parameter sets the window size, while the third parameter sets the color depth, which should be set to either 16 bit or 32 bit. If the application is going to be run in windowed mode, this parameter might be ignored and the color depth of the created window will be set to the depth of the desktop.

The fourth parameter determines whether or not the application should run in windowed or fullscreen mode. If the parameter is set to true the application will launch in fullscreen mode. If this is the case the sixth parameter is a boolean flag that can switch vertical synchronization (vsync) on or off.

The fifth parameter specifies whether to use the stencil buffer or not. If we would need to draw shadows, we need to set this parameter to true, but for now, we can leave this to false.

The seventh parameter should be used if we are going to use an event receiver; that does not interest us yet.

The "game loop"

You already know while and for loops, so what's the deal with this alleged "game loop"? In game development, we usually have a scene that needs to be updated in every frame. We would need to check for game logic events, like checking for collisions or if the player has won or lost the game then update the scene accordingly. The Irrlicht 3D graphics engine uses the same approach. Assume your application is like an interactive movie, each frame redraws the complete screen.

Time for action – creating the "game loop"

Let's create our game loop:

The "game loop" is a simple while loop. We will have to redraw each frame as long as the device is running.

You should see a blank window created as follows, if it runs successfully:

What just happened?

We just succeeded in creating our first application with Irrlicht that displays a window with a plain white background. To be able to draw within our "game loop", we need to get information about the video driver we are using. To save us some work, by not having to write device->getVideoDriver() each time, we would need something from the video driver; we define a variable that gets an instance from the video driver. You may have noticed the I in front of the type IVideoDriver tells you that this type is an interface. Irrlicht relies heavily on interfaces to be able to use different renderers under a common API.

beginScene

Drawing graphics to the display screen directly, every time, can cause the flickering artifact. To avoid this problem a method called double buffering is widely used. The idea is to use a secondary back buffer before drawing to the actual screen. So the renderer will draw on that back buffer first. Only once the drawing is finished, it'll flip the back buffer with the front buffer. The first parameter of beginScene method specifies if the back buffer should be cleared and set to true by default. The second parameter specifies whether to clear the Z buffer.

The third parameter is the color that will be used to clear the back buffer. The color type consists of four values alpha, red, green, and blue ranging from 0 to 255.

This method has to be called first before any rendering occurs.

endScene

The endScene method flips the screen buffers and draws everything on the screen.

Have a go hero – creating the fade-in/fade-out effect

Now that we have set up our base application with a white background, let's try to integrate a fade-in and fade-out effect into our application. If the background is white, we want to slowly fade to a black background and vice versa. So basically, you'll have to play around with the color values inside your game loop.

However, the preceding approach contains a new concept that is called frame independent update. Before starting any rendering, we calculate the total time (ticks) difference between each frame, and multiply that with the rate we want to use for fade-in, fade-out. This way we can achieve a smooth transition across different PCs. Otherwise, if you just use a constant value to subtract or add to the color values, your program will fade-in/out very fast on fast computers.

Summary

We set up our development environment and created our first application.

Alerts & Offers

Series & Level

We understand your time is important. Uniquely amongst the major publishers, we seek to develop and publish the broadest range of learning and information products on each technology. Every Packt product delivers a specific learning pathway, broadly defined by the Series type. This structured approach enables you to select the pathway which best suits your knowledge level, learning style and task objectives.

Learning

As a new user, these step-by-step tutorial guides will give you all the practical skills necessary to become competent and efficient.

Beginner's Guide

Friendly, informal tutorials that provide a practical introduction using examples, activities, and challenges.

Essentials

Fast paced, concentrated introductions showing the quickest way to put the tool to work in the real world.

Cookbook

A collection of practical self-contained recipes that all users of the technology will find useful for building more powerful and reliable systems.

Blueprints

Guides you through the most common types of project you'll encounter, giving you end-to-end guidance on how to build your specific solution quickly and reliably.

Mastering

Take your skills to the next level with advanced tutorials that will give you confidence to master the tool's most powerful features.

Starting

Accessible to readers adopting the topic, these titles get you into the tool or technology so that you can become an effective user.

Progressing

Building on core skills you already have, these titles share solutions and expertise so you become a highly productive power user.