SFML community forums

Help => General => Topic started by: Szustarol on October 27, 2016, 07:24:48 pm

Title: Problem with moving several object
Post by: Szustarol on October 27, 2016, 07:24:48 pm
Hi!
I want to make animated road using sfml, so I made objects that represent lines on the street.
There are 2 functions, init and move, while move is casted everytime, init is only used once.
These are the functions, along with function to draw them on window.
Code: [Select]
void lines::initialise(sf::RenderWindow &window){
    std::vector<sf::RectangleShape> temp;
    temp.resize(ammount);
    siz = window.getSize().y/40;
    for(int i = 0; i < ammount; i++){
        temp[i].setSize(sf::Vector2f(6, siz));
        temp[i].setFillColor(sf::Color(255,255,255));
    }
    for(int i = 0; i < ammount; i++){
        temp[i].setPosition(0, siz*2*i);
    }
    line = temp;
}

void lines::drawintargetwindow(sf::RenderWindow &window){
    int temp;
    temp = window.getSize().x*0.4-3;
    for(int i = 0; i < ammount; i++){
        line[i].setPosition(temp, line[i].getPosition().y);
        window.draw(line[i]);
    }
    temp = window.getSize().x*0.6-3;
    for(int i = 0; i < ammount; i++){
        line[i].setPosition(temp, line[i].getPosition().y);
        window.draw(line[i]);
    }
}

void lines::move(){
    time=clock.getElapsedTime();
    clock.restart();
    for(int i = 0; i < ammount; i++){
        line[i].move(sf::Vector2f(0, speed*time.asSeconds()));
        if(line[i].getPosition().y > siz*40)
            line[i].setPosition(0, 0-siz);
    }
}

so the problem is, there is a gap between these lines, screen will demonstrate, second attachement shows what happens if i comment out whole content of move function (while move is still called, it is just commented out so does nothing)
Title: Re: Problem with moving several object
Post by: Szustarol on October 28, 2016, 11:12:40 pm
bump
Title: Re: Problem with moving several object
Post by: Hapax on October 30, 2016, 10:17:00 am
When does the gap appear, immediately or after some time?

It could be linked to the 'new' position of the line when wrapped. Instead of setting the new position to just off-screen, try offsetting - or moving - the line upwards by the a set amount. The reason is that the line may pass further than the exact position off the edge of the screen but then is placed back as if it was exact. The 'set amount' would be the size of the road, which would probably be in this case just larger than the height of the window (the size of the wrap).

Posting code inside [code=cpp] [/code] tags is often a much better idea (see below) ;)

Bonus tip:
sf::Clock::restart() also returns the elapsed time so you can replace your two lines with just:
time = clock.restart(); // resets the clock and returns the elapsed time before the reset
Title: Re: Problem with moving several object
Post by: Szustarol on October 30, 2016, 12:47:21 pm
sadly the gap appears instantly so i guess it is not caused by wrong replacing of position, also i have noticed one strange thing
if i place the move method at the start of while window is open the gap seems smaller (but is  still there)
if i place it right after window.clear gap is bigger, maybe that is somehow connected with the problem
Title: AW: Problem with moving several object
Post by: eXpl0it3r on October 30, 2016, 12:58:33 pm
I don't have the time to understand every bit of your code. Generally if you have an issue where things don't get placed as you'd expect, it's best to just print out tge values and see where something is off. With that information you can then go back and go through your code step by step until you found the bug.
Title: Re: Problem with moving several object
Post by: Szustarol on October 30, 2016, 07:07:03 pm
If this d help i have reproduced the error with as small code as possible
Code: [Select]
#include <SFML/Graphics.hpp>
#include <SFML/Window.hpp>
#include <SFML/System.hpp>
using namespace sf;
int main() {
    Clock zegar;
    Time time;
    RenderWindow okno( VideoMode( 800, 600 ), "test" );
    RectangleShape pasek[ 20 ];
    int siz = 600 / 40;
    for( int i = 0; i < 20; i++ ) {
        pasek[ i ].setSize( sf::Vector2f( 6, siz ) );
        pasek[ i ].setFillColor( sf::Color( 255, 255, 255 ) );
    }
    for( int i = 0; i < 20; i++ ) {
        pasek[ i ].setPosition( 0, siz * 2 * i );
    }
    int temp;
    int speed = 100;
    while( okno.isOpen() ) {
        time = zegar.restart();
        for( int i = 0; i < 20; i++ ) {
            pasek[ i ].move( sf::Vector2f( 0, speed * time.asSeconds() ) );
            if( pasek[ i ].getPosition().y > siz * 40 )
                 pasek[ i ].setPosition( 0, 0 - siz );
           
        }
        okno.clear();
        temp = 800 * 0.4;
        for( int i = 0; i < 20; i++ ) {
            pasek[ i ].setPosition( temp, pasek[ i ].getPosition().y );
            okno.draw( pasek[ i ] );
        }
        temp = 800 * 0.6;
        for( int i = 0; i < 20; i++ ) {
            pasek[ i ].setPosition( temp, pasek[ i ].getPosition().y );
            okno.draw( pasek[ i ] );
        }
        okno.display();
    }
}
Title: Re: Problem with moving several object
Post by: Hapax on October 31, 2016, 01:21:13 am
Posting code inside [code=cpp] [/code] tags is often a much better idea

If this d help i have reproduced the error with as small code as possible
It does help, yes, as we are able to run it to test it.
Please make sure your minimal code is 'complete', though. A window should have an event loop. ;)

Anyway, as suspected, the problem is that you are working to a design that has a window height of 600 but your actual positions' range is a little larger than that.
The range of positions for your rectangles is from -siz (when you reset the y) to 600 (when the rectangle is off the bottom of the window).

Changing the move section (of the minimal code) to:
        for (int i = 0; i < 20; i++) {
            pasek[i].move(sf::Vector2f(0, speed * time.asSeconds()));
            if (pasek[i].getPosition().y > siz * 40)
                pasek[i].setPosition(0, 0 /* - siz */ ); // just setting it to zero
        }
fixes the problem. However, it's aesthetically unpleasing as the rectangle isn't introduced from off-screen.

To fix this problem, you can simply allow for the full range of positions as mentioned above or have an extra rectangle to cover that extra section.

(click to show/hide)

You may also be interested in eXpl0it3r's example of a scrolling road:
https://github.com/eXpl0it3r/Examples#road


EDIT: added modified minimal code