2

I want in my game there to be sort of sound waves going around the screen. I'm able to make a sine that goes straight but how do I make a sine rotated 20 degrees? So for example that goes from the left bottom corner to the right upper corner?

        let pi = CGFloat.pi
        let wave = Waves[0]
        let x = path.currentPoint.x
        let c = (2 * pi) / (wave.Wavelength * 30)
        let a = 30 * wave.Amplitude

        let y = a * sin(c * x)

        path.addLine(to: CGPoint(x: x + 2, y: y ))

2 Answers2

2

You can make a UIBezierPath that approximates a sine wave pretty accurately with 2 Bézier curves:

/// Make a path that approximates a peak-to-peak sine wave
func sinePath(size: CGSize) -> UIBezierPath {
  let path = UIBezierPath()

  // path starts at 0,0
  path.move(to: CGPoint.zero)

  let halfWidth = size.width / 2.0

  // base x-values for control points
  // baseX approximates the best fit Bézier curve for a sine wave
  let baseX:  = CGFloat(0.3642124232)
  let firstX  = halfWidth * baseX
  let secondX = halfWidth * (1.0 - baseX)

  // curve from start peak to trough
  path.addCurve(to: CGPoint(x: halfWidth, y: size.height),
                controlPoint1: CGPoint(x: firstX , y: 0),
                controlPoint2: CGPoint(x: secondX, y: size.height))

  // curve from trough to end peak
  path.addCurve(to: CGPoint(x: size.width, y:0),
                controlPoint1: CGPoint(x: size.width - secondX, y: size.height),
                controlPoint2: CGPoint(x: size.width - firstX , y: 0))
  return path
}

Then you can rotate it with a CGAffineTransform like this:

/// Convert degrees to radians
func degreeToRadian(_ angle: CGFloat) -> CGFloat {
  return angle * CGFloat.pi / 180.0
}

let path = sinePath(size: CGSize(width: 200.0, height: 100.0))
path.apply(CGAffineTransform(rotationAngle: degreeToRadian(20)))

I got the baseX constant from this question:

How to approximate a half-cosine curve with bezier paths in SVG?

0

You can apply affine transformation of rotation to calculated point positions

xnew = xbase + (x - xbase) * Cos(rot_angle) - (y - ybase) * Sin(rot_angle)
ynew = ybase + (x - xbase) * Sin(rot_angle) + (y - ybase) * Cos(rot_angle)

Here (xbase, ybase) - coordinates of center of rotation (perhaps 0,0 in your case), rot_angle - angle of rotation, in your case 20 * Pi / 180

Probably your graphics library already contains facilities for affine transformations, in this case just form transformation matrix and apply it.

MBo
  • 77,366
  • 5
  • 53
  • 86