Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LibGdx How to repeat background?

Tags:

java

libgdx

Few days ago I figured out how to do some scrolling in LibGdx. Now I'm triying to do something related. I want to repeat the background. My scrolling follows a ship (Is an s[ace ship game). In the background there is a space photo loaded as a Texture. When the ship reach the end of the backgorund, It keeps going and there's no background anymore. I have read about wrap but I don't really understand How It works. I did that:

    px=new Pixmap(Gdx.files.internal("fondo.jpg"));
    background=new Texture(px);
    background.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);

And then, in my render method

spriteBatch.begin();
    spriteBatch.draw(background,0,0,500,50);
    drawShip();
spriteBatch.end();

Of course It doesn't work, It only draws the background once. I don't know how make this wrap method work. Any help?

SOLUTION

I figured It out. It's not a nice code but It works.

First I declare two Textures with the same image

 bck1=new Texture(Gdx.files.internal("fondo.jpg"));
 bck2=new Texture(Gdx.files.internal("fondo.jpg"));

Also I declare two variables like this to specify the X value of the position of each bck

 int posXBck1=0,posXBck2=0;

Then I use that in Render()

 public void calculoPosicionFondos(){
    posXBck2=posXBck1+ANCHODEFONDO;
    if(cam.position.x>=posXBck2+cam.viewportWidth/2){
        posXBck1=posXBck2;
    }
}

Where:

ANCHODEFONDO is the width of my background

Cam is an OtrhoCam.

So I said that if the cam is in bck2 (wich means that you can't see bck1 anymore) It change positions, giving bck1 de position of bck2 and, in the next render loop, recalculating bck2

Then just paint both bck in your render mode.

like image 460
MBRebaque Avatar asked Jan 30 '13 12:01

MBRebaque


3 Answers

Like Teitus said, do not load your texture multiple times, ever! Anyway, you where on the right track with the wrapper:

texture.setWrap(TextureWrap.Repeat, TextureWrap.Repeat);

Now you can just use the draw method with the source location. The source location is the area you choose to draw on the texture.

batch.draw(texture, x, y, srcX, srcY, srcWidth, srcHeight)

To scroll your texture from right to left all you have to do is increase srcX incrementally. So create a int that increments in the update/render method.

int sourceX = 0;

//render() method

//Increment the variable where to draw from on the image.
sourceX += 10;

//Simply draw it using that variable in the srcX.    
batch.draw(YourTexture, 0, 0, sourceX, 0, screenWidth, screenHeight);

Because you are wrapping the texture it will wrap/loop and scroll indefinitely. There might be a issue with the sourceX int if the game runs for a very long time because a int can only hold 2147483647. It takes a while but you can fix it by subtracting the image width each time the number goes over the total image width.

like image 167
Madmenyo Avatar answered Oct 06 '22 09:10

Madmenyo


Don't to this, please:

bck1=new Texture(Gdx.files.internal("fondo.jpg"));
bck2=new Texture(Gdx.files.internal("fondo.jpg"));

That will load your big background texture twice. That's a complete waste. If you want to keep your solution at least do:

bck1=new Texture(Gdx.files.internal("fondo.jpg"));
bck2=bkg1;

Regarding the texture Wrapping. If your texture is 500px wide, and you draw a 500px sprite, you won't see any repetition. If you want it repeated 2 times, draw it 1000px wide with 0-2 texture coordinates. I'm not sure how spriteBatch handles the call you posted, you could try that one, or may be use the overload that uses a texture region and set your region manually.

like image 33
aacotroneo Avatar answered Oct 06 '22 10:10

aacotroneo


I see this is a pretty old question, but I think there is an easier way to accomplish background scrolling. Just use the Sprite class. Here is a snippet I use for layered background images that scroll from right to left.

public class LevelLayer 
{
    public float speedScalar = 1;

    private List<Sprite> backgroundSprites = new ArrayList<Sprite>();

    public LevelLayer()
    {

    }

    public void addSpriteLayer(Texture texture, float startingPointX, float y, int repeats)
    {
        for (int k = 0; k < repeats; k++)
        {
          Sprite s = new Sprite(texture);
          s.setX(startingPointX + (k*texture.getWidth()));
          s.setY(y);

          backgroundSprites.add(s);
        }
    }

  public void render(SpriteBatch spriteBatch, float speed)  
  { 
    for (Sprite s : backgroundSprites)
    {
        float delta = s.getX() - (speed * speedScalar);
        s.setX(delta);

        s.draw(spriteBatch);
    }
  }
}

Then you can use the same texture or series of textures like so:

someLayer.addSpriteLayer(sideWalkTexture1, 0, 0, 15);
someLayer.addSpriteLayer(sideWalkTexture2, 15 * sideWalkTexture1.getWidth(), 0, 7);

I change background repeating sections randomly in code and make new ones or reset existing sets when they go off screen. All the layers go to a pool and get pulled randomly when a new one is needed.

like image 20
dreamwagon Avatar answered Oct 06 '22 11:10

dreamwagon