BrunoMario
BrunoMario

Reputation: 11

LIBGDX horizontal and vertical parallax background

Im trying to do a little game in LibGdx, right now i have a spaceship that can move with a touchpad in every directions and the camera follows it. Im tryng to accomplish a parallax background made of stars that moves depending of where the spaceship is going.

Here it is the code, Im giving you all the class just to be sure to not mess up, for im new with this programming code.

public class TouchPadTest extends OrthographicCamera implements ApplicationListener {
public static final int WIDTH=480;
public static final int HEIGHT=800;
private OrthographicCamera camera;
private Stage stage;
private SpriteBatch batch;
private Touchpad touchpad;
private TouchpadStyle touchpadStyle;
private Skin touchpadSkin;
private Drawable touchBackground;
private Drawable touchKnob;
private Texture blockTexture;
private Sprite blockSprite;
private float blockSpeed;


public void create() {

    batch = new SpriteBatch();
    //Create camera
    float aspectRatio = (float) Gdx.graphics.getWidth() / (float) Gdx.graphics.getHeight();
    camera = new OrthographicCamera();
    camera.setToOrtho(false, TouchPadTest.WIDTH, TouchPadTest.HEIGHT);

    //Create a touchpad skin
    touchpadSkin = new Skin();
    //Set background image
    touchpadSkin.add("touchBackground", new Texture("data/touchBackground.png"));
    //Set knob image
    touchpadSkin.add("touchKnob", new Texture("data/touchKnob.png"));
    //Create TouchPad Style
    touchpadStyle = new TouchpadStyle();
    //Create Drawable's from TouchPad skin
    touchBackground = touchpadSkin.getDrawable("touchBackground");
    touchKnob = touchpadSkin.getDrawable("touchKnob");
    //Apply the Drawables to the TouchPad Style
    touchpadStyle.background = touchBackground;
    touchpadStyle.knob = touchKnob;
    //Create new TouchPad with the created style
    touchpad = new Touchpad(10, touchpadStyle);
    //setBounds(x,y,width,height)
    touchpad.setBounds(15, 15, 200, 200);


    //Create a Stage and add TouchPad
    stage = new Stage(new FitViewport(Gdx.graphics.getWidth(),Gdx.graphics.getHeight()));
    stage.addActor(touchpad);
    Gdx.input.setInputProcessor(stage);

    //Create block sprite
    blockTexture = new Texture(Gdx.files.internal("data/shuttle2.png"));
    blockSprite = new Sprite(blockTexture);
    //Set position to centre of the screen
    blockSprite.setPosition(Gdx.graphics.getWidth()/2-blockSprite.getWidth()/2, Gdx.graphics.getHeight()/2-blockSprite.getHeight()/2);

    blockSpeed=5;

}

public void movePlayer(){

    Vector2 v = new Vector2(touchpad.getKnobPercentX(), touchpad.getKnobPercentY());
    float angle = v.angle();

    if (touchpad.isTouched()){
        blockSprite.setRotation(angle);
    }

    blockSprite.setX(blockSprite.getX() + touchpad.getKnobPercentX()*blockSpeed);

    blockSprite.setY(blockSprite.getY() + touchpad.getKnobPercentY()*blockSpeed);

    //Draw

    camera.position.set(blockSprite.getX() + blockSprite.getWidth() / 2, blockSprite.getY() + blockSprite.getHeight() / 2, 0);

    camera.update();

    batch.setProjectionMatrix(camera.combined);

}



public void renderBackground() {
    //---------------PARALLAX BACKGROUND---------------------//



}



public void dispose() {

}



public void render() {

    Gdx.gl.glClearColor(0/255f,5/255f,15/255f,1);

    Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);




    //Move blockSprite with TouchPad

    movePlayer();

    batch.begin();

    renderBackground();

    blockSprite.draw(batch);

    batch.end();

    stage.act(Gdx.graphics.getDeltaTime());

    stage.draw();

}



@Override

public void pause() {

}



@Override

public void resume() {

}



@Override

public void resize(int width, int height) {

}

}

For a better exemple, this is the kind of result that i want to achieve: https://www.youtube.com/watch?v=zA91SaOR-Io, if you can help me it will be amazing. Thank You.

Upvotes: 1

Views: 720

Answers (1)

dfour
dfour

Reputation: 1376

This working example of a 3 layer parallax background was adapted from the LibGdx Parallax test and should give you an idea on how to implement a parallax effect. The three images used are all 1024x1024px.

import com.badlogic.gdx.ApplicationAdapter;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.InputProcessor;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.Matrix4;
import com.badlogic.gdx.math.Vector3;

public class Test extends ApplicationAdapter implements InputProcessor{
    private SpriteBatch batch;
    private ParallaxCamera camera;
    private Texture bgClose;
    private Texture bgMid;
    private Texture bgFar;
    final Vector3 curr = new Vector3();
    final Vector3 last = new Vector3(-1, -1, -1);
    final Vector3 delta = new Vector3();

    @Override
    public void create () {
        bgClose = new Texture(Gdx.files.internal("starbg-close.png"));
        bgMid = new Texture(Gdx.files.internal("starbg-mid.png"));
        bgFar = new Texture(Gdx.files.internal("starbg-far.png"));
        camera = new ParallaxCamera(1920,1080);
        batch = new SpriteBatch();
        Gdx.input.setInputProcessor(this);
    }

    @Override
    public void render () {
        //clear screen
        Gdx.gl.glClearColor(0f, 0f, 0f, 1f);
        Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);

        // background layer, no parallax, centered around origin
        batch.setProjectionMatrix(camera.calculateParallaxMatrix(0, 0));
        batch.disableBlending();
        batch.begin();
        batch.draw(bgFar, -(int)(bgFar.getWidth() / 2), -(int)(bgFar.getHeight() / 2));
        batch.end();
        batch.enableBlending();


        batch.setProjectionMatrix(camera.calculateParallaxMatrix(0.25f, 0.25f));
        batch.begin();
        for (int i = 0; i < 9; i++) {
            batch.draw(bgMid, i * bgClose.getWidth() - 512, -512);
        }
        batch.end();


        batch.setProjectionMatrix(camera.calculateParallaxMatrix(.5f, .5f));
        batch.begin();
        for (int i = 0; i < 9; i++) {
            batch.draw(bgClose, i * bgClose.getWidth() - 512, -512);
        }
        batch.end();

    }

    //.. omitted empty methods ..//
    @Override
    public boolean touchUp(int screenX, int screenY, int pointer, int button) {
        last.set(-1, -1, -1);
        return false;
    }
    @Override
    public boolean touchDragged(int x, int y, int pointer) {
        camera.unproject(curr.set(x, y, 0));
        if (!(last.x == -1 && last.y == -1 && last.z == -1)) {
            camera.unproject(delta.set(last.x, last.y, 0));
            delta.sub(curr);
            camera.position.add(delta.x, delta.y, 0);
        }
        last.set(x, y, 0);
        return false;
    }

    private class ParallaxCamera extends OrthographicCamera {
        Matrix4 parallaxView = new Matrix4();
        Matrix4 parallaxCombined = new Matrix4();
        Vector3 tmp = new Vector3();
        Vector3 tmp2 = new Vector3();

        public ParallaxCamera (float viewportWidth, float viewportHeight) {
            super(viewportWidth, viewportHeight);
        }

        public Matrix4 calculateParallaxMatrix (float parallaxX, float parallaxY) {
            update();
            tmp.set(position);
            tmp.x *= parallaxX;
            tmp.y *= parallaxY;

            parallaxView.setToLookAt(tmp, tmp2.set(tmp).add(direction), up);
            parallaxCombined.set(projection);
            Matrix4.mul(parallaxCombined.val, parallaxView.val);
            return parallaxCombined;
        }
    }
}

Upvotes: 1

Related Questions