0
\$\begingroup\$

I want to shake my OrhographicCamera on some event (i.e. click on the keyboard). How can I do that?

\$\endgroup\$
0
\$\begingroup\$

My approach to this problem is to create a child class of an OrthographicCamera() and add some functionality to its update() method.

import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.OrthographicCamera
import java.util.Random

class ShakyCamera: OrthographicCamera() {

    private lateinit var samples: FloatArray

    private var timer = 0f
    private var duration = 0f

    private var amplitude = 0
    private var frequency = 0
    private var isFading = true

    private var shake = false

    private fun ClosedRange<Int>.random() = Random().nextInt((endInclusive + 1) - start) +  start

    fun shake(time: Float = 1f, amp: Int = 10, freq: Int = 35, fade: Boolean = true) {
        shake = true
        timer = 0f
        duration = time
        amplitude = amp
        frequency = freq
        isFading = fade
        samples = FloatArray(frequency)
        for (i in 0 until frequency) {
//            samples[i] = Random().nextFloat() * 2f - 1f
            samples[i] = (-1..1).random().toFloat() // only 3 variants (-1, 0, 1) and same visible effect as function above, lol
        }
    }

    override fun update() {
        if (shake) {
            if (timer > duration) shake = false
            val dt = Gdx.graphics.deltaTime
            timer += dt
            if (duration > 0) {
                duration -= dt
                val shakeTime = timer * frequency
                val first = shakeTime.toInt()
                val second = (first + 1) % frequency
                val third = (first + 2) % frequency
                val deltaT = shakeTime - shakeTime.toInt()
                val deltaX = samples[first] * deltaT + samples[second] * (1f - deltaT)
                val deltaY = samples[second] * deltaT + samples[third] * (1f - deltaT)

                position.x += deltaX * amplitude * if (isFading) Math.min(duration, 1f) else 1f
                position.y += deltaY * amplitude * if (isFading) Math.min(duration, 1f) else 1f
            }
        }
            super.update()
    }
}

Make an object in your main class (add it to the Stage if you need):

    private val camera = ShakyCamera()
    private val stage = Stage(FillViewport(1280, 720, camera), batch)

Then call shake fuction when you need it (i.e. when you click a key):

handler = object: InputAdapter() {
        override fun keyDown(keycode: Int): Boolean {
            when (keycode) {
                Input.Keys.S -> camera.shake()
            }
            return true
        }
    }
\$\endgroup\$
0
\$\begingroup\$

This is a good example:

Create a Rumble class to manage the shaking:

public class Rumble {
    private static float time = 0;
    private static float currentTime = 0;
    private static float power = 0;
    private static float currentPower = 0;
    private static Random random;
    private static Vector3 pos = new Vector3();

    public static void rumble(float rumblePower, float rumbleLength) {
        random = new Random();
        power = rumblePower;
        time = rumbleLength;
        currentTime = 0;
    }

    public static Vector3 tick(float delta) {
        if (currentTime <= time) {
            currentPower = power * ((time - currentTime) / time);

            pos.x = (random.nextFloat() - 0.5f) * 2 * currentPower;
            pos.y = (random.nextFloat() - 0.5f) * 2 * currentPower;

            currentTime += delta;
        } else {
            time = 0;
        }
        return pos;
    }

    public static float getRumbleTimeLeft() {
        return time;
    }

    public static Vector3 getPos() {
        return pos;
    }
}

To start Rumble call:

Rumble.rumble(1, .2f);

And in the render method:

if (Rumble.getRumbleTimeLeft() > 0){
    Rumble.tick(Gdx.graphics.getDeltaTime());
    camera.translate(Rumble.getPos());
}

The example is from this tutorial:
https://carelesslabs.wordpress.com/2017/08/14/making-a-libgdx-roguelike-survival-game-part-9-screen-shake-inventory-gamedev/

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.