LibGDX parallax scrolling background
Hello guys!
Yesterday I was working on a game project that I started recently and I was in need of implementing parallax scrolling(I think its one of the coolest effects in 2D games) and I was of course Googling first if someone had come up with any great ideas or have implemented this within libgdx and I found something!
My last implementation was horrible and not reusable at all so I couldn’t use it, and the implementation on the forum post wasn’t really either what I was looking for but it gave me basic idea how I should organize it.
I knew I would like to use that parallaxRatio to help with implementing with the effect but things like startPosition and speed were useless for me and were making the code over complicated.
Also for me it seems like its a total waste to create another batch just to draw background because when you end() the batch it gets submitted to the GPU and if you do it many times in frame its inefficient.
Also I don’t see why would the background need to keep track of speed? Enough of arguing that the implementation is horrible on the forum!
So the idea in my head was basically this:
- ParallaxLayer
- xScrollingRatio
- textureRegion
- ParallaxBackground
- List of layers
- width and height of background
- render method that takes x and y position and a sprite batch as a parameter
I handled drawing the background two times so it looks like a continuos by using modulo operator on the x position with width so I wouldn’t have to keep track of anything else within the ParallaxBackground.
I didn’t implement handling different sizes of images withing the background, it just draws two width*height texture regions next to each other.
The varying of layer speed is handler by multiplying xPosition of render method my the xRatio of layer and only after then taking the remainder with modulo operator.
This idea would be easily applied with any language but my implementation with Java using libGDX framework goes like this
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
package com.ruuhkis.parallax; import java.util.ArrayList; import java.util.List; import com.badlogic.gdx.graphics.g2d.SpriteBatch; public class ParallaxBackground { private List<ParallaxLayer> layers; private float width, height; public ParallaxBackground(float width, float height) { this.layers = new ArrayList<ParallaxLayer>(); this.width = width; this.height = height; } public void render(float xPosition, float yPosition, SpriteBatch batch) { for(ParallaxLayer layer: layers) { float layerOffset = (xPosition * layer.getxRatio() % width); layer.render(xPosition - width / 2f - layerOffset, yPosition - height / 2f, width, height, batch); layer.render(xPosition - width / 2f - layerOffset + 5f, yPosition - height / 2f, width, height, batch); } } public List<ParallaxLayer> getLayers() { return layers; } public float getWidth() { return width; } public float getHeight() { return height; } public void addLayer(ParallaxLayer parallaxLayer) { layers.add(parallaxLayer); } } |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
package com.ruuhkis.parallax; import com.badlogic.gdx.graphics.g2d.SpriteBatch; import com.badlogic.gdx.graphics.g2d.TextureRegion; public class ParallaxLayer { private TextureRegion region; private float xRatio; public ParallaxLayer(TextureRegion region, float xRatio) { super(); this.region = region; this.xRatio = xRatio; } public TextureRegion getRegion() { return region; } public float getxRatio() { return xRatio; } public void render(float xPosition, float yPosition, float width, float height, SpriteBatch batch) { batch.draw(region, xPosition, yPosition, width, height); } } |
Outcome: