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

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - codergopher

Pages: [1]
1
Graphics / Re: Graphical glicth: horizontal lines in SFML2
« on: December 16, 2019, 01:11:01 am »
Hey everybody! I know this thread is quite old, but I found a solution that solves the problem perfectly, while maintaining floating point movement.

Laurent suggested that we round our movements units to ints in order to achieve pixel perfect rendering, and (s)he is about half right.

Rounding to ints works if we haven't zoomed our view at all, because at this point

1 pixel = 1 movement unit

Sounds simple, right?
Well, this all craps the bed if we zoom in our view, let's say by 4.

view.zoom(1/4.f);

What we've just done here is made the width and height of each pixel = 4 pixels. As a result of that,

1 movement unit = 4 pixels

or

1 pixel = .25 movement unit

If we were to say

player.move(1, 0);

our player would actually move 4 pixels to the right instead of just 1. This looks choppier than a hyperventilating  ninja on redbull. Here's where we need floating point precision so that we can move our player 1 pixel at a time instead of 4. Now,

1 pixel = .25 movement unit

So if we wanted to move our player just 1 pixel to the right, we would say

player.move(.25, 0);

But what happens if our players movement isn't exactly equal to the amount required to move 1 pixel?

ie

player.move(.16, 0);

In that case, our view might draw the player at the screen pixel location of 0, 0 or 1, 0, depending on if we've moved our camera(sf::View) at any time in the game. If we went

view.setCenter(somenumber.14, someothernumber.0);

then it would place our player at 1, 0 because .16 +.14 = .31 which is > .25.
This is where the weird vertical lines come into play, because SFML isn't really sure in which pixel to place our scene.

To solve the problem, all we have to do is keep our movements at multiples of our scaling factor. In our case, we just round our movements to multiples of .25, which is 1/4, and this will achieve pixel perfect rendering.

To implement:

#include <bits/stdc++.h> //for fmod

float ZOOM_SCALE = 4;

sf::Vector2f roundVector2f(sf::Vector2f p_vector, float p_scale)
{
   sf::Vector2f diff = sf::Vector2f(fmod(p_vector.x, 1/p_scale), fmod(p_vector.y, 1/p_scale));
   p_vector.x -= diff.x;
   p_vector.y -= diff.y;

   return p_vector;
}

int main()
{
        //some code
        sf::View view(sf::Vector2f(0.f, 0.f), sf::Vector2f(1280, 720));
   view.zoom(1/ZOOM_SCALE);
       
        //if we move the camera
        sf::Vector2f camPos = sf::Vector2f(234.12, 434.45);
        view.setCentre(roundVector2f(camPos, ZOOM_SCALE);

        //if we move our player
        sf::Vector2f vel = sf::Vector2f(1.1, 2.6);
        player.move(roundVector2f(vel, ZOOM_SCALE);
}

Hope this helps :)

Pages: [1]
anything