SFML community forums

Help => Graphics => Topic started by: nebula on November 09, 2013, 01:40:32 pm

Title: [C++ and SFML 2.1] Scrolling backgrounds ( y+) [SOLVED]
Post by: nebula on November 09, 2013, 01:40:32 pm
hey, i wanted to add a scrolling background to my game and now i have an issue with the background, as the title says :D (the jpg files are 800x600 just like the window)

i show you my code and screenshots so you can see whats going wrong

#ifndef GUIMOVABLEBACKGROUNDS_H
#define GUIMOVABLEBACKGROUNDS_H

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

class MovableBackground
{
public:
        MovableBackground();
        void Update(sf::RenderWindow &window, float elapsedTime);
        void Render(sf::RenderWindow &window);
       
private:
        sf::Texture bg1Tex;
        sf::Texture bg2Tex;

        sf::Sprite      bg1Sprite;
        sf::Sprite      bg2Sprite;

        float bgSpeed;
        float bg1Y;
        float bg2Y;
};
#endif
 

GUImovableBackground.cpp
#include "GUImovableBackground.h"


MovableBackground::MovableBackground()
{
        bgSpeed = 0.1;

        bg1Tex.loadFromFile("graphics//background.jpg");
        bg1Tex.setSmooth(false);
        bg1Sprite.setTexture(bg1Tex);
        bg1Y = bg1Sprite.getPosition().y;

        bg2Tex.loadFromFile("graphics//background.jpg");
        bg2Tex.setSmooth(false);
        bg2Sprite.setTexture(bg2Tex);
        bg2Sprite.setPosition(0, -799);
        bg2Y = bg2Sprite.getPosition().y;
}


void MovableBackground::Update(sf::RenderWindow &window, float elapsedTime)
{
        if (bg1Y >= window.getSize().y)
        {
                bg1Y = - 799;
        }else
        {
                bg1Y += bgSpeed * elapsedTime;
        }

        if (bg2Y >= window.getSize().y)
        {
                bg2Y = - 799;
        }else
        {
                bg2Y += bgSpeed * elapsedTime;
        }

        if (bg1Y == -799)
        {
                std::cout << bg1Y << "\t bg1" << std::endl;
        }
        if (bg2Y == -799)
        {
                std::cout << bg2Y << "\t bg2" << std::endl;
        }

        bg1Sprite.setPosition(0, bg1Y);
        bg2Sprite.setPosition(0, bg2Y);
}
void MovableBackground::Render(sf::RenderWindow &window)
{
        window.draw(bg1Sprite);
        window.draw(bg2Sprite);
 

the first screenshot:
(http://img0.www.suckmypic.net/img/3/H/R5Ue2i48/bg1-jpg_thumb.jpg) (http://www.suckmypic.net/R5Ue2i48.jpg)

the second screenshot:
(http://img0.www.suckmypic.net/img/i/X/073D8q6c/bg2-jpg_thumb.jpg) (http://www.suckmypic.net/073D8q6c.jpg)

As you can see, one time it nearly works, the other time the distance is just too high :/
and this goes on all the time... when background1 is set to - 799 the little gap is there. When background2 is set to - 799 the huge gap is there.

Maybe the mistake i made is simple, but I just dont see it :S
(if you need more code please tell me)
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: The Hatchet on November 09, 2013, 01:46:29 pm
You aren't setting an initial bg1Sprite.setPosition(x, y) is about the only simple thing standing out
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: nebula on November 09, 2013, 01:47:29 pm
You aren't setting an initial bg1Sprite.setPosition(x, y) is about the only simple thing standing out
if i dont set this manually it sets itself to (0,0) as i know

further this does not affect the problem because it is only in the destructor and as you see it is nearly set right
(but just for you i tested it and nothing changed)

here is how i use the class in my game (not my code, that would be way too long)

MovableBackground bg;

while running:
bg.Update (window, elapsedTime);
window.clear();
bg.Render(window);
window.display();
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: nebula on November 09, 2013, 04:40:53 pm
I rewrote this completely... now it works better, but i need to rework the initialization of the bg2Sprite position, because at the beginning there is still a mistake with it :/ here is the code

.h
#ifndef GUIMOVABLEBACKGROUNDS_H
#define GUIMOVABLEBACKGROUNDS_H

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

class MovableBackground
{
public:
        MovableBackground();
        void Update(sf::RenderWindow &window, float elapsedTime);
        void Render(sf::RenderWindow &window);
       
private:
        sf::Texture bg1Tex;
        sf::Texture bg2Tex;

        sf::Sprite      bg1Sprite;
        sf::Sprite      bg2Sprite;

        float bgSpeed;
        float bg1Y;
        float bg2Y;
        float windowbg1diff;
};
#endif
 

.cpp
#include "GUImovableBackground.h"


MovableBackground::MovableBackground()
{
        bgSpeed = 0.3;

        bg1Tex.loadFromFile("graphics//background.jpg");
        bg1Tex.setSmooth(false);
        bg1Sprite.setTexture(bg1Tex);
        bg1Y = bg1Sprite.getPosition().y;

        bg2Tex.loadFromFile("graphics//background.jpg");
        bg2Tex.setSmooth(false);
        bg2Sprite.setTexture(bg2Tex);
        bg2Sprite.setPosition(0, 601);
        bg2Y = bg2Sprite.getPosition().y;
}


void MovableBackground::Update(sf::RenderWindow &window, float elapsedTime)
{
        windowbg1diff = bg1Y - window.getSize().y;

        if (bg1Y >= 600)
        {
                bg1Y = - 590;
        }else
        {
                bg1Y += bgSpeed * elapsedTime;
        }

        if (bg2Y >= window.getSize().y)
        {
                bg2Y = - 600;
        }else if (bg2Y < bg1Y)
        {
                bg2Y = windowbg1diff + 5;
        }else
        {
                bg2Y += bgSpeed * elapsedTime;
        }

        bg1Sprite.setPosition(0, bg1Y);
        bg2Sprite.setPosition(0, bg2Y);
}
void MovableBackground::Render(sf::RenderWindow &window)
{
        window.draw(bg1Sprite);
        window.draw(bg2Sprite);
}
 
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: wintertime on November 09, 2013, 06:17:32 pm
Why dont you set the texture to be repeated? Then you should be able to only move the texture rectangle and draw a single fullscreen object.
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: nebula on November 09, 2013, 06:24:42 pm
Why dont you set the texture to be repeated? Then you should be able to only move the texture rectangle and draw a single fullscreen object.

that sounds legit :D i will read myself through the sfml tutorials for this and replace it. thanks ;)
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: nebula on November 09, 2013, 07:18:10 pm
okay. now the problem is that the background is supposed to move downwards as long as the game runs. and by the setRepeated function i can get a sprite within a texture that i can move to the max of the image. Or did i understand it wrong? :D
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: wintertime on November 09, 2013, 07:56:26 pm
If you set the texture to repeating its as if there would be copies of it all around it until infinity. So you should be able to set a texture rectangle(x,y,800,600) for your texture of size 800x600 in the sprite of size 800x600, where x,y is the position inside the texture you want to show at screen position 0,0 and it should fill the whole screen. At least thats how it works in OpenGL and SFML would most likely translate this appropriately without imposing more constraints.
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: nebula on November 09, 2013, 09:32:27 pm
        bgTex.loadFromFile("graphics//background.jpg");
        bgTex.setSmooth(false);
        bgTex.setRepeated(true);
        bgSprite.setTexture(bgTex);
        bgSprite.setTextureRect(sf::IntRect(0,0,800,600));
        bgY = bg1Sprite.getPosition().y;
 
like this? but how do i move the background? i tried this:
        if (bgY < 600)
        {
                bgY += bgSpeed * elapsedTime;
        }else
                {
                        bgY = 0;
                }
 
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: wintertime on November 09, 2013, 09:46:56 pm
More like this:
        bgTex.loadFromFile("graphics//background.jpg");
        bgTex.setSmooth(false);
        bgTex.setRepeated(true);
        bgSprite.setTexture(bgTex);
        bgSprite.setPosition(0,0);
        bgY = 0;
        bgSprite.setTextureRect(sf::IntRect(0,bgY,800,600));
 
if (bgY < 600)
{
        bgY += bgSpeed * elapsedTime;
}
else
{
        bgY = 0;
}
bgSprite.setTextureRect(sf::IntRect(0,bgY,800,600));
 
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: nebula on November 09, 2013, 09:54:20 pm
then this happens:
(http://img0.www.suckmypic.net/img/G/k/8u52c6g6/neu-1-jpg_thumb.jpg) (http://www.suckmypic.net/8u52c6g6.jpg)
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: wintertime on November 10, 2013, 01:21:08 am
Ahh I think that was because a Sprite gets implicitly resized with the Texture.
You can switch the type to use a RectangleShape instead and set the size of that at its construction to 800x600; everything else should be nearly the same.
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: nebula on November 10, 2013, 04:30:25 am
i think i am doin this wrong :D does not work like i wish

header
#ifndef GUIMOVABLEBACKGROUNDS_H
#define GUIMOVABLEBACKGROUNDS_H

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

class MovableBackground
{
public:
        MovableBackground();
        void Update(sf::RenderWindow &window, float elapsedTime);
        void Render(sf::RenderWindow &window);
       
private:
        sf::Texture bgTex;
        sf::Texture bg2Tex;

        sf::RectangleShape bgShape;
        sf::Vector2f bgSize;

        sf::Sprite      bgSprite;
        sf::Sprite      bg2Sprite;

        float bgSpeed;
        float bgY;
        float bg2Y;
        float windowbg1diff;
};
#endif
 

cpp
#include "GUImovableBackground.h"


MovableBackground::MovableBackground()
{
        bgSpeed = 0.3;

        bgTex.loadFromFile("graphics//background.jpg");
        bgTex.setSmooth(false);
        bgTex.setRepeated(true);

        bgY = bgShape.getPosition().y;
        bgSize.x = 800;
        bgSize.y = 600;

        bgShape.setTexture(&bgTex);
        bgShape.setSize(bgSize);
}


void MovableBackground::Update(sf::RenderWindow &window, float elapsedTime)
{
        if (bgY < 600)
        {
                bgY += bgSpeed * elapsedTime;
        }else
                {
                        bgY = 0;
                }
        bgShape.setPosition(0, bgY);
}
void MovableBackground::Render(sf::RenderWindow &window)
{
        window.draw(bgShape);
}
 
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: G. on November 10, 2013, 05:00:40 am
wintertime kindly gave you a short snippet of code, almost ready to be copied/pasted, and it doesn't seem like you bothered to read it.
Why do you move your background? You're supposed to modify its TextureRect.

It works with a Sprite or a RectangleShape.
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: nebula on November 10, 2013, 02:46:47 pm
i did read all of it. and looked it all up in the api. i try it all again and if i got it going i will post it ;)

I found the mistake :D

what wintertime did:
Quote
    bgY = 0;
what i did:
Quote
bgY = bgShape.getPosition().y;

@wintertime thanks a lot! now it does exactly move how it is supposed to. but uhhm did you edit the post? i think the initialization of bgY was not there in first place :D

ps:
I changed       
bgY += bgSpeed * elapsedTime;
into        
bgY -= bgSpeed * elapsedTime;
because the rect needs to go upwards to get the feeling of the background moving downwards :D
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: wintertime on November 10, 2013, 04:01:29 pm
If you didn't read it in the first 2.5 minutes after the posting got visible, there was no more edits after that. (Normally I only use spaces, but the existing lines contained tabs already. When I was typing in tabs to format the code consistently the forum editor was reacting weirdly and posted it prematurely without me clicking.)
Though the main point was calling setTextureRect before drawing.
Title: Re: [C++ and SFML 2.1] Scrolling backgrounds ( y+)
Post by: nebula on November 10, 2013, 05:33:19 pm
okay then i think i just overread it. in the screenshot i posted you can see that the initialization of bgY was not in your post, so i thought that it was correct. but now i totally understand that it was bullsh*t what i coded.

yeah the setTextureRect is logical because i do not want to change the sprites position but the area it shows. you really helped me out and for that i thank you a lot wintertime!

now, that the problem is solved i think it can be seen as solved