LibGDX guidance - sprite tracing 2D infinite rando

2019-04-12 09:50发布

问题:

I've been able to apply a smooth animation to my sprite and control it using the accelerometer. My sprite is fixed to move left and right along the x-aixs.

From here, I need to figure out how to create a vertical infinite wavy line for the sprite to attempt to trace. the aim of my game is for the user to control the sprite's left/right movement with the accelerometer in an attempt to trace the never ending wavy line as best they can, whilst the sprite and camera both move in a vertical direction to simulate "moving along the line." It would be ideal if the line was randomly generated.

I've researched about splines, planes, bezier curves etc, but I can't find anything that seems to relate close enough to what I'm trying to achieve.

I'm just seeking some guidance as to what methods I could possibly use to achieve this. Any ideas?

回答1:

You could use sum of 4 to 5 sine waves (each with different amplitude, wavelength and phase difference). All 3 of those parameters could be random.

The resulting curve would be very smooth (since it is primarily sinusoidal) yet it'll look random (it's time period would be LCM of all 4 to 5 random wavelengths which is a huge number).

So the curve won't repeat for a long time, yet it will not be hard on memory. Concerning computational complexity, you can always tune it by changing number of sine terms with FPS.

It should look like this.

It's really easy to implement too. (even I could generate above image.. haha)

Hope this helps. Maths rocks. :D

(The basic idea here is a finite Fourier series which I think should be ideal for your use case)


Edit:

You can create each term like this and assign random values to all terms.

public class SineTerm {

    private float amplitude;
    private float waveLength;
    private float phaseDifference;

    public SineTerm(float amplitude, float waveLength, float phaseDifference) {
        this.amplitude = amplitude;
        this.waveLength = waveLength;
        this.phaseDifference = phaseDifference;
    }

    public float evaluate(float x) {
        return amplitude * (float) Math.sin(2 * Math.PI * x / waveLength + phaseDifference);
    }

}

Now create an array of SineTerms and add all values returned by evaluate(x) (use one coordinate of sprite as input). Use the output as other coordinate of sprite. You should be good to go.

The real trick would be in tuning those random numbers.

Good luck.