Tutorial 2: Hello World

In this tutorial you will learn how to create a renderer and put a sprite on the screen.

Before starting this tutorial be sure to setup an empty project with the Setup Tutorial.

#include <NessEngine.h>

 

int _tmain(int argc, _TCHAR* argv[])

{

    Ness::init();

    Ness::Renderer renderer("new project", Ness::Sizei(800, 600));

}

That's it. :)

You managed to create a scene and render! let's continue to next tutorial and learn about transformations!
 
continue to next tutorial -->

Ness::Utils::EventsPoller EventsPoller;

Ness::Utils::ApplicationEvents app;

EventsPoller.add_handler(app);

 

while( !app.got_quit() )

{

    EventsPoller.poll_events();

}

#include <NessEngine.h>

 

int _tmain(int argc, _TCHAR* argv[])

{

    Ness::init();

    Ness::Renderer renderer("new project", Ness::Sizei(800,600));

 

    Ness::ScenePtr scene = renderer.create_scene();

    Ness::SpritePtr sprite = scene->create_sprite("ness-engine/resources/gfx/hello_world.png");

 

    Ness::Utils::EventsPoller EventsPoller;

    Ness::Utils::ApplicationEvents app;

    EventsPoller.add_handler(app);

 

    while( !app.got_quit() )

    {

        EventsPoller.poll_events();

 

        renderer.start_frame();

        scene->render();

        renderer.end_frame();

    }

}

Ness::ScenePtr scene = renderer.create_scene();

Ness::SpritePtr sprite = scene->create_sprite("ness-engine/resources/gfx/hello_world.png");

renderer.start_frame();

scene->render();

renderer.end_frame();

what are we going to get?

at the end of this tutorial we will have this code:

which will produce the following window:

If you are more of a "hands-on" type of programmer you can just copy the code and go play with it. if you want to break it down and understand it step by step, please continue reading:

 
Step 1: create a renderer

This tutorial assume you already followed the first tutorial of how to setup a ness-engine project, and you now have an empty project ready to run.

 

first thing we do is to init ness-engine and create a renderer:

Ness::init() is the engine init function that setup some internal libs. it must be called once before using ness-engine objects.

 

Ness::Renderer is our main rendering class, which is shared among all ness-engine entities. if you are familiar with SDL2 you should know the ness-engine Renderer actually wraps the SDL2 renderer, and extends it's functionality.

 

when creating a renderer, it receive the following parameters:

windowName: the name to give to the main application window (and caption).

screenSize: resolution / window size.

windowFlags: flags related to creating the window.

rendererFlags: different init flags we will cover at later tutorials.

you can read more about them in the function documentation in the header file.

 

Ness::Sizei is a class that represent an integer size (has int x and int y). ness-engine comes with many built-in helpers that makes handling basic types such as vectors and colors an easy task. 

 

Now when you compile and run the application you will see a window opening for a moment and immediatly closes. this is because there is nothing to keep the application running. time to create the main loop.

 

Renderer size

It's important to understand the difference between screen size and renderer size.

screen size is the size of the window you create, and if you work in fullscreen mode - the resolution.

renderer size is the actual size of the renderer and this will effect the size (in pixels) of the things you render. by default the renderer size is equal to the screen size, but you can set it to a different value. for example, you can set screen size of 1280x1024 and renderer size of 800x600. the result would be that the window/resolution will be 1280x1024, but all the renderings will be scaled to fit resolution size of 800x600. you can use renderer size to create resolutions that don't normally exist in modern monitors.

 

to set renderer size use the function set_renderer_size() after creating the renderer.

 

Step 2: main loop & events

A "main loop" is basically an endless loop that runs as long as your application is running. let's create our main loop to keep the application alive. add the following code after creating the renderer:

It doesn't do much now, but now when you run the application it will keep the window alive.

 

Ness::Utils::EventsPoller is an object that polls system events from the events queue. this include events like when the window is focused, minizied, moved, quit, etc.. without handling events inside the main loop, the operating system will think our application is stuck.

 

Ness::Utils::ApplicationEvents is an event handler for general application events. we create it in this example because it handles the system quit event, which is our ending loop condition (app.got_quit()). note that you don't have to use event handlers to fetch events, you can also poll them manually and parse them yourself, using the Ness::poll_event() function.

you will learn more about events in later tutorials.

 

EventsPoller.poll_events() is the function that tells the EventsPoller to fetch all events from the queue and send them to the handlers. must be called inside the main loop to keep the application from getting stuck.

 

Step 3: create a scene and a sprite

You can think of it this way: if your game is a play, then the scene is your stage and the sprites are your actors. there are other type of entities you can put in a scene, but we will cover them later.

 

To be more precise, a scene is a container with rendering settings that you put renderable entities inside. the scene will handle the rendering overhead of these entities.

 

An entity is simply something you can render on the screen.  you can read more about this subject here.

 

So let's create a scene and a sprite:

Pretty simple huh?

 

The Sprite is the most common entity you will use: it's an entity that renders a texture from a given file. the texture is fully managed and loaded automatically, and will be cleared from memory once there are no more objects using it.

 

now let's render our new scene. add the following code inside the main loop:

renderer.start_frame() makes the renderer ready to receive rendering requests.

scene->render() renderes your scene. it must be called after start_frame()

renderer.end_frame() finish the rendering for the current frame and present everything on the screen (swap buffers, if you are familiar with OpenGL/DirectX terminology).

 

start_frame and end_frame actually do a lot more then describe here; these functions manage time factor, animators, etc.. these subjects will be covered in later tutorials.

 

What about cleanup?

Being a CPP developer you are probably wondering what about the cleanup code. for most cases in ness-engine cleanup is not something you should worry about. as mentioned before, the textures and resources are managed automatically. the scene & sprite pointers are also managed (shared_ptrs), and these objects will be deleted as soon as they are no longer referenced.

 

Note that your sprite is also referenced by the scene containing it, so even if you lose the sprite pointer it will continue to exist and render, as long as the scene exist. when the scene is deleted, so will all the entities inside it that do not have any external references.

 

If you run your project in debug you can see useful prints on the console window that will provide you with more information.

 

Working Example

You can find a working example of this tutorial here.

Note: ness-engine path in the examples is different then in the tutorials, so make sure to fix the path of the resources if you copy the code.

profile on indiedb

Help ness-engine grow!