Move a sphere along the swipe?

I am trying to get a sphere curl based on the swipe. I know this has been asked many times, but still it's yearning to be answered. I have managed to add force on the direction of the swipe and it works near perfect. I also have all the swipe positions stored in a list. Now I would like to know how can the curl be achieved. I believe the the curve in the swipe can be calculated by the Vector dot product

If theta is 0, then there is no need to add the swipe. If it is not, then add the curl. Maybe this condition is redundant if I managed to find how to curl the sphere along the swipe position

The code that adds the force to sphere based on the swipe direction is as below:

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

public class SwipeControl : MonoBehaviour
{
//First establish some variables
private Vector3 fp; //First finger position
private Vector3 lp; //Last finger position
private Vector3 ip; //some intermediate finger position

private float dragDistance;  //Distance needed for a swipe to register
public float power;
private Vector3 footballPos;
private bool canShoot = true;
private float factor = 40f;

private List<Vector3> touchPositions = new List<Vector3>();

void Start(){

dragDistance = Screen.height*20/100;
Physics.gravity = new Vector3(0, -20, 0);
footballPos = transform.position;
}

// Update is called once per frame
void Update()
{
//Examine the touch inputs
foreach (Touch touch in Input.touches)
{
/*if (touch.phase == TouchPhase.Began)
{
fp = touch.position;
lp = touch.position;

}*/

if (touch.phase == TouchPhase.Moved)
{
touchPositions.Add(touch.position);
}

if (touch.phase == TouchPhase.Ended)
{

fp = touchPositions[0];
lp = touchPositions[touchPositions.Count-1];
ip = touchPositions[touchPositions.Count/2];

//First check if it's actually a drag
if (Mathf.Abs(lp.x - fp.x) > dragDistance || Mathf.Abs(lp.y - fp.y) > dragDistance)
{   //It's a drag

//Now check what direction the drag was
//First check which axis
if (Mathf.Abs(lp.x - fp.x) > Mathf.Abs(lp.y - fp.y))
{   //If the horizontal movement is greater than the vertical movement...
if ((lp.x>fp.x) && canShoot)  //If the movement was to the right)
{   //Right move
float x = (lp.x - fp.x) / Screen.height * factor;
rigidbody.AddForce((new Vector3(x,10,16))*power);
Debug.Log("right "+(lp.x-fp.x));//MOVE RIGHT CODE HERE
canShoot = false;
//rigidbody.AddForce((new Vector3((lp.x-fp.x)/30,10,16))*power);
StartCoroutine(ReturnBall());

}
else
{   //Left move
float x = (lp.x - fp.x) / Screen.height * factor;
rigidbody.AddForce((new Vector3(x,10,16))*power);
Debug.Log("left "+(lp.x-fp.x));//MOVE LEFT CODE HERE
canShoot = false;
//rigidbody.AddForce(new Vector3((lp.x-fp.x)/30,10,16)*power);
StartCoroutine(ReturnBall());
}
}
else
{   //the vertical movement is greater than the horizontal movement
if (lp.y>fp.y)  //If the movement was up
{   //Up move
float y = (lp.y-fp.y)/Screen.height*factor;
float x = (lp.x - fp.x) / Screen.height * factor;
rigidbody.AddForce((new Vector3(x,y,16))*power);
Debug.Log("up "+(lp.x-fp.x));//MOVE UP CODE HERE
canShoot = false;
//rigidbody.AddForce(new Vector3((lp.x-fp.x)/30,10,16)*power);
StartCoroutine(ReturnBall());
}
else
{   //Down move
Debug.Log("down "+lp+" "+fp);//MOVE DOWN CODE HERE
}
}

}
else
{   //It's a tap
Debug.Log("none");//TAP CODE HERE
}

}
}

}

IEnumerator ReturnBall() {

yield return new WaitForSeconds(5.0f);
rigidbody.velocity = Vector3.zero;
rigidbody.angularVelocity = Vector3.zero;
transform.position = footballPos;
canShoot =true;
isKicked  = false;
}


}

1 Answer

I have written a utility class in a game before for handling Bezier Curve. You may try to use the points along the swiping path as control points. Though I did not make use of any physics stuff for calculations, the outcome should satisfy your need.

using UnityEngine;
using System;
using System.Collections;

public class BezierCurve {
public static Vector3 Lerp(Vector3 start, Vector3 end, Vector3[] controlPoints, float time) {
Vector3[] points = new Vector3[controlPoints.Length + 2];
points[0] = start;
points[points.Length - 1] = end;
Array.Copy(controlPoints, 0, points, 1, controlPoints.Length);
return Lerp(points, time);
}

public static Vector3 Lerp(Vector3[] points, float time) {
Vector3 ret = Vector3.zero;

if (points != null && points.Length > 0) {
int n = points.Length;
for (int i = 0; i < n; i++) {
Vector3 cp = points[i];
cp *= BinomialCoefficient(n - 1, i);
cp *= Mathf.Pow(1 - time, n - i - 1);
cp *= Mathf.Pow(time, i);
ret += cp;
}
}

return ret;
}

static int BinomialCoefficient(int n, int k) {
int nCk = 1;

if (k >= 1 && k <= n - 1) {
int numerator = 1;
int denominator = 1;

for (int i = 0; i < k; i++) {
numerator *= (n - i);
denominator *= (k - i);
}

nCk = (int)(numerator / denominator);
}

return nCk;
}
}

• I'm new to the concept of the Bezier curves and forgive me if I say something wrong, but, I believe apart from the start and end points all the other control points does no lie on the swipe/curve. How do I go about this, if whatever I have understood is right? – gameOne Jul 24 '14 at 9:59
• @gameOne So you want to join points up and form a smooth curve, right? – S.C. Jul 24 '14 at 10:10
• yes that's right! – gameOne Jul 24 '14 at 10:14
• After doing a bit searching, I believe this site can help you. – S.C. Jul 24 '14 at 10:15
• will check it out and get back – gameOne Jul 24 '14 at 10:43