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

Author Topic: Wrapping map view visibility issues in sfml  (Read 2500 times)

0 Members and 1 Guest are viewing this topic.

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Wrapping map view visibility issues in sfml
« on: April 20, 2015, 07:44:11 am »
I'm opening a new question, because it's about a different problem, where a view is completely invisible.
I'm implementing a wrapping map consisting of two neighbouring parts. The problem: Only the first view is visible and works as intended. The second view is invisible and I don't know why. If you go to the left, there is a a black area instead of the second view. After having done many number changes/tests, it seems as the second view is limited to the area of the first view only. I´ve really tried to change everything, I`ve read many old posts and the view tutorials, but it is a "mission impossible". With one tiled maps, that were not bigger than the screen size it worked like a charm, unlike here. Many thanks for any help in advance.

#include <SFML/Graphics.hpp>
#include <iostream>

int main()
{
    sf::RenderWindow mMainWindow(sf::VideoMode(1000,600), "Map", sf::Style::Close);
    sf::View view(sf::Vector2f(500, 300), sf::Vector2f(1000, 600));
    sf::View view2(sf::Vector2f(500, 300), sf::Vector2f(1000, 600));

    sf::Image mapimage;
    mapimage.loadFromFile("world1.jpg");  //1000*600 px
    sf::Texture maptexture;
    maptexture.loadFromImage(mapimage);
    sf::Sprite mapsprite(maptexture);
    sf::Sprite mapsprite2(maptexture);
    mapsprite.setPosition(0, 0);
    mapsprite2.setPosition(1000, 0);

    sf::RectangleShape viewrect;
    viewrect.setSize(sf::Vector2f(2000, 600));
    viewrect.setPosition(0, 0);
    viewrect.setFillColor(sf::Color(250,0,0,40));

    sf::RectangleShape viewrect2;
    viewrect2.setSize(sf::Vector2f(2000, 600));
    viewrect2.setPosition(0, 0);
    viewrect2.setFillColor(sf::Color(0,0,250,40));

    float fview2 = 1;
    view2.setViewport(sf::FloatRect(fview2, 0, 1, 1));
    int mapmovementvar = 0;

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

        while (mMainWindow.pollEvent(event))
        {
            switch (event.type)
            {
            case sf::Event::Closed:
                mMainWindow.close();
                break;
            }
        }
        if(sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            system("cls");
            view.move(-100, 0);
            fview2=fview2+0.1f;
            mapmovementvar--;

            if(mapmovementvar<0)
            {  
                mapmovementvar=19;
                fview2=-0.9f;
                view.reset(sf::FloatRect(1900, 0, 1000, 600));
                view2.reset(sf::FloatRect(-1000, 0, 1000, 600));
            }

            view2.setViewport(sf::FloatRect(fview2, 0, 1, 1));
            std::cout << "fview2 " << fview2 << std::endl;
            std::cout << "mapmovementvar " << mapmovementvar << std::endl;
        }

        mMainWindow.clear();

        mMainWindow.setView(view);
        mMainWindow.draw(mapsprite);
        mMainWindow.draw(mapsprite2);
        mMainWindow.draw(viewrect);

        mMainWindow.setView(view2);
        mMainWindow.draw(mapsprite);
        mMainWindow.draw(mapsprite2);
        mMainWindow.draw(viewrect2);

        mMainWindow.display();
    }
    return 0;
}
« Last Edit: April 20, 2015, 04:50:53 pm by Bogdan »

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10820
    • View Profile
    • development blog
    • Email
AW: Wrapping map view visibility issues in sfml [SOLVED]
« Reply #1 on: April 20, 2015, 11:44:26 am »
You're not setting the viewport correctly. Check out that part again with the official tutorial: http://www.sfml-dev.org/tutorials/2.2/graphics-view.php#defining-how-the-view-is-viewed
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Wrapping map view visibility issues in sfml
« Reply #2 on: April 20, 2015, 04:56:38 pm »
Now it works perfectly, but the sprites drawn in the blue view are cut off at the edges. In the smaller map from the other post it worked and nothing was cut off, but not here in this bigger map. Is there anything that can be done to solve this?

#include <SFML/Graphics.hpp>

int main()
{
    sf::RenderWindow mMainWindow(sf::VideoMode(1000,600), "Map", sf::Style::Close);
        sf::View view(sf::Vector2f(500, 300), sf::Vector2f(1000, 600));
        sf::View view2(sf::Vector2f(500, 300), sf::Vector2f(1000, 600));
        mMainWindow.setFramerateLimit(60);
       
        sf::Texture texture;
    texture.loadFromFile("settlement.png");
        std::vector<sf::Sprite> EnemyVector;

        sf::RectangleShape viewrect;
        viewrect.setSize(sf::Vector2f(2000, 600));
        sf::RectangleShape viewrect2;
        viewrect2.setSize(sf::Vector2f(2000, 600));
        viewrect2.setFillColor(sf::Color(0,0,250));

        float fview2 = 2;
        int mapmovementvar = 0;

        sf::Sprite sprite;          
    sprite.setTexture(texture);
    sprite.setOrigin(sprite.getTextureRect().width / 2,sprite.getTextureRect().height / 2);

        sprite.setPosition(10, 250);
        EnemyVector.push_back(sprite);
        sprite.setPosition(1990, 350);
        EnemyVector.push_back(sprite);

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

        while (mMainWindow.pollEvent(event))
        {
            switch (event.type)
            {
            case sf::Event::Closed:
                mMainWindow.close();
                break;
            }
                }
                if(sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
                {
                        view.move(100, 0);
                        fview2=fview2-0.1f;
                        mapmovementvar++;

                        if(mapmovementvar>19)
                        {
                                mapmovementvar=0;
                                fview2=2;
                                view.reset(sf::FloatRect(0, 0, 1000, 600));
                        }
                        view2.setViewport(sf::FloatRect(fview2, 0, 1, 1));
                }

        mMainWindow.clear();
                mMainWindow.setView(view);
                mMainWindow.draw(viewrect);
                mMainWindow.setView(view2);
                mMainWindow.draw(viewrect2);

                mMainWindow.setView(view);
                for(auto &SpriteIt = EnemyVector.begin();SpriteIt != EnemyVector.end();++SpriteIt)
                {
                        mMainWindow.draw(*SpriteIt);
                }
                mMainWindow.setView(view2);
                for(auto &SpriteIt = EnemyVector.begin();SpriteIt != EnemyVector.end();++SpriteIt)
                {
                        mMainWindow.draw(*SpriteIt);
                }

        mMainWindow.display();
    }
    return 0;
}

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10820
    • View Profile
    • development blog
    • Email
Re: Wrapping map view visibility issues in sfml
« Reply #3 on: April 20, 2015, 05:31:19 pm »
What are you actually trying to achieve?

Why use views if you want to draw across views anyways?
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Wrapping map view visibility issues in sfml
« Reply #4 on: April 20, 2015, 06:08:12 pm »
I need the views for achieving a wrapping/boundless world effect (earth map) when scrolling the map and for moving sprites smoothly across the map edges. I don't see any other way to do this other than by using multiple views. My sprite movement and coordinate calculations and everything works perfectly but the sprites at the edges cut off and that does look ugly. In the smaller map of my other topic it even worked, although the code didn't really change.

eXpl0it3r

  • SFML Team
  • Hero Member
  • *****
  • Posts: 10820
    • View Profile
    • development blog
    • Email
Re: Wrapping map view visibility issues in sfml
« Reply #5 on: April 20, 2015, 07:19:31 pm »
You can also just draw the sprite twice.... :D
Official FAQ: https://www.sfml-dev.org/faq.php
Official Discord Server: https://discord.gg/nr4X7Fh
——————————————————————
Dev Blog: https://duerrenberger.dev/blog/

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Wrapping map view visibility issues in sfml
« Reply #6 on: April 23, 2015, 02:51:07 pm »
After having done experiments with different approaches, I've came up with the following code. It's almost perfect, but sprite-duplicates that have their center in a different "viewrect" than the viewrect the cursor is in, are not selectable. I know how to draw it to make units selectable (only sprite-duplicates that correspond to the last draw call of an if-condition are selectable-->that causes the whole problem, because I need to distinguish between different cases), but I don't have a "condition" that distinguishes between sprite-copies that have their center in the viewrect and those that have not. Is there a way to come up with such a condition or are there better approaches? Sorry for long code, but it is neccessary to demonstrate the problem.

#include <SFML/Graphics.hpp>
#include <tuple>

int main()
{
    sf::RenderWindow mMainWindow(sf::VideoMode(1000,600), "Map", sf::Style::Close);

        mMainWindow.setFramerateLimit(60);
        mMainWindow.setKeyRepeatEnabled(false);
       
        sf::Texture texture;
    texture.loadFromFile("settlement.png");
        std::vector<std::tuple<sf::Sprite,sf::Vector2i>> EnemyVector;

        sf::RectangleShape viewrect;
        viewrect.setSize(sf::Vector2f(400, 600));
        viewrect.setPosition(0, 0);

        sf::RectangleShape viewrect2;
        viewrect2.setSize(sf::Vector2f(400, 600));
        viewrect2.setPosition(400, 0);
        viewrect2.setFillColor(sf::Color(0,250,0));

        sf::Vector2i pixel_pos;
        sf::Vector2f coord_pos;
        sf::Sprite* focus = nullptr;

    while (mMainWindow.isOpen())
    {
        sf::Event event;
                sf::Vector2i mousePos;
                bool creating = false;
                bool leftclicked = false;
        while (mMainWindow.pollEvent(event))
        {
            switch (event.type)
            {
            case sf::Event::Closed:
                mMainWindow.close();
                break;
                        case sf::Event::MouseButtonPressed:
                if (event.mouseButton.button == sf::Mouse::Left)
                                {
                                        mousePos = sf::Vector2i(event.mouseButton.x, event.mouseButton.y);
                                        leftclicked = true;
                                        break;
                                }
                        case sf::Event::KeyPressed:
                                if (event.key.code == sf::Keyboard::A)
                                {
                                        creating = true;
                                        break;
                                }
            }
                }
                if (creating)
        {
                        focus=nullptr;
                        pixel_pos = sf::Mouse::getPosition(mMainWindow);
                        coord_pos = mMainWindow.mapPixelToCoords(pixel_pos);

            sf::Sprite sprite;      
            sprite.setTexture(texture);
            sprite.setOrigin(sprite.getTextureRect().width / 2,sprite.getTextureRect().height / 2);
                        if(viewrect.getGlobalBounds().contains(coord_pos.x, coord_pos.y))
                        {
                                sprite.setPosition(coord_pos.x, coord_pos.y);
                                EnemyVector.push_back(std::make_tuple(sprite,sf::Vector2i(coord_pos.x, coord_pos.y)));
                        }
                        else if(viewrect2.getGlobalBounds().contains(coord_pos.x, coord_pos.y))
                        {
                                sprite.setPosition(coord_pos.x, coord_pos.y);
                                EnemyVector.push_back(std::make_tuple(sprite,sf::Vector2i(coord_pos.x-400, coord_pos.y)));
                        }
        }
                if(leftclicked)
                {
                        pixel_pos = sf::Mouse::getPosition(mMainWindow);
                        coord_pos = mMainWindow.mapPixelToCoords(pixel_pos);
                       
                        for (auto& enemy=EnemyVector.rbegin(); enemy!=EnemyVector.rend(); ++enemy)
                        {      
                                if (std::get<0>(*enemy).getGlobalBounds().contains(coord_pos.x, coord_pos.y))
                                {      
                                        for (auto& enemy=EnemyVector.rbegin(); enemy!=EnemyVector.rend(); ++enemy)
                                        {
                                                std::get<0>(*enemy).setColor(sf::Color::White);
                                        }
                                        focus = &(std::get<0>(*enemy));
                                        std::get<0>(*enemy).setColor(sf::Color::Yellow);
                                        break;
                                }
                                else
                                {
                                        for (auto& enemy=EnemyVector.rbegin(); enemy!=EnemyVector.rend(); ++enemy)
                                        {
                                                std::get<0>(*enemy).setColor(sf::Color::White);
                                        }
                                        focus=nullptr;
                                }
                        }
                }
        mMainWindow.clear();
                mMainWindow.draw(viewrect);
                mMainWindow.draw(viewrect2);

                pixel_pos = sf::Mouse::getPosition(mMainWindow);
                coord_pos = mMainWindow.mapPixelToCoords(pixel_pos);

                if(viewrect.getGlobalBounds().contains(coord_pos.x, coord_pos.y))
                {
                        for(auto &enemy = EnemyVector.begin();enemy != EnemyVector.end();++enemy)
                        {
                                std::get<0>(*enemy).setPosition(std::get<1>(*enemy).x-400, std::get<1>(*enemy).y);
                                mMainWindow.draw(std::get<0>(*enemy));
                                std::get<0>(*enemy).setPosition(std::get<1>(*enemy).x+400, std::get<1>(*enemy).y);
                                mMainWindow.draw(std::get<0>(*enemy));
                                std::get<0>(*enemy).setPosition(std::get<1>(*enemy).x, std::get<1>(*enemy).y);
                                mMainWindow.draw(std::get<0>(*enemy)); 
                        }
                }
                else if(viewrect2.getGlobalBounds().contains(coord_pos.x, coord_pos.y))
                {
                        for(auto &enemy = EnemyVector.begin();enemy != EnemyVector.end();++enemy)
                        {
                                std::get<0>(*enemy).setPosition(std::get<1>(*enemy).x-400, std::get<1>(*enemy).y);
                                mMainWindow.draw(std::get<0>(*enemy)); 
                                std::get<0>(*enemy).setPosition(std::get<1>(*enemy).x, std::get<1>(*enemy).y);
                                mMainWindow.draw(std::get<0>(*enemy)); 
                                std::get<0>(*enemy).setPosition(std::get<1>(*enemy).x+400, std::get<1>(*enemy).y);
                                mMainWindow.draw(std::get<0>(*enemy));         
                        }
                }
        mMainWindow.display();
    }
    return 0;
}

Bogdan

  • Jr. Member
  • **
  • Posts: 93
    • View Profile
Re: Wrapping map view visibility issues in sfml
« Reply #7 on: April 28, 2015, 06:21:15 pm »
Some time ago, I've found a workaround by simply creating 3 identical maps and 3 tuples that have all the same behaviour and it really behaves like one infinite map. There doesn't seem to be any other simpler or more "ressource saving" solution.