domingo, 27 de octubre de 2013

First Experiments with Qt and SFML

Hi!

I just wanted to share my first attempts to effectively use the Qt and SFML integration I showed you in the previous post. My goal is to build a simple, yet useful level editor for a 2d platform game I'm developing. As you will see, there's still much to do, but it's a beginning.

NOTE: the video seems to show buggy rendering, but it's just a matter of the screen capturer software. The renderer is completely clean and fluent (for the moment, at least :). 



jueves, 24 de octubre de 2013

Qt 5 and SFML 2.0 Integration

Hi all!

Today, I'm gonna show you my last fight and victory (for now :)). The goal: integrating SFML with Qt. Yeah, too many abbreviations... ok, let's go step by step.

SFML, as mentioned in earlier posts, is an efficient, easy to learn library that wraps OpenGL as a set of higher-level classes and methods. As its main purpose is to draw (or technically, render) things on the screen, it is usually referred as a renderer library. But it doesn't go beyond that: it's not a framework that manages the screen by screen graphs or trees, such as Ogre3D, for example. It is just a nicer entry point to OpenGL.

On the other hand, Qt (pronounced 'cute'), is a framework for developing Graphical User Interfaces (GUI) applications. As such, it provides an API to let developers create buttons, windows, labels, etc in an easy manner. Its (very) complete API also allows developers to render things on the windows. 

The question is: why would it be a good idea to integrate these two libraries? Well, SFML is a very good renderer, but it lacks the capability to create complex GUIs, whereas Qt has the opposite pros and cons. Therefore, the integration yields the breeding ground for nice game tools development, for instance, a level editor. And this is actually the reason why I wanted this integration. I can take advantage of my current knowledge of SFML, and just need to learn some concrete parts of Qt, concretely, the parts for drawing windows stuff (toolbars, menus, etc) and for receiving interaction events from the user.

In addition, Qt brings a very complete IDE (Integrated Development Environment) for C++, which according to many people in forums, it is better if you want to work in C++ than XCode (the Mac OS default IDE), which is more fine-tuned to work with Objective-C. The Qt IDE is called Qt Creator.

First of all, the specification of the problem:
Operating System: Mac OS X 10.7.5
Qt: 5.5.1 (Clang 3.1, 64 bit) -> Clang is the name of the C++ compiler to be used and is installed automatically when you install Qt.
Qt Creator: 2.8.1
SFML: 2.0

Once you have downloaded everything you need (correct SFML and Qt packages), you must follow the following steps:

1) Open a new Qt Creator project. You have to let Qt Creator know where it can find the headers and libraries of SFML. You can copy the following lines and paste them in the .pro file of the Qt Creator project. IMPORTANT: Everything between '< >' must be set appropriately according to your installation settings.

### TO ALLOW SFML LIBRARY ###
CONFIG_APP_NAME = <Name of your application (in Qt Creator)>
INCLUDEPATH += <Path of installation of SFML>/SFML/include
DEPENDPATH += <Path of installation of SFML>/SFML/include
CONFIG(release, debug|release): 
LIBS += -L/<Path build of SFML>/SFML-build/lib -lsfml-audio 
-lsfml-graphics -lsfml-network -lsfml-window -lsfml-system
CONFIG(debug, debug|release): 
LIBS += -L<Path build of SFML>/SFML-build/lib -lsfml-audio-d 
-lsfml-graphics-d -lsfml-network-d -lsfml-window-d -lsfml-system-d
macx {
    QMAKE_POST_LINK += $(MKDIR) 
$${CONFIG_APP_NAME}.app/Contents/Frameworks &&
    QMAKE_POST_LINK += $${QMAKE_COPY} -r 
<Path build of SFML>/SFML-build/lib/* 
$${CONFIG_APP_NAME}.app/Contents/Frameworks
}

Before macx, we're simply doing what I explained: more precisely, we are telling to the compiler where it can find the SFML headers, and to the linker where it can find the SFML libraries. The instructions after the macx (which are QMake instructions), make the following: first, it creates a directory called Framework under <Application path>.app/Contents/, and then, it copies the SFML libraries in this directory. Why? Because the Mac OS loader reads the binaries of these libraries from this location. As simple as that. If you want to avoid problems, I suggest you at this point disallowing 'Shadow build' in Qt Creator (more information here).

2) Once these configuration issues are solved, let's perform the actual integration. As explained here, Qt extensions are done by means of extending QWidget class. So, we have to create a new QWidget, which is the SFML RenderWindow. The code changes a bit with respect to the SFML 1.6 tutorial. I'm simply going to paste here the raw code you will need for the different files. For a proper explanation though, I suggest you to read the aforementioned tutorial. 

QSFMLCanvas.h
#ifndef QSFMLCANVAS_H
#define QSFMLCANVAS_H
#include <QWidget>
#include <SFML/Graphics.hpp>
#include <QTimer>
class QSFMLCanvas : public QWidget, public sf::RenderWindow
{
//Q_OBJECT
public:
explicit QSFMLCanvas(QWidget *parent, const QPoint& Position, const QSize& Size, unsigned int FrameTime = 0);
virtual void showEvent(QShowEvent*);
virtual QPaintEngine* paintEngine() const;
virtual void paintEvent(QPaintEvent*);
virtual ~QSFMLCanvas();
virtual void OnInit();
virtual void OnUpdate();
private:
QTimer myTimer;
bool myInitialized;
};
#endif // QSMLCANVAS_H


QSFMLCanvas.cpp
#include "qsfmlcanvas.h"
#ifdef Q_WS_X11
#include <Qt/qx11info_x11.h>
#include <X11/Xlib.h>
#endif
#include <iostream>
QSFMLCanvas::QSFMLCanvas(QWidget* Parent, const QPoint& Position, const QSize& Size, unsigned int FrameTime) : QWidget(Parent),
myInitialized (false)
{
// Setup some states to allow direct rendering into the widget
setAttribute(Qt::WA_PaintOnScreen);
setAttribute(Qt::WA_OpaquePaintEvent);
setAttribute(Qt::WA_NoSystemBackground);
// Set strong focus to enable keyboard events to be received
setFocusPolicy(Qt::StrongFocus);
// Setup the widget geometry
move(Position);
resize(Size);
// Setup the timer
myTimer.setInterval(FrameTime);
}
QSFMLCanvas::~QSFMLCanvas() {}
void QSFMLCanvas::showEvent(QShowEvent*)
{
if (!myInitialized)
{
// Under X11, we need to flush the commands sent to the server to ensure that
// SFML will get an updated view of the windows
#ifdef Q_WS_X11
//XFlush(QX11Info::display());
#endif
// Create the SFML window with the widget handle
RenderWindow::create((void *) winId());
// Let the derived class do its specific stuff
OnInit();
// Setup the timer to trigger a refresh at specified framerate
connect(&myTimer, SIGNAL(timeout()), this, SLOT(repaint()));
myTimer.start();
myInitialized = true;
}
}
QPaintEngine* QSFMLCanvas::paintEngine() const
{
return 0;
}
void QSFMLCanvas::paintEvent(QPaintEvent*)
{
// Let the derived class do its specific stuff
OnUpdate();
// Display on screen
RenderWindow::display();
}
void QSFMLCanvas::OnInit() {}
void QSFMLCanvas::OnUpdate() {}


MyCanvas.h 
 #ifndef MYCANVAS_H
#define MYCANVAS_H
#include "qsfmlcanvas.h"
#include <SFML/Graphics.hpp>
class MyCanvas : public QSFMLCanvas
{
public :
MyCanvas(QWidget* Parent, const QPoint& Position, const QSize& Size);
void OnInit();
void OnUpdate();
private :
sf::Clock myClock;
sf::Texture myImage;
sf::Sprite mySprite;
};
#endif // MYCANVAS_H


MyCanvas.cpp
#include "mycanvas.h"
#include <iostream>
#include <string>
#include <QDir>
MyCanvas::MyCanvas(QWidget* Parent, const QPoint& Position, const QSize& Size) : QSFMLCanvas(Parent, Position, Size)
{
}
void MyCanvas::OnInit()
{
// Load the image
std::cout << "onInit" << std::endl;
QString dir = QDir::currentPath();
std::string utf8_text = dir.toUtf8().constData();
std::cout << "HELLO: " << utf8_text << std::endl;
if (!myImage.loadFromFile(utf8_text + "/chef.png")) {
std::cout << "Loading error"<< std::endl;
} else {
std::cout << "Image was loaded fine" << std::endl;
}
// Setup the sprite
mySprite.setTexture(myImage);
mySprite.setPosition(150, 150);
std::cout << "setting the texture of the sprite" << std::endl;
//mySprite.setCenter(mySprite.GetSize() / 2.f);
myClock.restart();
}
void MyCanvas::OnUpdate()
{
// Clear screen
RenderWindow::clear(sf::Color(0, 128, 0));
// Rotate the sprite
mySprite.rotate(myClock.getElapsedTime().asSeconds() * 100.f);
// Draw it
RenderWindow::draw(mySprite);
myClock.restart();
}


main.cpp 
#include <QApplication>
#include "mycanvas.h"
#include <QFrame>
int main(int argc, char *argv[])
{
QApplication App(argc, argv);
// Create the main frame
QFrame* MainFrame = new QFrame;
MainFrame->setWindowTitle("Qt SFML");
MainFrame->resize(400, 400);
MainFrame->show();
// Create a SFML view inside the main frame
MyCanvas* SFMLView = new MyCanvas(MainFrame, QPoint(20, 20), QSize(360, 360));
SFMLView->show();
return App.exec();
}

There is an important consideration. Qt Creator uses a special way to declare the resources (e.g. images) that your application will use. It does so in order to comply with the cross-platform requirement, but it can be quite weird for someone who is not used to it. Basically, you would need to create a Resource file. However, SFML does not understand this, and when you try to execute loadFromFile in the MyCanvas::OnInit method by using this approach, SFML does not find the image. The solution, at least temporal and for testing purposes, is that you place you image inside the <Path application>.app/Contents/MacOS directory, and that you use the piece of code that I have provided above, which will search the image in that directory.

Figure 1. Output of the program. Basically, it's a Qt frame with a SFML renderer window inside the frame. It is showing the chef, which is a sprite (which as usual has been designed by Manuela) that I'm using for an iOS game that will come out very soon :).

I think that's all. If I forgot something or you need more explanations, just let me know and I'll update the post.

EDIT: Some people following this tutorial have encountered the following error: "error: invalid conversion from 'void*' to 'sf::WindowHandle {aka HWND__*}' [-fpermissive] RenderWindow::create((void *) winId());^". This error occurs in the line RenderWindow::create((void *) winId());

The solution, which was posted here, is to change the aforementioned line to this one: RenderWindow::create(reinterpret_cast<sf::WindowHandle>(winId())); (Thanks to delio and hyde for raising the problem and the fix)

Good luck!

domingo, 13 de octubre de 2013

On Scripting Engines

Hi all!

These last days I have been reading quite a lot about scripting engines or systems and why they should be included yes or yes in any worthy game engine. When I first heard about this, I have to admit that I had a narrow vision on its possibilities, maybe because I didn't fully understand the idea behind having an embedded scripting engine. Now that I understand it better, I want to share some of my (limited) knowledge with you.

Ok, so first of all: what is a script? According to Wikipedia, scripts are 'programs written for a special run-time environment that can interpret and automate the execution of tasks which could alternatively be executed one-by-one by a human operator'. Well, actually, the truth is that there is a fading boundary between a script and a 'traditional' program. Script languages are usually interpreted, which means that their instructions are executed on the fly by the interpreter, which usually is simply a virtual machine capable of understanding the high-level script instructions and of executing them on the target machine. 

Traditionally, interpreted languages have not been considered a good choice for game programming, given the high performance requirements of this kind of software, which must run at a minimum of around 60 frames per second. However, as interpreted languages evolve and devices acquire more powerful processors, this is no longer completely this way. 


Figure 1. Scripting-enabled game engine: Visual3D Game Engine
Most game engines include scripting as part of their suite. 

Well, it is true that the performance of a C or C++-written game will never (for the moment) equal the performance of the same game written in an interpreted language (or in other higher level languages like Java). But it is indeed possible to, let's say, outsource some functionalities to be implemented by these languages.

Let's go with a simple example. Let's suppose you're doing a side-scrolling game and you want that when the player reaches a certain position in the scenario, a particle system sparks off, e.g., an explosion goes off. Let's assume that you don't know anything about scripts, so you must hard-code this effect in the game logic, which would result in something like this:

void ParticleSystem::start(Position x, Position y) {  
     for (int i = 0; i < N_PARTICLES; i++) {
          particles[i] -> start();
          particles[i] -> setVelocity(...//random velocity for each particle);
          ... //more settings
       }
}

void Particle::start() {
     p = new Particle("particle.png");
}

void Level::update() {
    //update of all the objects
   if (player.position > X_EFFECT_POSITION) {
        ParticleSystem::getInstance() -> start(player.position.x, player.position.y);
   }
}

The code is not difficult to follow. I have to check, in each update of the game for a specific level, if the player has reached the specified position. [NOTE: I simplified the code here; I think that an improved version should use the Observer pattern so that the player object itself notifies the particle system when it reaches the destination]. Then, the particle system initializes all the particles with a given image (particle.png) and sets a random velocity for each particle. So far so good. 

However, when you run your game, you notice that setting the velocity to a random number does not provide a realistic explosion effect. Ok, you change the code, compile again, and run again. Ufff... the bitmap used for the particles is not that cool. Ok, let's create a new bitmap, compile again, and test it. And you can be repeating this process dozens of times until you end up happy with the result. 

Now, let's assume that you implemented a scripting engine in your system. Let's see how the code  in your game would look like (of course, this is no real code, just a simplification, as usual):

void ScriptingEngine::explosionEffect(Position x, Position y) {
    initializeEngine(&sh); //sh stands for scripting handler
    sh.pushParameters(x, y);
    sh.executeFile("explosion.script");
}

void Level::update() {
    //update of all the objects
   if (player.position > X_EFFECT_POSITION) {
        ScriptingEngine::getInstance() -> explosionEffect(player.position.x, player.position.y);
   }
}

And now, we create a .script file that will do exactly what the older code did: 

//explosion.script//
Begin Script 
   player.position.x = popParameter(1);
   player.position.y = popParamenter(2);
   image = loadParticleImage("particle.png");   
   ... //code that creates all the particles with random velocity
End Script

Basically, you communicate the required arguments (pushParameters) from the host language (e.g. C++) to the scripting system. Then, the scripting engine executes the explosion effect implemented in the file.

Now, you compile and execute. Mmmm... you're not happy with the particle bitmap or with the velocity of the particles. Let's change all that. Need to recompile again every time? No! Because the effect is completely loaded in the script, you only have to change the .script file and execute the game again. The game engine has outsourced the explosion effect to a scripting system, and this provides higher flexibility and effectiveness. The explosion effect is totally decoupled from the game logic, so any change in the effect doesn't alter the game logic and vice versa. 

This is a really powerful feature that pushes the development experience forward. The possibilities of this approach are unlimited: faster testing and debugging, easy change of characters behaviour, improved extensibility of the game (capability of adding new features effortless), and much more!. And even better: you could provide a terminal with the game so that you can write script commands while the game is running, and you would see the changes immediately at runtime, without the need for restarting it.

From a design perspective, the biggest challenge is to know which parts of the game are worth this outsourcing. If you read enough about it, you'll get the following answer: delegate to the scripting system any aspect of the game that has no significant performance impact. In my opinion, this can be re-formulated as follows: do not call the script engine once per frame. Anything that needs to be executed once per frame should be implemented in the host language (e.g. C++). But any effect or event that does not occur every frame is a great candidate to be delegated to the scripting engine. The more you export (with unnoticeable performance degradation), the higher the productivity boost you will experience.

Regarding the scripting language to choose, there are lots of them out there, and the decision is likely to depend on the host language. For C++, for example, it's common to see bindings with Python and Lua, given that they are lightweight (specially the latter) and are implemented in C. I'm currently looking at Lua because I know that it's being used currently in many commercial games and the API seems to be simple enough. I'll let you know about my progress soon.

Hope this post was interesting, or at least that you learned something new from it. Don't hesitate to ask or comment anything you want. 

See you!