Scrolling parallax background, infinitely repeated in libgdx
Asked Answered
M

4

12

I'm making a 2D sidescrolling space shooter-type game, where I need a background that can be scrolled infintely (it is tiled or wrapped repeatedly). I'd also like to implement parallax scrolling, so perhaps have one lowest background nebula texture that barely moves, a higher one containing far-away stars that barely moves and the highest background containing close stars that moves a lot.

I see from google that I'd have each layer move 50% less than the layer above it, but how do I implement this in libgdx? I have a Camera that can be zoomed in and out, and in the physical 800x480 screen could show anything from 128x128 pixels (a ship) to a huge area of space featuring the textures wrapped multiple times on their edges.

How do I continuosly wrap a smaller texture (say 512x512) as if it were infinitely tiled (for when the camera is zoomed right out), and then how do I layer multiple textures like these, keep them together in a suitable structure (is there one in the libgdx api?) and move them as the player's coords change? I've looked at the javadocs and the examples but can't find anything like this problem, apologies if it's obvious!

Mckee answered 22/9, 2011 at 11:15 Comment(1)
Further info, right now the player input moves the player's sprite around the world coordinates, and the camera remains centered on the player.Mckee
P
3

I have not much more to say regarding to the Parallax Scrolling than PFG already did. There is indeed an example in the repository under the test folder and several explanations around the web. I liked this one. The matter with the background is really easy to solve. This and other related problems can be approached by using modular algebra. I won't go into the details because once shown is very easy to understand.

Imagine that you want to show a compass in your screen. You have a texture 1024x16 representing the cardinal points. Basically all you have is a strip. Letting aside the considerations about the real orientation and such, you have to render it.

Your viewport is 300x400 for example, and you want 200px of the texture on screen (to make it more interesting). You can render it perfectly with a single region until you reach the position (1024-200) = 824. Once you're in this position clearly there is no more texture. But since it is a compass, it's obvious that once you reach the end of it, it has to start again. So this is the answer. Another texture region will do the trick. The range 825-1023 has to be represented by another region. The second region will have a size of (1024-pos) for every value pos>824 && pos<1024

This code is intended to work as real example of a compass. It's very dirty since it works with relative positions all the time due to the conversion between the range (0-3.6) to (0-1024).

spriteBatch.begin();
    if (compassorientation<0)
        compassorientation = (float) (3.6 - compassorientation%3.6);
    else
        compassorientation = (float) (compassorientation %  3.6);
    if ( compassorientation < ((float)(1024-200)/1024*3.6)){
        compass1.setRegion((int)(compassorientation/3.6*1024), 0, 200, 16);
        spriteBatch.draw(compass1, 0, (Gdx.graphics.getHeight()/2) -(-250 + compass1.getTexture().getHeight()* (float)1.2), Gdx.graphics.getWidth(), 32 * (float)1.2);

    }
    else if (compassorientation > ((float)(1024-200)/1024*3.6)) {
        compass1.setRegion((int)(compassorientation/3.6*1024), 0, 1024 - (int)(compassorientation/3.6*1024), 16);
        spriteBatch.draw(compass1, 0, (Gdx.graphics.getHeight()/2) -(-250 + compass1.getTexture().getHeight()* (float)1.2), compass1.getRegionWidth()/200f * Gdx.graphics.getWidth() , 32 * (float)1.2);
        compass2.setRegion(0, 0, 200 - compass1.getRegionWidth(), 16);
        spriteBatch.draw(compass2, compass1.getRegionWidth()/200f * Gdx.graphics.getWidth() , (Gdx.graphics.getHeight()/2) -(-250 + compass1.getTexture().getHeight()* (float)1.2), Gdx.graphics.getWidth() - (compass1.getRegionWidth()/200f * Gdx.graphics.getWidth())  , 32 * (float)1.2);
    } 


    spriteBatch.end();
Peracid answered 24/1, 2012 at 18:16 Comment(0)
U
11

Hey I am also making a parrallax background and trying to get it to scroll.

There is a ParallaxTest.java in the repository, it can be found here.

this file is a standalone class, so you will need to incorporate it into your game how you want. and you will need to change the control input since its hooked up to use touch screen/mouse.

this worked for me. as for repeated bg, i havent gotten that far yet, but i think you just need to basic logic as in, ok one screen away from the end, change the first few screens pos to line up at the end.

Unity answered 24/9, 2011 at 14:11 Comment(1)
ParallaxTest.java now lives at github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/…Shading
P
3

I have not much more to say regarding to the Parallax Scrolling than PFG already did. There is indeed an example in the repository under the test folder and several explanations around the web. I liked this one. The matter with the background is really easy to solve. This and other related problems can be approached by using modular algebra. I won't go into the details because once shown is very easy to understand.

Imagine that you want to show a compass in your screen. You have a texture 1024x16 representing the cardinal points. Basically all you have is a strip. Letting aside the considerations about the real orientation and such, you have to render it.

Your viewport is 300x400 for example, and you want 200px of the texture on screen (to make it more interesting). You can render it perfectly with a single region until you reach the position (1024-200) = 824. Once you're in this position clearly there is no more texture. But since it is a compass, it's obvious that once you reach the end of it, it has to start again. So this is the answer. Another texture region will do the trick. The range 825-1023 has to be represented by another region. The second region will have a size of (1024-pos) for every value pos>824 && pos<1024

This code is intended to work as real example of a compass. It's very dirty since it works with relative positions all the time due to the conversion between the range (0-3.6) to (0-1024).

spriteBatch.begin();
    if (compassorientation<0)
        compassorientation = (float) (3.6 - compassorientation%3.6);
    else
        compassorientation = (float) (compassorientation %  3.6);
    if ( compassorientation < ((float)(1024-200)/1024*3.6)){
        compass1.setRegion((int)(compassorientation/3.6*1024), 0, 200, 16);
        spriteBatch.draw(compass1, 0, (Gdx.graphics.getHeight()/2) -(-250 + compass1.getTexture().getHeight()* (float)1.2), Gdx.graphics.getWidth(), 32 * (float)1.2);

    }
    else if (compassorientation > ((float)(1024-200)/1024*3.6)) {
        compass1.setRegion((int)(compassorientation/3.6*1024), 0, 1024 - (int)(compassorientation/3.6*1024), 16);
        spriteBatch.draw(compass1, 0, (Gdx.graphics.getHeight()/2) -(-250 + compass1.getTexture().getHeight()* (float)1.2), compass1.getRegionWidth()/200f * Gdx.graphics.getWidth() , 32 * (float)1.2);
        compass2.setRegion(0, 0, 200 - compass1.getRegionWidth(), 16);
        spriteBatch.draw(compass2, compass1.getRegionWidth()/200f * Gdx.graphics.getWidth() , (Gdx.graphics.getHeight()/2) -(-250 + compass1.getTexture().getHeight()* (float)1.2), Gdx.graphics.getWidth() - (compass1.getRegionWidth()/200f * Gdx.graphics.getWidth())  , 32 * (float)1.2);
    } 


    spriteBatch.end();
Peracid answered 24/1, 2012 at 18:16 Comment(0)
I
1

You can use setWrap function like below:

Texture texture = new Texture(Gdx.files.internal("images/background.png"));
texture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);

It will draw background repeatedly! Hope this help!

Imco answered 2/11, 2012 at 5:41 Comment(2)
Can you also set the wrap on textureRegions?Kristie
just for reference : this wraps a texture and not a texture region and doesnt work with viewport scaling. It also needs, I believe, a POT texture but may be mistaken.Marcellus
H
1

Beneath where you initialize your Texture for the object. Then beneath that type in this

YourTexture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);

Where YourTexture is your texture that you want to parallax scroll.

In Your render file type in this code.

batch.draw(YourTexture,0, 0, 0 , srcy, Gdx.graphics.getWidth(),     
           Gdx.graphics.getHeight());  
srcy +=10;

It is going to give you an error so make a variable called srcy. It is nothing too fancy.

Int srcy
Housecarl answered 27/6, 2014 at 1:47 Comment(1)
It does not repeat infinitelyGibeon

© 2022 - 2024 — McMap. All rights reserved.