Now that we've set up our new personal project, and written the main game loop, we're ready to add a NeL 3D text context and write "Hello, World!" in the center of the screen.
First, open the main.cpp
file in your ryzomcore/personal
project folder, and create a new class including the necessary headers and a member variable for the text renderer, inheriting from CDriver:
class CTextMyGame : public CDriver
{
public:
CTextMyGame();
void gameLoop();
private:
NL3D::UTextContext *m_TextContext; // The text context
};
In the constructor method, initialize the text renderer using the createTextContext()
method of the NL3D::UDriver
class.
CTextMyGame::CTextMyGame()
: CDriver()
{
// Initialize the text renderer
m_TextContext = m_Driver->createTextContext("../../ryzom/tools/leveldesign/master/n019003l.pfb"); // Note: This file path is relative to the `ryzomcore/build/bin` directory
if (!m_TextContext)
{
nlerror("Failed to create text renderer");
return;
}
m_TextContext->setFontSize(24);
}
Here, the createTextContext()
function takes a single parameter, which is the font file to use for rendering text. You should replace "../../ryzom/tools/leveldesign/master/n019003l.pfb" with the path to your desired font file.
The setFontSize()
method sets the font size for the text renderer.
The text renderer is taken care of by m_Driver->release()
, so there's no point in a destructor releasing the text renderer.
In CDriver, add a public virtual gameLoop
abstract member. This is what the driver will have to actually do:
class CDriver : public NLMISC::IEventListener
{
public:
CDriver();
~CDriver();
void run();
virtual void gameLoop() abstract;
//...
}
In the run()
method of CDriver, add a call to gameLoop()
:
void CDriver::run()
{
// Main driver loop
while (m_Driver->isActive() && !m_CloseWindow)
{
//...
m_Driver->clearBuffers(NLMISC::CRGBA(0, 0, 128));
// Actual gameLoop call
gameLoop();
// Swap buffers
m_Driver->swapBuffers();
}
}
Add the gameLoop()
method to CTextMyGame. It will update the text renderer and display the "Hello, World!" message on the screen.
void CTextMyGame::gameLoop()
{
// Update the text renderer
m_TextContext->setHotSpot(NL3D::UTextContext::MiddleMiddle);
m_TextContext->setColor(NLMISC::CRGBA(255, 255, 255));
m_TextContext->printfAt(0.5f, 0.5f, "Hello, World!");
}
Here, the setHotSpot()
method defines the anchor point for the text, and the setColor()
method sets the color of the text. The printfAt()
method renders the text on the screen at the specified x and y coordinates. In this case, the coordinates are (0.5, 0.5), which corresponds to the center of the screen.
In the main()
method, change the type of mygame
to CTextMyGame:
int main(int argc, char *argv[])
{
//...
// Defining the game
CTextMyGame myGame;
// Run the game
myGame.run();
return EXIT_SUCCESS;
}
Compile and run your project. You should see the "Hello, World!" message displayed in the center of the screen.
Here is the complete source code for the tutorial project:
// Driver container class
#include <nel/3d/u_driver.h>
class CDriver : public NLMISC::IEventListener
{
public:
CDriver();
~CDriver();
void run();
virtual void gameLoop() abstract;
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));
// Actual gameLoop call
gameLoop();
// Swap buffers
m_Driver->swapBuffers();
}
}
// Handle events
void CDriver::operator()(const NLMISC::CEvent &event)
{
// Handle event
if (event == NLMISC::EventCloseWindowId)
m_CloseWindow = true;
}
#include <nel/3d/u_text_context.h>
class CTextMyGame : public CDriver
{
public:
CTextMyGame();
void gameLoop();
private:
NL3D::UTextContext *m_TextContext; // The text context
};
CTextMyGame::CTextMyGame()
: CDriver()
{
// Initialize the text renderer
m_TextContext = m_Driver->createTextContext("../../ryzom/tools/leveldesign/master/n019003l.pfb"); // Note: This file path is relative to the `ryzomcore/build/bin` directory
if (!m_TextContext)
{
nlerror("Failed to create text renderer");
return;
}
m_TextContext->setFontSize(24);
}
void CTextMyGame::gameLoop()
{
// Update the text renderer
m_TextContext->setHotSpot(NL3D::UTextContext::MiddleMiddle);
m_TextContext->setColor(NLMISC::CRGBA(255, 255, 255));
m_TextContext->printfAt(0.5f, 0.5f, "Hello, World!");
}
// Main function
int main(int argc, char *argv[])
{
// Create the application context
NLMISC::CApplicationContext applicationContext;
// Defining the game
CTextMyGame myGame;
// Run the game
myGame.run();
return EXIT_SUCCESS;
}