We've just prepared a new personal project that initializes the NeL application context. This tutorial explains how to set up the NeL 3D graphics driver, implement a basic game loop, and handle window events.
Open the main.cpp
file in your ryzomcore/personal
folder, to include the necessary headers and add a member variable for the NL3D driver to the game class:
// Main game class
#include <nel/3d/u_driver.h>
class CDriver
{
public:
CDriver();
~CDriver();
void run();
protected:
NL3D::UDriver *m_Driver; // The graphic driver
};
In the constructor method, initialize the graphics driver and open a blank window.
To initialize the graphics driver, use the createDriver()
method of the NL3D::UDriver
class. If the driver cannot be created, display an error message using the nlerror()
method.
Then initialize the window using the setDisplay()
method of the driver. You can pass in a NL3D::UDriver::CMode
object to specify the dimensions and color depth of the window. You can also set the window title using the setWindowTitle()
method of the driver.
CDriver::CDriver()
{
// Initialize the graphics driver
m_Driver = NL3D::UDriver::createDriver();
if (!m_Driver)
{
nlerror("Failed to create driver");
return;
}
// Initialize the window
m_Driver->setDisplay(NL3D::UDriver::CMode(800, 600, 32));
// Set the window title
m_Driver->setWindowTitle(ucstring("My Game"));
}
In the destructor, release any resources used.
CDriver::~CDriver()
{
// Release the driver's resources
m_Driver->release();
delete m_Driver;
}
Implement a basic game loop in the run()
method.
This loop should repeat until the window is closed or the application is exited. You must check the isActive()
method of the graphics driver to verify if the window still exists. In order for the window to receive event messages, such as user input, from the window manager, the events will be received using the pump()
method on the EventServer
of the driver.
Use the clearBuffers()
method of the driver to clear the screen with a specified color, and swapBuffers()
to display the updated screen.
void CDriver::run()
{
// Main driver loop
while (m_Driver->isActive())
{
// Update window messages
m_Driver->EventServer.pump();
// Clear the screen
m_Driver->clearBuffers(NLMISC::CRGBA(0, 0, 128));
// Swap buffers
m_Driver->swapBuffers();
}
}
Now, compile and run your project. When running your project, you should see a blank window with the title "My Game". However, it will stay open when you try to close it.
To make the window close, you must register a listener for the relevant window event.
Modify the game class to inherit from NLMISC::IEventListener
.
You'll also need a variable in your class to flag when the window is being closed.
The release()
call on the driver will define the behaviour when you ask the window to close.
class CDriver : public NLMISC::IEventListener
{
public:
CDriver();
~CDriver();
void run();
virtual void operator()(const NLMISC::CEvent &event) NL_OVERRIDE;
private:
bool m_CloseWindow;
protected:
NL3D::UDriver *m_Driver; // The graphic driver
};
Implement the event handler for the window close message, and update the main loop to exit when the close event has been flagged.
// Handle events
void CDriver::operator()(const NLMISC::CEvent &event)
{
// Handle event
if (event == NLMISC::EventCloseWindowId)
m_CloseWindow = true;
}
void CDriver::run()
{
// Main driver loop
while (m_Driver->isActive() && !m_CloseWindow)
{
// ...
}
}
Initialize the flag, and register the listener to handle the window close event.
CDriver::CDriver()
: m_CloseWindow(false)
{
// ...
// Add event listeners
m_Driver->EventServer.addListener(NLMISC::EventCloseWindowId, this);
// Initialize the window
// ...
}
The window should now remain open until you close it manually.
Here's the complete source of the tutorial project so far.
// Driver container class
#include <nel/3d/u_driver.h>
class CDriver : public NLMISC::IEventListener
{
public:
CDriver();
~CDriver();
void run();
virtual void operator()(const NLMISC::CEvent &event) NL_OVERRIDE;
private:
bool m_CloseWindow;
protected:
NL3D::UDriver *m_Driver; // The graphic driver
};
// Initialize game resources
CDriver::CDriver()
: m_CloseWindow(false)
{
// Initialize the graphics driver
m_Driver = NL3D::UDriver::createDriver();
if (!m_Driver)
{
nlerror("Failed to create driver");
return;
}
// Add event listeners
m_Driver->EventServer.addListener(NLMISC::EventCloseWindowId, this);
// Initialize the window
m_Driver->setDisplay(NL3D::UDriver::CMode(800, 600, 32));
// Set the window title
m_Driver->setWindowTitle(ucstring("My Game"));
}
// Release game resources
CDriver::~CDriver()
{
// Release the driver's resources
m_Driver->release();
delete m_Driver;
}
// Main loop
void CDriver::run()
{
// Main driver loop
while (m_Driver->isActive() && !m_CloseWindow)
{
// Update window messages
m_Driver->EventServer.pump();
// Clear the screen
m_Driver->clearBuffers(NLMISC::CRGBA(0, 0, 128));
// Swap buffers
m_Driver->swapBuffers();
}
}
// Handle events
void CDriver::operator()(const NLMISC::CEvent &event)
{
// Handle event
if (event == NLMISC::EventCloseWindowId)
m_CloseWindow = true;
}
// Main function
int main(int argc, char *argv[])
{
// Create the application context
CApplicationContext applicationContext;
// Defining the game
CDriver myGame;
// Run the game
myGame.run();
return EXIT_SUCCESS;
}
At this point, you should have set up a personal NeL project, configured CMake, initialized the NeL 3D driver, opened a blank window, and implemented a basic game loop.