Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Problem with sf::View - minimap isnt displayed where it is supposed to be  (Read 4993 times)

0 Members and 1 Guest are viewing this topic.

kingcools

  • Jr. Member
  • **
  • Posts: 57
    • View Profile
Hi, this is basically just a compressed version of this thread: http://en.sfml-dev.org/forums/index.php?topic=15414.0

i figured that this is better suited in this section of the forum.

So in short:
Quote
i want to split my window in three (well known) parts basically:

1) game region where the game itself is drawn e.g. the map, units and everything else
2) minimap in the typical left bottom corner
3) unitmenu in the bottom right part of the screen for the player to give commands to the units

i ignored the third point for now, so im messing around with sf::View to get what i want.

i was told that to have the minimap display the whole map i just need to set its view to the respective size of the whole map in pixel. This is what i did, but the map gets displaced that way, which i do not want to happen.

see for yourself:

Quote
when i do this i get this:


the view is shifted by some offset when i set the size of it to the size of the whole tilemap.

all i did was to add one line, which does what you told me:
        sf::View mapview(app_window.getDefaultView());
        sf::View minimap(app_window.getDefaultView());
        //sf::View menu(app_window.getDefaultView());

        mapview.setViewport(sf::FloatRect(0.f,0.f,1.f,0.75f));
        minimap.setViewport(sf::FloatRect(0.f, 0.75, 0.5, 0.25));
        minimap.setSize(20*32,20*32); // my tilemap is 20 x 20 with each tile having the size of 32 x 32 pixel
 

but i don't want this behaviour, i want the minimap to be drawn at the position specified in "setViewport" (well to be precise i want the map to be drawn at the top left corner of that viewport)

what i want is this (note: minimap does not show the whole map so it is not what im trying to achieve):


my code is the following:
#include <SFML/Graphics.hpp>
#include <iostream>

sf::Texture m_tileset;
sf::VertexArray m_vertices;
void setTilemap()
{
    m_tileset.loadFromFile("Tileset.png");
    m_vertices.setPrimitiveType(sf::Quads);
    m_vertices.resize(20*20*4); // we use some dummy numbers to get a mapwidth > renderwindow_width

    for (unsigned int i = 0; i < 20; ++i)
    {
        for (unsigned int j = 0; j < 20; ++j)
        {
            //get the current tile number
            int tileNumber = 34;

            // find its position in the tileset texture
            int tu = tileNumber % (m_tileset.getSize().x / 32);
            int tv = tileNumber / (m_tileset.getSize().x / 32);

            // get a pointer to the current tile's quad
            sf::Vertex* quad = &m_vertices[(i + j * 20) * 4];

            // define its 4 corners
            quad[0].position = sf::Vector2f(i * 32, j * 32);
            quad[1].position = sf::Vector2f((i + 1) * 32, j * 32);
            quad[2].position = sf::Vector2f((i + 1) * 32, (j + 1) * 32);
            quad[3].position = sf::Vector2f(i * 32, (j + 1) * 32);

            // define its 4 texture coordinates
            quad[0].texCoords = sf::Vector2f(tu * 32, tv * 32);
            quad[1].texCoords = sf::Vector2f((tu + 1) * 32, tv * 32);
            quad[2].texCoords = sf::Vector2f((tu + 1) * 32, (tv + 1) * 32);
            quad[3].texCoords = sf::Vector2f(tu * 32, (tv + 1) * 32);
        }
    }
}



int main() {
    // Create the main SFML window
    float width = 320.f;
    float height = 420.f;
    sf::RenderWindow app_window( sf::VideoMode(width,height), "SFGUI Canvas Example", sf::Style::Titlebar | sf::Style::Close );

    // Start the game loop
    app_window.setFramerateLimit(20);
    setTilemap();
    sf::RenderStates states;
    states = &m_tileset;

    sf::View mapview(app_window.getDefaultView());
    sf::View minimap(app_window.getDefaultView());
    //sf::View menu(app_window.getDefaultView());

    mapview.setViewport(sf::FloatRect(0.f,0.f,1.f,0.75f));
    minimap.setViewport(sf::FloatRect(0.f, 0.75, 0.5, 0.25));
    minimap.setSize(20*32,20*32);




    while ( app_window.isOpen() ) {
        sf::Event event;

        while ( app_window.pollEvent( event ) ) {

            // Close window : exit
            if ( event.type == sf::Event::Closed ) {
                app_window.close();
            }
        }

        app_window.clear();
        app_window.setView(mapview);
        app_window.draw(m_vertices,states);

        app_window.setView(minimap);
        app_window.draw(m_vertices,states);


        app_window.display();
    }
    return EXIT_SUCCESS;
}

the used tileset can be found in the attachment.

why is the minimap displaced when i set its size to the mapsize? i expected (and observed) this behaviour when calling sf::View::zoom(), but not for sf::View::setSize().

Advice is greatly appreciated.

kingcools

  • Jr. Member
  • **
  • Posts: 57
    • View Profile
So am i doing it right and my graphics card just sucks ass in regards to sfml?

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 11030
    • View Profile
    • development blog
    • Email
Whaf if you set the size before setting the viewport? Or what if you set the center to (10*32, 10*32)?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
When you resize a view, it is resized relatively to its center, not its top-left corner. Therefore, when you create your minimap view and make it bigger, it expands in all directions, which explains that your map is offset. Create it directly with its final size, or resize it with a FloatRect if you want to avoid surprises.
Laurent Gomila - SFML developer

kingcools

  • Jr. Member
  • **
  • Posts: 57
    • View Profile
I see, Thank you so much :) Both of you of course :)

edit: it still does not do what i want.
i initialized it with my desired center and size and then changed its viewport, yet it still gets displaced.
Furthermore arent all tiles shown which i thought to be the case when i adjust the size of the view accordingly (in the initialization).



what i changed:
        sf::View mapview(app_window.getDefaultView());
        sf::View minimap(sf::Vector2f(80.f, 320.f * 0.875) , sf::Vector2f(20 * 32.f, 20 * 32.f));
        //sf::View menu(app_window.getDefaultView());

        mapview.setViewport(sf::FloatRect(0.f,0.f,1.f,0.75f));
        minimap.setViewport(sf::FloatRect(0.f, 0.75, 0.5, 0.25));
 

« Last Edit: June 13, 2014, 01:47:20 am by kingcools »

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
The true center of a rectangle with size (20 * 320, 20 * 32) is obviously not (80, 320 * 0.875).

sf::View minimap(sf::Vector2f(320.f, 320.f), sf::Vector2f(20 * 32.f, 20 * 32.f));
or
sf::View minimap(sf::FloatRect(0, 0, 20 * 32.f, 20 * 32.f));
Laurent Gomila - SFML developer

kingcools

  • Jr. Member
  • **
  • Posts: 57
    • View Profile
hi, that is indeed doing what its supposed to do haha thank you so much :)

now my question: why does it work?^^

from what i undestood its like this:
the ratio of the view and renderwindow's dimensions determines whether the drawings are distorted or not.
e.g. if i setup a view with a width of 300 and the renderwindows own width is 100 pixels and the viewport is the whole renderwindow all drawings are shrunk by a factor of 3 (in x direction).
same goes for the other dimension.

now when i set a new viewport that is smaller than the renderwindow, this should stay the same just with local viewport coordinates? I.e. when i got my 100 pixel wide renderwindow and setup a viewport that fills up 1/4 of that area (so half height, width) and the center of my 300 pixel view is set to (150.f,150.f) my drawings will be shrunk by a factor of 6 in each direction (assuming a 300 x 300 view) without displacement of any sorts relative to the top left corner of my viewport?

small additional question:
in your second option you set the first two parameters to 0, opposed to the 320 you chose in the first version. Is the second one setting the top left corner?

Laurent

  • Administrator
  • Hero Member
  • *****
  • Posts: 32498
    • View Profile
    • SFML's website
    • Email
Quote
from what i undestood its like this
Yes, you're right.

Quote
in your second option you set the first two parameters to 0, opposed to the 320 you chose in the first version. Is the second one setting the top left corner?
Yes. The first constructor is (center, size) while the second one is (rect). And a sf::FloatRect, as explained in the documentation, is defined by (left, top, width, height).
Laurent Gomila - SFML developer

kingcools

  • Jr. Member
  • **
  • Posts: 57
    • View Profile
Thank you alot, that greatly helped :)