#Problem With SFML 3's views

110 messages · Page 1 of 1 (latest)

round epoch
#

So, for the little story I am coding a game using SFML 3, and, after making the whole system for my procedurally generated map (or at least the beginning thereof), I noticed that the black pixels on my textures "spread around" while my player is moving.

I simply use a view as follows:

Main Loop - main.cpp

        window.setFramerateLimit(60);

        View view;
            
            player.setViewSize({ 1000, 800 });
            view.setCenter({ 0,0 });

            map.loadCurrentZone();

        while (window.isOpen())
        {
            

            deltaTime.restart();

            if (auto event = window.pollEvent())
            {
                if (event->getIf < sf::Event::Closed>())
                {
                    window.close();
                }
            }

            if (sf::Mouse::isButtonPressed(sf::Mouse::Button::Right))
            {
                player.setTarget(static_cast<Vec2f>(window.mapPixelToCoords(sf::Mouse::getPosition(window))));
            }

            player.updateView();

            player.update(deltaTime);

            window.setView(player.getView());

            window.clear();

            window.draw(map);

            window.draw(player);

            window.display();
        }

player.updateView() - Player.h (derived from: MoveableEntity)

void MoveableEntity::updateView()
{
    if(!detachView)
    {
        currentViewPosition = currentPosition;
        view.setCenter(currentViewPosition);
    }
}

I truly do not know what's causing this, feel free to ping me.
(I added a small video that demonstrates the problem)

round epoch
#

I haven't fixed it but i know the root cause of the problem.

It isn't a problem I have in my code, the problem is being caused by muy monitor (when I share a video of it, other people don't seem to see it).

So, muy problem is ghosting.

rich glade
#

You can try to round the position of your character and of the view or disabling AA

round epoch
rich glade
#

What's the resolution of your monitor

round epoch
round epoch
rich glade
#

No lol

round epoch
#

Oh my bad, I thought that 1920x1080 was 4k resolution

rich glade
#

So which do you have?

round epoch
#

But my resolution is 1920x1080.

rich glade
#

What's the model of your monitor?

round epoch
rich glade
#

What's your monitor

#

Also I'm not sure what the problem is

#

Do you see it when you play the video on your computer?

#

What about on your phone?

round epoch
# rich glade Do you see it when you play the video on your computer?

As I said (or maybe I expressed it badly), on my computer be it the video or when I'm testing the game.
It is lagging, on my phone or other devices, it doesn't do it.

So I figured that my problem doesn't arise from a buffer video problem but rather a "ghosting" problem?
From my monitor.

rich glade
#

Do you see it in other games?

#

Do you see it on phone

round epoch
round epoch
rich glade
#

Hmm

#

It's hard to say without seeing the problem

round epoch
#

Yep... and I cannot even record it.

#

Maybe through my phone!

#

But, this is not technically related to C++ (as I figured).

#

However, I have another question if I may.

What do you think about OpenGL?

Should I use that instead of SFML?
Or maybe SDL?

rich glade
round epoch
# rich glade Sfml is fine, you can always move on if you need to

I see, I saw that, I am going to stick to SFML for making games I think.

I'll then move on to OpenGL to learn low-level rendering.

And maybe if I can I'll make a graphic Engine using SDL + OpenGL.

So, I'll have to learn GLSL to make my own shaders (and make the GPU work a little lol).
And maybe, if I want to move on to more modern OpenGL-like libraries, I could start using Direct X (or the other that I don't remember the name of).

rich glade
#

You can use glsl with sfml btw

#

Vulkan is the modern cross platform api

round epoch
round epoch
# rich glade You can use glsl with sfml btw

I see, to make shaders for my game it could be cool.

But the game I am making mainly works as my first big project.

I think that will truly be using GLSL for the game Engine that I will make or for some other games.

rich glade
#

I wouldn't recommend making an engine tbh

round epoch
#

Would you still recommend I learn how to use OpenGL?
And low-level rendering alongside GLSL?

If you don't, may I also know why?

My apologies if there are too many questions.

rich glade
round epoch
round epoch
rich glade
rich glade
round epoch
round epoch
#

Thanks for your help.

rich glade
#

What's your long term goal?

round epoch
rich glade
#

You want to do game dev?

#

why Qt?

round epoch
# rich glade why Qt?

I think it is a powerful software to make good looking apps with C++ (or their special language).

#

From what I've seen it is a very good software.

#

Framework*

#

If I want to make GUIs of course.

#

But I think that making my own softwares through SFML or SDL or any other library (that will prevent me from coding too much low-level stuff) will enable me to learn more than if I simply use Qt.

rich glade
#

yeah that's probably true

#

SFML is a good middle ground

#

and you can even use opengl with SFML

round epoch
#

But, I am still not sure as to whether I should go on with OpenGL only and GLSL.

#

To really learn about low-level stuff and truly know how pipelines, shaders etc are rendered.

rich glade
#

I'd say, start with SFML, that'll give you a good feel for it

round epoch
#

I have already started with SFML.

But, maybe you were talking about starting to use SFML + OpenGL together?

rich glade
#

no just SFML is fine

round epoch
#

Oh?

In that case I have already started using SFML, the game I am making uses SFML 3.

#

Since everything is included I merely need to use SFML and the STL.

rich glade
#

what are you using to render the map?

#

multiple sprites or a vertex array?

round epoch
# rich glade what are you using to render the map?

I have a class Tile: a tile is defined by a sprite and an array of length 4 of type BorderType which is an enum including None = -1, Up, Down, Left, Right.

This is a basic Tile.

Then, I have Zone that has-a std::vector of Tiles, this manages a set of tiles from their creation to their position in wolrd coordinates.

When a zone is created it isn't directly loaded (because loading a zone can be quite expensive depending on its size), therefore Zone has four main functions:

generateZone() which iterates through all the existing tiles and creates a vector made out of randomly picked tiles from the aforementionned set.
Then there is defineZone() which places each tile net to each other to fully form the zone.
At last but not least there is borderZone() which defines which tiles are borders based on their positions.

And, the fourth function is loadZone() which call those three functions in the order they're supposed to.

Then, there's another class: Map which manages a std::vector of Zones and a pointer to Zone. The pointer to Zoneacts as the "current Zone".
The Map also manages Gates small entities that are used to indicate the next zone according to whether the player passed through them of not.

That's the core logic for my Map.

#

I know it's not perfect, but everything works fine together.

#

And it isn't very costy (the only thing I could change is how I detect collisions with borders).

rich glade
#

but how are you rendering it?

round epoch
#

Tile overrides the draw() function from sf::Drawable which is itself overridden in both Zoneand Map.

I render each tile using a for-range loop in my class Zone:

void Zone::draw(RenderTarget& target, RenderStates states) const
{
    for (const auto& i : tile_zone)
        target.draw(i);
}
rich glade
#

right

round epoch
#

Is this the correct solution?

rich glade
round epoch
#

yea, I saw that too.

But, I didn't manage to make them work.

I read the entirety of SFML 3's tutorial.
But, I didn't manage to make my textures stick to my tiles (when they were defined by vertx arrays).

#

So, I moved on to sf::sprite.

rich glade
#

I think this would be the next step for you

round epoch
rich glade
#

maybe

round epoch
#
const std::optional<Vector<Tile*>> Player::isCollidingBT()
{
    using BT = BorderType;

    Vector<Tile*> colliders;

    for (const auto& i : refMap.getCurrentZone().getBorderIndexes())
    {
        if (sprite.getGlobalBounds().findIntersection(refMap.getCurrentZone().getTileZone().at(i).getSprite().getGlobalBounds()))
        {
            colliders.push_back(&refMap.getCurrentZone().getTileZone().at(i));
        }
    }

    return colliders;
}
#
void Player::update(const DeltaTime& dt)
{
    using BT = BorderType;

    Vec2f offset{ normalise(applySpeedDT(quotient(), dt)) };

    if ((targetPosition - currentPosition).lengthSquared() <= std::pow(threshold, 2))
    {
        reachedTarget = true;
    }
    
    if (std::optional colliders = isCollidingBT())
    {        
        for(const auto& collider : *colliders)
            for(const auto& i : collider->getBorderArray())
            {
                switch (i)
                {
                case BT::Up:
                    for (float i{ collider->getPosition().x }; i != static_cast<float>(collider->getPosition().x + collider->getTexture().getSize().x); i++)
                    {
                        if ((currentPosition.x + sprite.getTexture().getSize().x / 2 >= i && currentPosition.x + sprite.getTexture().getSize().x / 2 <= i + 1) && (currentPosition.y >= static_cast<float>(collider->getPosition().y) && currentPosition.y <= static_cast<float>(collider->getPosition().y) + 1))
                        {
                            teleport({ currentPosition.x, currentPosition.y + 0.1f });
                            reachedTarget = true;
                        }
                    }
#
                    break;

                case BT::Down:
                    for (float i{ collider->getPosition().x }; i != static_cast<float>(collider->getPosition().x + collider->getTexture().getSize().x); i++)
                    {
                        if ((currentPosition.x + sprite.getTexture().getSize().x / 2 >= i && currentPosition.x + sprite.getTexture().getSize().x / 2 <= i + 1) && (currentPosition.y + sprite.getTexture().getSize().y >= static_cast<float>(collider->getPosition().y + collider->getTexture().getSize().y) && currentPosition.y + sprite.getTexture().getSize().y <= static_cast<float>(collider->getPosition().y + collider->getTexture().getSize().y) + 1))
                        {
                            teleport({ currentPosition.x, currentPosition.y - 0.1f });
                            reachedTarget = true;
                        }
                    }
                    break;

                case BT::Left:
                    for (float i{ collider->getPosition().y }; i != static_cast<float>(collider->getPosition().y + collider->getTexture().getSize().y); i++)
                    {
                        if ((currentPosition.y + sprite.getTexture().getSize().y / 2 >= i && currentPosition.y + sprite.getTexture().getSize().y / 2 <= i + 1) && (currentPosition.x >= static_cast<float>(collider->getPosition().x) && currentPosition.x <= static_cast<float>(collider->getPosition().x) + 1))
                        {
                            teleport({ currentPosition.x + 0.1f, currentPosition.y });
                            reachedTarget = true;
                        }
                    }
#
                    break;

                case BT::Right:
                    for (float i{ collider->getPosition().y }; i != static_cast<float>(collider->getPosition().y + collider->getTexture().getSize().y); i++)
                    {
                        if ((currentPosition.y + sprite.getTexture().getSize().y / 2 >= i && currentPosition.y + sprite.getTexture().getSize().y / 2 <= i + 1) && (currentPosition.x + sprite.getTexture().getSize().x >= static_cast<float>(collider->getPosition().x + collider->getTexture().getSize().x) && currentPosition.x + sprite.getTexture().getSize().x <= static_cast<float>(collider->getPosition().x + collider->getTexture().getSize().x) + 1))
                        {
                            teleport({ currentPosition.x - 0.1f, currentPosition.y });
                            reachedTarget = true;
                        }
                    }
                    break;
                }
            }

    }

    
    if (!reachedTarget)
    {
        sprite.move(offset);
    }
    currentPosition = sprite.getPosition();

    updateTextures();
    updateSounds();

}
#

I create a "virtual" border using a for loop and the currentPosition of the player to know whether it is colliding with the side of the border

#

This works for one border, but since the player can be colliding with two borders at the same type I return a vector of pointers to tiles wrapped in a std::optional (to avoid useless iterations).

#

But, my for loops to create "virtual" borders aren't very optimized.

#

It costs a lot to go over a lot of pixels individually.

#

I could also use a variable to make the code clearer.

rich glade
#

you don't really need to check all the tiles

#

you can get the tiles the player is over directly

round epoch
#

But, I need to iterate over the all the tiles to know which one it is colliding with?

rich glade
#

not really

round epoch
#

Oh by the way, this: refMap.getCurrentZone().getBorderIndexes() returns only an index to access the tiles that are borders.

#

So that I don't uselessly iterate through non-border tiles.

round epoch
rich glade
#

usually you'd have a kind of 2d grid for you tile

#

so that you can compute the index of the tiles that are at a given position

round epoch
#

But teh 2D grid would still be represented by a vector?

rich glade
#

yes

round epoch
#

I mean, first would be the corner up left and second the corner down right

rich glade
#

no basically you'd do

auto tilePos = playerPos / tileSize;
auto tileIndex = tilePos.x + tilePos.y * mapWidth;


round epoch
# rich glade no basically you'd do ```cpp auto tilePos = playerPos / tileSize; auto tileIndex...

I see.

I do not know how this works though.
And why, I'll look it up online!

Thanks a lot for your asnwers, I am going to be silent for awhile, I need to continue my game (I gotta finish it for the end of next week).
And there are still many things to do.

Thanks again for your answers!
I will definitely look at what you suggested me and try my best to use what you provided me with (after understanding it of course).

round epoch
#

My apologies.

round epoch