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

Author Topic: Viewport moving parallax backgrounds  (Read 2513 times)

0 Members and 1 Guest are viewing this topic.

ESuth

  • Newbie
  • *
  • Posts: 3
    • View Profile
Viewport moving parallax backgrounds
« on: April 13, 2020, 04:56:23 pm »
So I'm trying to make a 2d shooting scroller.

I set up a scrolling background that has different levels for a parallax effect. I have it all set up and working. But as soon as I try to set a viewport to follow the player. It messes up the positions of the backgrounds and they no longer stay seamless and continue on as they should. Why is it when I try to use the viewport and scroll it along, it also changes the positions of the background images?

The way I'm doing this is by having two sprites and assigning the same texture to them both. Having the first sprite the size of the screen. And the second sprite the same size but to the right of the first one. Then as the player presses right or left, I scroll the sprite either left or right. And as one sprite goes off screen, I am redrawing it on the other side of the other sprite to make it seem like its continuous. I repeated this step with different speeds for each layer. And it works (if you don't move the viewport). But as soon as I use the viewport everything goes strange and the backgrounds dont join up anymore.

I am a bit of a beginner and don't really understand why this happens. Can anyone help by explaining why this is happening or how I can stop it from happening? it's as if the viewport changes the global positioning of everything?

const int screenWidth = 1920;
const int screenHeight = 1080;

static shared_ptr<Entity> player;

Texture mage;
Texture skele;
Texture skeletArcher;
Texture skeletChief;
Sprite skeleton;

Sprite bckSprites[12];

Texture bckTextures[6];

View view;

void Level2Scene::Load() {
  cout << "Scene 2 Load" << endl;
  ls::loadLevelFile("res/level_2.txt", 40.0f);

//Set Viewport for scrolling screen
  view.reset(sf::FloatRect(0, 0, screenWidth, screenHeight));
  view.setViewport(sf::FloatRect(0, 0, 1.0f, 1.0f));

  //Background
  // *********************************
  if (!bckTextures[0].loadFromFile("res/layer1.png"))
  {
      cout << "Couldn't load Background1!" << endl;
  }
  if (!bckTextures[1].loadFromFile("res/layer2.png"))
  {
      cout << "Couldn't load Background2!" << endl;
  }
  if (!bckTextures[2].loadFromFile("res/layer3.png"))
  {
      cout << "Couldn't load Background3!" << endl;
  }
  if (!bckTextures[3].loadFromFile("res/layer4.png"))
  {
      cout << "Couldn't load Background4!" << endl;
  }
  if (!bckTextures[4].loadFromFile("res/layer5.png"))
  {
      cout << "Couldn't load Background5!" << endl;
  }
  if (!bckTextures[5].loadFromFile("res/layer6.png"))
  {
      cout << "Couldn't load Background6!" << endl;
  }

  bool t = true;
  int j = 0;
  for (int i = 0; i < 12; i++)
  {  
     
 
      if (t == true)
      {
          bckSprites[i].setTexture(bckTextures[j]);
          bckSprites[i].setPosition(0, 0);
          t = !t;
      }
      else if (t == false)
      {
          bckSprites[i].setTexture(bckTextures[j]);
          bckSprites[i].setPosition(screenWidth, 0);
          t = !t;
          j++;
      }
  }

  // *********************************

  // Create player
  {
  // *********************************
        player = makeEntity();
        player->setPosition(ls::getTilePosition(ls::findTiles(ls::START)[0]));
        auto s = player->addComponent<ShapeComponent>();
        s->setShape<sf::RectangleShape>(Vector2f(20.f, 30.f));
    mage.loadFromFile("res/mage.png");
    s->getShape().setTexture(&mage);
        s->getShape().setOrigin(10.f, 15.f);
   
    player->addTag("player");
    player->addComponent<PlayerMovementComponent>();
    player->setHealth(100);

  }
  // *********************************

// Add physics colliders to level tiles.
  {
    // *********************************
          auto walls = ls::findTiles(ls::WALL);
          for (auto w : walls) {
                  auto pos = ls::getTilePosition(w);
                  pos += Vector2f(20.0f, 20.0f); // offset to centre
                  auto e = makeEntity();
                  e->setPosition(pos);
                  e->addComponent<PhysicsComponent>(false, Vector2f(40.0f, 40.0f));
          }
    // *********************************
  }

  cout << " Scene 2 Load Done" << endl;
  setLoaded(true);
}

void Level2Scene::UnLoad() {
  cout << "Scene 2 UnLoad" << endl;
  player.reset();
  ls::unload();
  Scene::UnLoad();
}

void Level2Scene::Update(const double& dt) {

    //scroll screen as player reaches middle
    //*****************************************************

    Vector2f position(0, 0);

    position.x = player->getPosition().x + 10 - (screenWidth / 2);
    position.y = player->getPosition().y + 10 - (screenHeight / 2);

    if (position.x < 0)
    {
        position.x = 0;
    }
    if (position.y < 0)
    {
        position.y = 0;
    }

    view.reset(FloatRect(position.x, position.y, screenWidth, screenHeight));

   

    //*****************************************************

#pragma region Background Speeds

    if(Keyboard::isKeyPressed(Keyboard::Right))
    {
        bckSprites[0].move(Vector2f(-600 * dt,0));
        bckSprites[1].move(Vector2f(-600 * dt, 0));
    }
    if (Keyboard::isKeyPressed(Keyboard::Left))
    {
        bckSprites[0].move(Vector2f(600 * dt, 0));
        bckSprites[1].move(Vector2f(600 * dt, 0));
    }
   
    if (Keyboard::isKeyPressed(Keyboard::Right))
    {
        bckSprites[2].move(Vector2f(-500 * dt, 0));
        bckSprites[3].move(Vector2f(-500 * dt, 0));
    }
    if (Keyboard::isKeyPressed(Keyboard::Left))
    {
        bckSprites[2].move(Vector2f(500 * dt, 0));
        bckSprites[3].move(Vector2f(500 * dt, 0));
    }

    if (Keyboard::isKeyPressed(Keyboard::Right))
    {
        bckSprites[4].move(Vector2f(-400 * dt, 0));
        bckSprites[5].move(Vector2f(-400 * dt, 0));
    }
    if (Keyboard::isKeyPressed(Keyboard::Left))
    {
        bckSprites[4].move(Vector2f(400 * dt, 0));
        bckSprites[5].move(Vector2f(400 * dt, 0));
    }

    if (Keyboard::isKeyPressed(Keyboard::Right))
    {
        bckSprites[6].move(Vector2f(-300 * dt, 0));
        bckSprites[7].move(Vector2f(-300 * dt, 0));
    }
    if (Keyboard::isKeyPressed(Keyboard::Left))
    {
        bckSprites[6].move(Vector2f(300 * dt, 0));
        bckSprites[7].move(Vector2f(300 * dt, 0));
    }

    if (Keyboard::isKeyPressed(Keyboard::Right))
    {
        bckSprites[8].move(Vector2f(-200 * dt, 0));
        bckSprites[9].move(Vector2f(-200 * dt, 0));
    }
    if (Keyboard::isKeyPressed(Keyboard::Left))
    {
        bckSprites[8].move(Vector2f(200 * dt, 0));
        bckSprites[9].move(Vector2f(200 * dt, 0));
    }

    if (Keyboard::isKeyPressed(Keyboard::Right))
    {
        bckSprites[10].move(Vector2f(-100 * dt, 0));
        bckSprites[11].move(Vector2f(-100 * dt, 0));
    }
    if (Keyboard::isKeyPressed(Keyboard::Left))
    {
        bckSprites[10].move(Vector2f(100 * dt, 0));
        bckSprites[11].move(Vector2f(100 * dt, 0));
    }

#pragma endregion


#pragma region Move Backgrounds


    if (bckSprites[0].getPosition().x < -1920)
    {
        bckSprites[0].setPosition(bckSprites[1].getPosition().x + 1920, 0);
    }
    if (bckSprites[0].getPosition().x > 1920)
    {
        bckSprites[0].setPosition(bckSprites[1].getPosition().x - 1920, 0);
    }

    cout << "PlayerPos: " << position << " spritePos: " << bckSprites[0].getPosition().x << endl;

    if (bckSprites[1].getPosition().x < -1920)
    {              
        bckSprites[1].setPosition(bckSprites[0].getPosition().x + 1920, 0);
    }              
    if (bckSprites[1].getPosition().x > 1920)
    {              
        bckSprites[1].setPosition(bckSprites[0].getPosition().x - 1920, 0);
    }
    if (bckSprites[2].getPosition().x < -1920)
    {
        bckSprites[2].setPosition(bckSprites[3].getPosition().x + 1920, 0);
    }
    if (bckSprites[2].getPosition().x > 1920)
    {
        bckSprites[2].setPosition(bckSprites[3].getPosition().x - 1920, 0);
    }
    if (bckSprites[3].getPosition().x < -1920)
    {
        bckSprites[3].setPosition(bckSprites[2].getPosition().x + 1920, 0);
    }
    if (bckSprites[3].getPosition().x > 1920)
    {
        bckSprites[3].setPosition(bckSprites[2].getPosition().x - 1920, 0);
    }
    if (bckSprites[4].getPosition().x < -1920)
    {
        bckSprites[4].setPosition(bckSprites[5].getPosition().x + 1920, 0);
    }
    if (bckSprites[4].getPosition().x > 1920)
    {
        bckSprites[4].setPosition(bckSprites[5].getPosition().x - 1920, 0);
    }
    if (bckSprites[5].getPosition().x < -1920)
    {
        bckSprites[5].setPosition(bckSprites[4].getPosition().x + 1920, 0);
    }
    if (bckSprites[5].getPosition().x > 1920)
    {
        bckSprites[5].setPosition(bckSprites[4].getPosition().x - 1920, 0);
    }
    if (bckSprites[6].getPosition().x < -1920)
    {
        bckSprites[6].setPosition(bckSprites[7].getPosition().x + 1920, 0);
    }
    if (bckSprites[6].getPosition().x > 1920)
    {
        bckSprites[6].setPosition(bckSprites[7].getPosition().x - 1920, 0);
    }
    if (bckSprites[7].getPosition().x < -1920)
    {
        bckSprites[7].setPosition(bckSprites[6].getPosition().x + 1920, 0);
    }
    if (bckSprites[7].getPosition().x > 1920)
    {
        bckSprites[7].setPosition(bckSprites[6].getPosition().x - 1920, 0);
    }
    if (bckSprites[8].getPosition().x < -1920)
    {
        bckSprites[8].setPosition(bckSprites[9].getPosition().x + 1920, 0);
    }
    if (bckSprites[8].getPosition().x > 1920)
    {
        bckSprites[8].setPosition(bckSprites[9].getPosition().x - 1920, 0);
    }
    if (bckSprites[9].getPosition().x < -1920)
    {
        bckSprites[9].setPosition(bckSprites[8].getPosition().x + 1920, 0);
    }
    if (bckSprites[9].getPosition().x > 1920)
    {
        bckSprites[9].setPosition(bckSprites[8].getPosition().x - 1920, 0);
    }
    if (bckSprites[10].getPosition().x < -1920)
    {
        bckSprites[10].setPosition(bckSprites[11].getPosition().x + 1920, 0);
    }
    if (bckSprites[10].getPosition().x > 1920)
    {
        bckSprites[10].setPosition(bckSprites[11].getPosition().x - 1920, 0);
    }
    if (bckSprites[11].getPosition().x < -1920)
    {
        bckSprites[11].setPosition(bckSprites[10].getPosition().x + 1920, 0);
    }
    if (bckSprites[11].getPosition().x > 1920)
    {
        bckSprites[11].setPosition(bckSprites[10].getPosition().x - 1920, 0);
    }

#pragma endregion
 

  Scene::Update(dt);

  const auto pp = player->getPosition();

  if (ls::getTileAt(pp) == ls::END) {
    Engine::ChangeScene((Scene*)&level3);
  } else if (!player->isAlive()) {
    Engine::ChangeScene((Scene*)&gameOver);
  }


}

void Level2Scene::Render() {

    for (int i = 11; i > -1; i--)
    {
        Engine::GetWindow().draw(bckSprites[i]);
    }

  ls::render(Engine::GetWindow());
  Engine::GetWindow().setView(view);
 
  Scene::Render();
}
 

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Viewport moving parallax backgrounds
« Reply #1 on: April 13, 2020, 05:10:31 pm »
Quickly skimming through your code, it looks like you're moving a view and the objects. This is not necessary. Just do one of those.

If you use views, you can use multiple views. Use one for each level of parallax depth. Simplifies a lot.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*

ESuth

  • Newbie
  • *
  • Posts: 3
    • View Profile
Re: Viewport moving parallax backgrounds
« Reply #2 on: April 13, 2020, 05:57:42 pm »
If you use views, you can use multiple views. Use one for each level of parallax depth. Simplifies a lot.

I can set it so that it will move the sprites as the player position moves. And have it scroll properly with the view on one layer. But how do I set up multiple views at the same time to do something like this?

Hapax

  • Hero Member
  • *****
  • Posts: 3379
  • My number of posts is shown in hexadecimal.
    • View Profile
    • Links
Re: Viewport moving parallax backgrounds
« Reply #3 on: April 13, 2020, 07:21:18 pm »
St up two different views, one for each depth, and then activate the view before drawing the stuff at that depth.

sf::View viewFar;
sf::View viewNear;

// ...

window.clear();

window.setView(viewFar);
window.draw(farAwayStuff);

window.setView(viewNear);
window.draw(nearStuff);

window.display();

Basically, set "viewFar" to be larger so that it moves slower. It could be the same as viewNear but zoomed out.
Selba Ward -SFML drawables
Cheese Map -Drawable Layered Tile Map
Kairos -Timing Library
Grambol
 *Hapaxia Links*