first line register the camera into the renderer animators queue. you must do so to make the animation work automatically every frame. you also need to unregister the camera when you're done. you can read more about animators here.

 

the second line actually set the target the camera will focus on, always keeping it in the center of the screen.

 

by default, the camera will always "teleport" to the right position to keep target in the center. however, if you want the camera to slowly "move" into the desired position, you can set following speed:

Tutorial 4: Camera & keyboard movement

In this tutorial you will learn how to create a camera object and move it with the keyboard.

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

    Ness::SpritePtr back = scene->create_sprite("ness-engine/resources/gfx/forest_background.jpg");

    back->set_scale(1.5f);

That's it. :)

Now that you know about cameras, input & and time delta, it's time to learn about scene nodes!
 
continue to next tutorial -->

#include <NessEngine.h>

 

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

{

    Ness::init();

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

 

    // create the scene and the background sprite

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

    Ness::SpritePtr back = scene->create_sprite("ness-engine/resources/gfx/forest_background.jpg");

    back->set_scale(1.5f);

 

    // create camera

    Ness::CameraPtr camera = renderer.create_camera();

    const float CamSpeed = 150.0f;

 

    // events handlers

    Ness::Utils::EventsPoller EventsPoller;

    Ness::Utils::ApplicationEvents app;

    EventsPoller.add_handler(app);

    Ness::Utils::Keyboard keyboard;

    EventsPoller.add_handler(keyboard);

 

    while( !app.got_quit() )

    {

        EventsPoller.poll_events();

 

        // move camera up

        if (keyboard.key_state(SDLK_UP) && camera->position.y > 0) {

                camera->position.y -= renderer.time_factor() * CamSpeed;

        }

 

        // move camera down

        if (keyboard.key_state(SDLK_DOWN) &&

            camera->position.y < back->get_absolute_size().y - renderer.get_screen_size().y) {

                camera->position.y += renderer.time_factor() * CamSpeed;

        }

 

        // move camera left

        if (keyboard.key_state(SDLK_LEFT) && camera->position.x > 0) {

                camera->position.x -= renderer.time_factor() * CamSpeed;

        }

 

        // move camera right

        if (keyboard.key_state(SDLK_RIGHT) &&

            camera->position.x < back->get_absolute_size().x - renderer.get_screen_size().x) {

                camera->position.x += renderer.time_factor() * CamSpeed;

            }

 

        // render

        renderer.start_frame();

        scene->render(camera);

        renderer.end_frame();

    }

}

    Ness::CameraPtr camera = renderer.create_camera();

    const float CamSpeed = 150.0f;

    Ness::Utils::Keyboard keyboard;

    EventsPoller.add_handler(keyboard);

        // move camera up

        if (keyboard.key_state(SDLK_UP) && camera->position.y > 0) {

                camera->position.y -= renderer.time_factor() * CamSpeed;

        }

        // move camera down

        if (keyboard.key_state(SDLK_DOWN) &&

            camera->position.y < back->get_absolute_size().y - renderer.get_screen_size().y) {

                camera->position.y += renderer.time_factor() * CamSpeed;

        }

        // move camera left

        if (keyboard.key_state(SDLK_LEFT) && camera->position.x > 0) {

                camera->position.x -= renderer.time_factor() * CamSpeed;

        }

 

        // move camera right

        if (keyboard.key_state(SDLK_RIGHT) &&

            camera->position.x < back->get_absolute_size().x - renderer.get_screen_size().x) {

                camera->position.x += renderer.time_factor() * CamSpeed;

            }

        renderer.start_frame();

        scene->render(camera);

        renderer.end_frame();

entity->set_static(true);

what are we going to get?

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

which will produce the following window:

when pressing the arrow keys the camera will move around and reveal different parts of the background. let's go over the code

 

Step 1: creating the background

This is nothing special, all we do is create the sprite with the background image and scaling it by 1.5f so it will cover more space:

CamSpeed is a factor we'll use later when moving the camera.

 

Step 3: create keyboard handler

Remember the events poller, an object that poll operating system events and pass them to handlers? so far we only had ApplicationHandler which we used to respond when the application gets shut down. now we create a new handler, KeyboardHandler, which handle keyboard events for us:

we will use it inside the main loop, in later step.

 

Step 4: camera movement

Let's begin from the code to move the camera up:

First we call keyboard.key_state(SDLK_UP) to check if arrow-up key is down. if so, we also validate that the position of the camera is not negative, so we won't move the camera out of background bounderies.

 

If both conditions are met, we move the camera up based on CamSpeed which we defined above. but what about that renderer.time_factor() part?

 

time_factor is the time it took the renderer to complete the rendering of the last frame (1.0f == one second), between the start_frame() and end_frame() calls. we use this factor to multiply all animations with it. this way we make sure that everything moves on the same speed regardless of the computer performance and FPS count. the more FPS the player has the smoother the animations will be, while less FPS makes a more "laggy" animation.  this is called delta timing.

 

now let's move camera down:

Note the back->get_absolute_size() call. this function returns the absolute size of the given sprite, with all the transformations included.

 

moving camera left and right is pretty much the same, only on X axis:

Note the camera being used as a paremeter for 'render()'.

 

Static entities

You might want to have some of your entities static, i.e. not affected by camera. for example, you might want to create a background that covers the entire screen and does not move. one way to do it is to put it in a different scene and render it without camera, but a more simple option is available for you:

all built-in renderables support this option, which will make them ignore the camera position.

 
Out of sight - Out of mind

Don't waste your time hiding objects that are not within camera; ness-engine does that automatically for you. all objects that are currently out of screen will not be rendered and will barely cost you any CPU (and zero GPU).

 

note that this optimization also exist when you don't use camera (no camera is equivalent to camera at position 0, 0)

 

Camera follow

In many cases you would want your camera to follow a given entity or node position, always keeping the target in the center of the screen.

 

to do so, the camera object comes with a built-in following functionality:

Step 2: creating the camera

Creating a camera object is very easy:

Step 5: rendering with camera

now it's time to render everything with our camera object:

renderer.register_animator(camera);

camera->set_target(target);

camera->set_target_follow_speed(Ness::Point(150.0f, 150.0f));

as you can see you can provide different speed for X and Y axis movement. when setting limited following speed you can also set the maximum distance yo allow the camera to drift away from the target, in case the target is moving faster then the camera:

camera->set_target_follow_max_distance(Ness::Point(100.0f, 100.0f));

one last thing to note is you can also set offset for the target position. for example, if you want the camera to follow not the object itself but 50 pixels above it, you can use this:

camera->set_target_follow_offset(Ness::Point(0.0f, -50.0f));

Help ness-engine grow!