Parallax scrolling is a special scrolling technique that creates the illusion of depth in a 2D scene. Therefore, the objects in the background move slower than the objects in the foreground when the camera moves by.
We will now implement a parallax scrolling effect for the mountains in the background of the game screen.
Add the following import line to the Mountains
class:
import com.badlogic.gdx.math.Vector2;
After this, add the following lines of code to the same class:
public void updateScrollPosition (Vector2 camPosition) { position.set(camPosition.x, position.y); }
Next, make the following changes to the same class:
private void drawMountain (SpriteBatch batch, float offsetX, float offsetY, float tintColor, float parallaxSpeedX) { TextureRegion reg = null; batch.setColor(tintColor, tintColor, tintColor, 1); floatxRel = dimension.x * offsetX; floatyRel = dimension.y * offsetY; // mountains span the whole level int mountainLength = 0; mountainLength += MathUtils.ceil(length / (2 * dimension.x) * (1 - parallaxSpeedX)); mountainLength += MathUtils.ceil(0.5f + offsetX); for (int i = 0; i<mountainLength; i++) { // mountain left reg = regMountainLeft; batch.draw(reg.getTexture(), origin.x + xRel + position.x * parallaxSpeedX, origin.y + yRel + position.y, origin.x, origin.y, dimension.x, dimension.y, scale.x, scale.y, rotation, reg.getRegionX(), reg.getRegionY(), reg.getRegionWidth(), reg.getRegionHeight(), false, false); xRel += dimension.x; // mountain right reg = regMountainRight; batch.draw(reg.getTexture(), origin.x + xRel + position.x * parallaxSpeedX, origin.y + yRel + position.y, origin.x, origin.y, dimension.x, dimension.y, scale.x, scale.y, rotation, reg.getRegionX(), reg.getRegionY(), reg.getRegionWidth(), reg.getRegionHeight(), false, false); xRel += dimension.x; } // reset color to white batch.setColor(1, 1, 1, 1); } @Override public void render (SpriteBatch batch) { // 80% distant mountains (dark gray) drawMountain(batch, 0.5f, 0.5f, 0.5f, 0.8f); // 50% distant mountains (gray) drawMountain(batch, 0.25f, 0.25f, 0.7f, 0.5f); // 30% distant mountains (light gray) drawMountain(batch, 0.0f, 0.0f, 0.9f, 0.3f); }
We have added a fifth parameter to drawMountain()
that ranges between 0.0
and 1.0
and describes the distance and its scrolling speed. The scrolling depends on the camera's current position, which is then multiplied with the distance factor. This is the reason why we have also added a new method called updateScrollPosition()
, which needs to be called in every update cycle where the camera can move.
Make the following changes to the WorldController
class:
public void update (float deltaTime) { handleDebugInput(deltaTime); if (isGameOver()) { timeLeftGameOverDelay -= deltaTime; if (timeLeftGameOverDelay< 0) backToMenu(); } else { handleInputGame(deltaTime); } level.update(deltaTime); testCollisions(); cameraHelper.update(deltaTime); if (!isGameOver() &&isPlayerInWater()) { lives--; if (isGameOver()) timeLeftGameOverDelay = Constants.TIME_DELAY_GAME_OVER; else initLevel(); } level.mountains.updateScrollPosition(cameraHelper.getPosition()); }
All three mountain layers will now scroll at different speeds: 30 percent, 50 percent, and 80 percent.