hello_world - ryzom/ryzomcore GitHub Wiki


title: Create a Hello World sample application description: An introduction to NeL programming published: true date: 2023-05-27T23:18:50.627Z tags: editor: markdown dateCreated: 2022-03-07T02:32:57.317Z

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.

Add necessary headers and member variables

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
};

Initialize the text renderer

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.

Release 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.

Add a gameLoop to CDriver

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;
  //...
 }

Call the gameLoop

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();
	}
}

Render the text

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.

Test the application

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.

Complete source code

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;
}

What's next

⚠️ **GitHub.com Fallback** ⚠️