在sfml中包装地图可见性问题

时间:2015-04-19 17:40:22

标签: c++ view sfml

我正在实现一个由两部分组成的包装地图,只有第一个视图可见并按预期工作。 第二种观点是看不见的,我不知道为什么。如果你向左转,有一个黑色区域而不是第二个视图。 在完成许多次数更改/测试后,似乎第二个视图仅限于第一个视图的区域。 有一个平铺的地图,它不像屏幕尺寸那样像一个魅力,不像这里。非常感谢您提前提供任何帮助。

#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;
}

1 个答案:

答案 0 :(得分:1)

我没有解决您所拥有的观点的问题,但我认为在您的情况下甚至不需要使用观点。请参阅下面的代码,我认为实现您想要的代码。

初始化

如您所见,如果您不想将Image对象用于其他内容,则可以直接从文件中加载Texture。而且这里的观点有点过分,我认为不是像你想要的那样使用观点的目标。

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

int main()
{
    float screenWidth = 1000;

    sf::RenderWindow mMainWindow(sf::VideoMode(screenWidth, 600), "Map",
            sf::Style::Close);

    // no need to use image, you can load texture directly from a file
    sf::Texture maptexture;
    maptexture.loadFromFile("world1.jpg"); //1000*600 px

    // you only really need one sprite, but that's not really a problem.
    sf::Sprite mapsprite(maptexture);

    // you don't need views at all, just a position.
    sf::Vector2f pos;

App loop

这里没有任何改变。

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

        while (mMainWindow.pollEvent(event))
        {
            switch (event.type)
            {
            case sf::Event::Closed:
                mMainWindow.close();
                break;
            default:
                break;
            }
        }

键盘输入处理

处理输入时,只更改依赖于输入的内容。这里,只有位置发生变化。 (还有用于缩放的精灵比例,但这里有奖金)

        // you may as well test with all directions because f*ck One Direction.
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Left))
        {
            pos.x += 1.0f;
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Right))
        {
            pos.x -= 1.0f;
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down))
        {
            pos.y -= 1.0f;
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Up))
        {
            pos.y += 1.0f;
        }

        // bonus zoom
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Equal)) // + zoom
        {
            mapsprite.setScale(mapsprite.getScale().x + 0.001f,
                    mapsprite.getScale().y + 0.001f);
        }
        if (sf::Keyboard::isKeyPressed(sf::Keyboard::Dash)) // - zoom
        {
            mapsprite.setScale(mapsprite.getScale().x - 0.001f,
                    mapsprite.getScale().y - 0.001f);
        }

调整后的位置

由于我们总是使用相同的地图,我们只需要跟踪一个地图矩形内的位置。所以,如果我们通过那个矩形,我们只是调整位置以回到地图内部,我们在渲染之前这样做,所以我们只是改变了地图位置它是不可见的。

        // Here's all the magic happening, you loop your position around the width.
        float width = mapsprite.getGlobalBounds().width;
        if (pos.x <= -width)
        {
            pos.x += width;
        }
        else if (pos.x > 0)
        {
            pos.x -= width;
        }

        std::cout << "X pos : " << pos.x << std::endl;

渲染循环

我们只需要一个Sprite对象来实现渲染循环,因为我们使用与Sprite引用相同的Texture。我们只是给Sprite一个新的位置,然后绘制它,然后重复。你仍然可以毫无问题地使用很多Sprite对象,因为Sprite是一个轻量级对象,但是这里使用多个没有用。

        mMainWindow.clear();

        for (int i = 0; pos.x + (i * width) < screenWidth; ++i)
        {

            // display each sprite with a new position according to the last one.
            mapsprite.setPosition(pos.x + (i * width), pos.y);
            mMainWindow.draw(mapsprite);

        }

        mMainWindow.display();
    }
    return 0;
}