DEV Community

Noah11012
Noah11012

Posted on • Edited on

9 1

Using SDL2: Viewports

When rendering a scene or world not everything will be inside the boundaries of the window. Only a partial region can be rendered and displayed to the user at a time. In SDL (and generally in GC) this region is also known as the viewport. Anything within the viewport is rendered and everything outside is ignored. Many games have a character that can move and perform operations within in a world. Depending on where the character moves, the viewport must move with it to keep the character in focus.

As an example to demonstrate viewports in SDL, we will have a program that can zoom and move around in a world that is basically an image of a house and tree.

In previous posts, we have the Appplication class that handles window events, updating entities and lastly rendering. However, unlike in the previous installments, we will have an extra method named handle_zoom(). This method handles the user zoom when the event SDL_KEYDOWN is detected.



void Application::loop()
{
    bool keep_window_open = true;
    while(keep_window_open)
    {
        while(SDL_PollEvent(&m_window_event) > 0)
        {
            switch(m_window_event.type)
            {
                case SDL_QUIT:
                    keep_window_open = false;
                    break;

                case SDL_KEYDOWN:
                    handle_zoom();
            }
        }

        update(1.0/60.0);
        draw();
    }
}


Enter fullscreen mode Exit fullscreen mode

Because I decided on using transparency for the image's background, I had to use the SDL2 image extension library for opening PNG images. In the constructor, the image library is initialized and the image we will use is loaded into memory.



Application::Application()
{
    // ...

    m_render_viewport = { 0, 0, 680, 480 };

    IMG_Init(IMG_INIT_PNG);

    SDL_Surface *image_surface = IMG_Load("world.png");
    m_image = SDL_CreateTextureFromSurface(m_window_renderer, image_surface);
    SDL_FreeSurface(image_surface);
}


Enter fullscreen mode Exit fullscreen mode

In past articles when using an image, we loaded the image's pixel data into an SDL_Surface *, converted it into an SDL_Texture, and finally, queried for the texture's width and height. We do the first two here, but not the last. m_render_viewport takes care of what part of the image gets rendered onto the screen.

Now finally, I can show the method that makes all the magic happens:



void Application::handle_zoom()
{
    unsigned char const *keys = SDL_GetKeyboardState(nullptr);
    if(keys[SDL_SCANCODE_UP])
    {
        m_render_viewport.w += 5;
        m_render_viewport.h += 5;
    } else if(keys[SDL_SCANCODE_DOWN])
    {
        m_render_viewport.w -= 5;
        m_render_viewport.h -= 5;
    }
    else if(keys[SDL_SCANCODE_W])
    {
        m_render_viewport.y += 20;
        if(m_render_viewport.y > 0)
            m_render_viewport.y = 0;
    } else if(keys[SDL_SCANCODE_S])
    {
        m_render_viewport.y -= 20;
        if(m_render_viewport.y < -720)
            m_render_viewport.y = -720;
    } else if(keys[SDL_SCANCODE_A])
    {
        m_render_viewport.x += 20;
    } else if(keys[SDL_SCANCODE_D])
    {
        m_render_viewport.x -= 20;
        if(m_render_viewport.x < -1280)
            m_render_viewport.x = -1280;
    }
}


Enter fullscreen mode Exit fullscreen mode

This merely manipulates the viewports location and dimensions. In the Application::draw() method, we set the viewport and render.



void Application::draw()
{
    SDL_SetRenderDrawColor(m_window_renderer, 255, 255, 255, 255);
    SDL_RenderClear(m_window_renderer);
    SDL_RenderCopy(m_window_renderer, m_image, nullptr, nullptr);
    SDL_RenderSetViewport(m_window_renderer, &m_render_viewport);
    SDL_RenderPresent(m_window_renderer);
}


Enter fullscreen mode Exit fullscreen mode

Compile and run.

Of course, you can move about and zoom in and out.

What's next

Nothing is explicitly scheduled for the next post, but you can think it as a surprise.

Github repository: https://github.com/Noah11012/sdl2-tutorial-code

Reinvent your career. Join DEV.

It takes one minute and is worth it for your career.

Get started

Top comments (0)

AWS Security LIVE!

Tune in for AWS Security LIVE!

Join AWS Security LIVE! for expert insights and actionable tips to protect your organization and keep security teams prepared.

Learn More

👋 Kindness is contagious

Discover a treasure trove of wisdom within this insightful piece, highly respected in the nurturing DEV Community enviroment. Developers, whether novice or expert, are encouraged to participate and add to our shared knowledge basin.

A simple "thank you" can illuminate someone's day. Express your appreciation in the comments section!

On DEV, sharing ideas smoothens our journey and strengthens our community ties. Learn something useful? Offering a quick thanks to the author is deeply appreciated.

Okay