Search code examples
mathunity-game-enginegame-makertrigonometry

Sin wave line from x1,y1 to x2,y2


EXAMPLE PICTURE :

I want to be able to draw lines from one point to another that are just like the lines shown in the picture above, but I'm not sure how to go about doing so.

I'm using GML but if you give me any other code then i'll more than likely be able to understand it.


Solution

  • Despite kind of looking like a sin wave, that is actually a cubic Bézier curve. That Wikipedia article goes through the math, and here is an article that walks through an implementation that should be fairly straightforward. Assuming that you're generally drawing lines horizontally like in UE4 blueprints, I would place the control points at the horizontal midpoint, and at the same y-level as the endpoint that each is controlling, creating a "step" shape:

    p0 .  .  .  p1 .  .  .  .
    .  .  .  .  .  .  .  .  .
    .  .  .  .  p2 .  .  .  p3
    

    First, you'll need to create a function that can calculate a point on a given curve. Here's the C# implementation from the article:

    Vector3 CalculateBezierPoint(float t,
      Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
    {
        float u = 1 – t;
        float tt = t*t;
        float uu = u*u;
        float uuu = uu * u;
        float ttt = tt * t;
    
        Vector3 p = uuu * p0; //first term
        p += 3 * uu * t * p1; //second term
        p += 3 * u * tt * p2; //third term
        p += ttt * p3; //fourth term
    
        return p;
    }
    

    You can change Vector3 into a 2D Vector2 structure, or break it out into x/y values and just adjust the math to compensate (I apologize, it's been about a decade since I've used GML so I'm not sure what types of data structures you have to work with).

    Now that you have a way to calculate points on a curve, you can write a function to draw it. The simplest way to draw it without any missing pixels would be to draw a series of line segments. Again, here's the C# implementation in the article:

    q0 = CalculateBezierPoint(0, p0, p1, p2, p3);
    
    for(int i = 1; i <= SEGMENT_COUNT; i++)
    {
        t = i / (float) SEGMENT_COUNT;
        q1 = CalculateBezierPoint(t, p0, p1, p2, p3);
        DrawLine(q0, q1);
        q0 = q1;
    }
    

    There are better ways of doing it, but that should get you started and give you some vocabulary for further searching. Cheers!