"Venkat at Axiom Studios Please Help" 谁知道我将如何在 unity3D 中使用手势 Android 来跟踪 2 指 V 运动
"Venkat at Axiom Studios Please Help" dose anyone know how i would use gestures in unity3D for Android to track a 2 finger V motion
好的,这是我的问题,
我正在尝试弄清楚如何才能注册用户已使用两根手指在屏幕上制作 V(手指起点将是用户用两根手指触摸的位置,然后展开有两个手指同时向上移动以形成 V 形)使用 Unity 3d for android。
我之前从未做过涉及形状的手势,因此非常感谢任何关于如何做到这一点的建议、链接或示例
提前致谢
格雷姆
已编辑:
所以我在等待有人帮助我的时候一直在努力解决这个问题。
这是我到目前为止所得到的,它还没有按照我想要的方式工作,但我不确定我做错了什么,因为我以前从未尝试过用手势做这样的事情.任何帮助将不胜感激
再次感谢
格雷姆
using UnityEngine;
使用 System.Collections;
public class Pinchv : MonoBehaviour {
public Vector2 leftFingerStartPosition;
public Vector2 leftFingerEndPosition;
public Vector2 rightFingerStartPosition;
public Vector2 rightFingerEndPosition;
void Update () {
foreach(Touch touch in Input.touches)
{
if(touch.phase == TouchPhase.Began){
Touch leftFinger = Input.GetTouch (0);
Touch rightFinger = Input.GetTouch (1);
leftFingerStartPosition = Input.GetTouch (0).position;
leftFingerEndPosition = Input.GetTouch(0).position;
rightFingerStartPosition = Input.GetTouch(1).position;
rightFingerEndPosition = Input.GetTouch(1).position;
if(Input.touchCount == 2 && Mathf.Abs(leftFingerEndPosition.x + Screen.width - leftFingerStartPosition.x) > 20 &&
Mathf.Abs(leftFingerEndPosition.y + Screen.height - leftFingerStartPosition.y) > 60){
if(Input.touchCount == 2 && Mathf.Abs(rightFingerEndPosition.x + Screen.width - rightFingerStartPosition.x) > 20 &&
Mathf.Abs(rightFingerEndPosition.y + Screen.height - rightFingerStartPosition.y) > 60){
Debug.Log ("its a v ");
}
}
if(touch.phase == TouchPhase.Ended){
leftFingerStartPosition = Vector2.zero;
leftFingerEndPosition = Vector2.zero;
rightFingerStartPosition = Vector2.zero;
rightFingerEndPosition = Vector2.zero;
}
}
}
}
}
编辑:
所以我听取了你的建议并尝试了一些不同的方法,但不幸的是它根本不起作用。
如果我不能解决这个问题,我很快就要开始拔头发了,哈哈。这是我尝试创建的新代码,但它不起作用。有人可以帮我解决这个问题吗?它已经让我发疯了 3 天了,哈哈。
@Axiom Studios 的 Venkat 你能再次帮助我吗,我将不胜感激:)
耐心等待
格雷姆
using UnityEngine;
使用 System.Collections;
public class Pinchv : MonoBehaviour {
public Vector2 fingerOneStartPosition;
public Vector2 fingerOneEndPosition;
public Vector2 fingerTwoStartPosition;
public Vector2 fingerTwoEndPosition;
void Update () {
foreach(Touch touch in Input.touches)
{
if(touch.phase == TouchPhase.Began){
// Touch leftFinger = Input.GetTouch (0);
// Touch rightFinger = Input.GetTouch (1);
fingerOneStartPosition = Input.GetTouch (0).position;
fingerOneEndPosition = Input.GetTouch(0).position;
fingerTwoStartPosition = Input.GetTouch(1).position;
fingerTwoEndPosition = Input.GetTouch(1).position;
if(Input.touchCount == 2 && Mathf.Abs(fingerOneStartPosition.x - fingerOneEndPosition.x) > 700 &&
Mathf.Abs(fingerOneStartPosition.y - fingerOneEndPosition.y) > 120){
if(Input.touchCount == 2 && Mathf.Abs(fingerTwoStartPosition.x - fingerTwoEndPosition.x) > 700 &&
Mathf.Abs(fingerTwoStartPosition.y - fingerTwoEndPosition.y) > 120){
Debug.Log ("its a v ");
}
}
}
if(touch.phase == TouchPhase.Ended){
fingerOneStartPosition = fingerOneEndPosition;
fingerOneEndPosition = Vector2.zero;
fingerTwoStartPosition = fingerTwoEndPosition;
fingerTwoEndPosition = Vector2.zero;
}
}
}
public void OnGUI(){
GUILayout.Label("Where am i fingerone X : " + fingerOneStartPosition + "end position" + fingerOneEndPosition);
GUILayout.Label("Where am i fingerone X : " + fingerTwoStartPosition + "end position" + fingerTwoEndPosition);
}
}
@Graeme
好的,我想出了一些不完整的代码。这绝不是一段很棒的代码,但它应该让您对如何解决问题有一个相当清晰的认识。
代码确实有效(使用 Moto G 1st Gen,Unity 4.6 测试),但它仍然会给出一些不正确的结果。
我已经评论了 class 中我发现潜在问题的部分,因此您可以将其作为一个不错的起点。
试试看,然后告诉我。肯定有比这个更优雅的解决方案,事实上,几个月前我正在为 Unity 开发一个手势识别库。我应该把它掸掉然后完成它 :P
Unity C#代码
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class DetectVGesture : MonoBehaviour {
//Note : This was tested on a 1st Gen Moto G (1280 x 720 resolution, IIRC)
// and an orthographic size of 5.
//Why this matters :
//The Vector2 minimumDeltas uses Screen units, so resolution matters here
//The float maxDistBetInitPos uses World units, so if the camera's ortho size is larger, this value becomes larger as well
//Therefore, some trial and error in these values will be needed to get it to work right
//TODO : Write some code to take into account screen resolution and camera size / FOV.
//If anyone feels like editing that portion in, please feel free
//The touches used are maintained in these two lists
private List<Touch> firstTouches = new List<Touch>();
private List<Touch> secondTouches = new List<Touch>();
//This is the minimum distance in SCREEN units
//of touch.deltaTouch for a new touch in TouchPhase.Moved to register
public Vector2 minimumDeltas = new Vector2(1, 1);
//This is the maximum distance between the two initial touches
//in WORLD units for the algorithm to work
public float maxDistBetInitPos = 3f;
//These are the minimum and maximum angles between the two
//"ARMS" of the "V" for a V gesture to be recognized
public Vector2 vAnglesMinMax = new Vector2(15, 60);
// Use this for initialization
void Start () {
}
void OnGUI () {
GUI.Label(new Rect(10, 10, 100, 50), "Touches "+Input.touchCount.ToString());
if(Input.touchCount > 0)
GUI.Label(new Rect(110, 10, 100, 50), "Touch1 "+Input.touches[0].position.ToString());
if(Input.touchCount > 1)
GUI.Label(new Rect(210, 10, 100, 50), "Touch2 "+Input.touches[1].position.ToString());
}
// Update is called once per frame
void Update () {
//For this sample, we're only interested in a "V" created with
//2 fingers, so we'l ignore the rest
if(Input.touchCount == 2) {
foreach(Touch touch in Input.touches) {
//The below two lines are to allow for an early
//exit if EITHER of the fingers is stationary.
//Uncomment the lines if you want touches to be registered
//only when BOTH fingers move.
//if(touch.phase == TouchPhase.Stationary)
//return;
//This is the first time TWO fingers are registered,
//so we can use this as our starting point, where the
//touches are closest to each other.
//From here on, I'll refer this to as the BOTTOM of the "V"
if(touch.phase == TouchPhase.Began) {
CheckTouchAndAdd(Input.touches[0], Input.touches[1]);
}
//There was some movement, so let's check what it is
if(touch.phase == TouchPhase.Moved) {
//The movement in this touch is at least as much as we want
//So, we add both the touches, and we move to the next iteration
//Here, I want both the X & Y delta positions to meet my minimum
//delta distance. You can change this to either X or Y.
if(Mathf.Abs(touch.deltaPosition.x) >= minimumDeltas.x &&
Mathf.Abs(touch.deltaPosition.y) >= minimumDeltas.y) {
CheckTouchAndAdd(Input.touches[0], Input.touches[1]);
}
else {
Debug.Log("There was too less of delta!");
}
}
//The touch / touches have ended.
//So let's clear the lists for the next trial
if(touch.phase == TouchPhase.Ended) {
firstTouches.Clear();
secondTouches.Clear();
}
}//Iterate over touches in Input.touches ends
}//Input.touchCount == 2 ends
}
private void CheckTouchAndAdd (Touch touch1, Touch touch2) {
if(!firstTouches.Contains(touch1) && !secondTouches.Contains(touch2)) {
firstTouches.Add(touch1);
secondTouches.Add(touch2);
CheckForV();
}
}
private void CheckForV () {
if(firstTouches.Count < 5 || secondTouches.Count < 5) {
Debug.Log("Not enough touches to perform the check! ");
return;
}
//First, let's check if the two initial touch points
//were relatively close enough to warrant a "V"
//If they're not, we'll have an early exit
Vector3 firstTouchInitPos = Camera.main.ScreenToWorldPoint(firstTouches[0].position);
Vector3 secondTouchInitPos = Camera.main.ScreenToWorldPoint(secondTouches[0].position);
//First we check if the X distance falls within our limit of maximum distance
if(Mathf.Abs(secondTouchInitPos.x - firstTouchInitPos.x) > maxDistBetInitPos) {
Debug.Log (string.Format("The X values were too far apart! Exiting check First {0}," +
"Second {1}, Distance {2}",
new object[] { firstTouchInitPos.x, secondTouchInitPos.x,
Mathf.Abs(secondTouchInitPos.x - firstTouchInitPos.x)} ));
return;
}
//Then we check the same for Y
if(Mathf.Abs(secondTouchInitPos.y - firstTouchInitPos.y) > maxDistBetInitPos) {
Debug.Log (string.Format("The Y values were too far apart! Exiting check First {0}," +
"Second {1}, Distance {2}",
new object[] { firstTouchInitPos.y, secondTouchInitPos.y,
Mathf.Abs(secondTouchInitPos.y - firstTouchInitPos.y)} ));
return;
}
//If we reach this point, both the X & the Y positions are within the maximum distance
//we want. So, they're close enough that we can calculate the average between the two Vectors
//and assume that both these Vectors intersect at the average point. (i.e. the average point
//is the corner at the BOTTOM of the "V")
//Note that there are more elegant ways of doing this. You can always use trignometry to do so
//but for the sake of this example, this should yield fairly good results.
Vector3 bottomCornerPoint = new Vector3( (firstTouchInitPos.x + secondTouchInitPos.x) * 0.5f,
(firstTouchInitPos.y + secondTouchInitPos.y) * 0.5f );
//Now that we have our bottom point, we then calculate the Vector between this common
//bottom point, and the last touch point added to each list. From this point
//I'll refer to these two Vectors as the ARMS of the "V"
Vector3 arm1 = new Vector3( firstTouches[firstTouches.Count - 1].position.x - bottomCornerPoint.x,
firstTouches[firstTouches.Count - 1].position.y - bottomCornerPoint.y );
Vector3 arm2 = new Vector3( secondTouches[secondTouches.Count - 1].position.x - bottomCornerPoint.x,
secondTouches[secondTouches.Count - 1].position.y - bottomCornerPoint.y );
//Now let's calculate the angle between the ARMS of the "V".
//If the angle is too small (< 15 degrees), or too large (> 60 degrees),
//it's not really a "V", so we'll exit
//Note: Vector2.Angle / Vector3.Angle perform a DOT product of the two vectors
//Therefore in certain cases, you're going to get incorrect results.
//TODO : If anyone can, please change the below to use a cross product
//to calculate the angle between the Vectors.
if(Vector3.Angle(arm1, arm2) < vAnglesMinMax.x ||
Vector3.Angle(arm1, arm2) > vAnglesMinMax.y) {
Debug.Log (string.Format("The angle was outside the allowed range! Angle {0}",
new object[] { Vector3.Angle(arm1, arm2) } ));
return;
}
//If we reach this point, everything's great, we have a "V"!
Debug.Log ("There's a V gesture here!");
}
}
代码背后的逻辑
我假设如下
- "V"总是用两根手指开始并拢,然后逐渐远离。
- 当手指彼此远离时,它们在一个轴上的移动方向相同,而在另一个轴上的移动方向相反。 (比如"V"画的跟字母一模一样,那么两根手指都往Y轴正方向移动,一根手指往X轴负方向移动,另一根手指往X轴正方向移动)
- 手指靠得比较近,所以可以取两点的平均值作为"V"两臂的交点。 (请阅读替代机制的代码)
在下面以图形方式表达我的想法的糟糕尝试
好的,这是我的问题,
我正在尝试弄清楚如何才能注册用户已使用两根手指在屏幕上制作 V(手指起点将是用户用两根手指触摸的位置,然后展开有两个手指同时向上移动以形成 V 形)使用 Unity 3d for android。
我之前从未做过涉及形状的手势,因此非常感谢任何关于如何做到这一点的建议、链接或示例
提前致谢 格雷姆
已编辑: 所以我在等待有人帮助我的时候一直在努力解决这个问题。
这是我到目前为止所得到的,它还没有按照我想要的方式工作,但我不确定我做错了什么,因为我以前从未尝试过用手势做这样的事情.任何帮助将不胜感激
再次感谢 格雷姆
using UnityEngine;
使用 System.Collections;
public class Pinchv : MonoBehaviour {
public Vector2 leftFingerStartPosition;
public Vector2 leftFingerEndPosition;
public Vector2 rightFingerStartPosition;
public Vector2 rightFingerEndPosition;
void Update () {
foreach(Touch touch in Input.touches)
{
if(touch.phase == TouchPhase.Began){
Touch leftFinger = Input.GetTouch (0);
Touch rightFinger = Input.GetTouch (1);
leftFingerStartPosition = Input.GetTouch (0).position;
leftFingerEndPosition = Input.GetTouch(0).position;
rightFingerStartPosition = Input.GetTouch(1).position;
rightFingerEndPosition = Input.GetTouch(1).position;
if(Input.touchCount == 2 && Mathf.Abs(leftFingerEndPosition.x + Screen.width - leftFingerStartPosition.x) > 20 &&
Mathf.Abs(leftFingerEndPosition.y + Screen.height - leftFingerStartPosition.y) > 60){
if(Input.touchCount == 2 && Mathf.Abs(rightFingerEndPosition.x + Screen.width - rightFingerStartPosition.x) > 20 &&
Mathf.Abs(rightFingerEndPosition.y + Screen.height - rightFingerStartPosition.y) > 60){
Debug.Log ("its a v ");
}
}
if(touch.phase == TouchPhase.Ended){
leftFingerStartPosition = Vector2.zero;
leftFingerEndPosition = Vector2.zero;
rightFingerStartPosition = Vector2.zero;
rightFingerEndPosition = Vector2.zero;
}
}
}
}
}
编辑:
所以我听取了你的建议并尝试了一些不同的方法,但不幸的是它根本不起作用。
如果我不能解决这个问题,我很快就要开始拔头发了,哈哈。这是我尝试创建的新代码,但它不起作用。有人可以帮我解决这个问题吗?它已经让我发疯了 3 天了,哈哈。
@Axiom Studios 的 Venkat 你能再次帮助我吗,我将不胜感激:)
耐心等待 格雷姆
using UnityEngine;
使用 System.Collections;
public class Pinchv : MonoBehaviour {
public Vector2 fingerOneStartPosition;
public Vector2 fingerOneEndPosition;
public Vector2 fingerTwoStartPosition;
public Vector2 fingerTwoEndPosition;
void Update () {
foreach(Touch touch in Input.touches)
{
if(touch.phase == TouchPhase.Began){
// Touch leftFinger = Input.GetTouch (0);
// Touch rightFinger = Input.GetTouch (1);
fingerOneStartPosition = Input.GetTouch (0).position;
fingerOneEndPosition = Input.GetTouch(0).position;
fingerTwoStartPosition = Input.GetTouch(1).position;
fingerTwoEndPosition = Input.GetTouch(1).position;
if(Input.touchCount == 2 && Mathf.Abs(fingerOneStartPosition.x - fingerOneEndPosition.x) > 700 &&
Mathf.Abs(fingerOneStartPosition.y - fingerOneEndPosition.y) > 120){
if(Input.touchCount == 2 && Mathf.Abs(fingerTwoStartPosition.x - fingerTwoEndPosition.x) > 700 &&
Mathf.Abs(fingerTwoStartPosition.y - fingerTwoEndPosition.y) > 120){
Debug.Log ("its a v ");
}
}
}
if(touch.phase == TouchPhase.Ended){
fingerOneStartPosition = fingerOneEndPosition;
fingerOneEndPosition = Vector2.zero;
fingerTwoStartPosition = fingerTwoEndPosition;
fingerTwoEndPosition = Vector2.zero;
}
}
}
public void OnGUI(){
GUILayout.Label("Where am i fingerone X : " + fingerOneStartPosition + "end position" + fingerOneEndPosition);
GUILayout.Label("Where am i fingerone X : " + fingerTwoStartPosition + "end position" + fingerTwoEndPosition);
}
}
@Graeme
好的,我想出了一些不完整的代码。这绝不是一段很棒的代码,但它应该让您对如何解决问题有一个相当清晰的认识。
代码确实有效(使用 Moto G 1st Gen,Unity 4.6 测试),但它仍然会给出一些不正确的结果。
我已经评论了 class 中我发现潜在问题的部分,因此您可以将其作为一个不错的起点。
试试看,然后告诉我。肯定有比这个更优雅的解决方案,事实上,几个月前我正在为 Unity 开发一个手势识别库。我应该把它掸掉然后完成它 :P
Unity C#代码
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public class DetectVGesture : MonoBehaviour {
//Note : This was tested on a 1st Gen Moto G (1280 x 720 resolution, IIRC)
// and an orthographic size of 5.
//Why this matters :
//The Vector2 minimumDeltas uses Screen units, so resolution matters here
//The float maxDistBetInitPos uses World units, so if the camera's ortho size is larger, this value becomes larger as well
//Therefore, some trial and error in these values will be needed to get it to work right
//TODO : Write some code to take into account screen resolution and camera size / FOV.
//If anyone feels like editing that portion in, please feel free
//The touches used are maintained in these two lists
private List<Touch> firstTouches = new List<Touch>();
private List<Touch> secondTouches = new List<Touch>();
//This is the minimum distance in SCREEN units
//of touch.deltaTouch for a new touch in TouchPhase.Moved to register
public Vector2 minimumDeltas = new Vector2(1, 1);
//This is the maximum distance between the two initial touches
//in WORLD units for the algorithm to work
public float maxDistBetInitPos = 3f;
//These are the minimum and maximum angles between the two
//"ARMS" of the "V" for a V gesture to be recognized
public Vector2 vAnglesMinMax = new Vector2(15, 60);
// Use this for initialization
void Start () {
}
void OnGUI () {
GUI.Label(new Rect(10, 10, 100, 50), "Touches "+Input.touchCount.ToString());
if(Input.touchCount > 0)
GUI.Label(new Rect(110, 10, 100, 50), "Touch1 "+Input.touches[0].position.ToString());
if(Input.touchCount > 1)
GUI.Label(new Rect(210, 10, 100, 50), "Touch2 "+Input.touches[1].position.ToString());
}
// Update is called once per frame
void Update () {
//For this sample, we're only interested in a "V" created with
//2 fingers, so we'l ignore the rest
if(Input.touchCount == 2) {
foreach(Touch touch in Input.touches) {
//The below two lines are to allow for an early
//exit if EITHER of the fingers is stationary.
//Uncomment the lines if you want touches to be registered
//only when BOTH fingers move.
//if(touch.phase == TouchPhase.Stationary)
//return;
//This is the first time TWO fingers are registered,
//so we can use this as our starting point, where the
//touches are closest to each other.
//From here on, I'll refer this to as the BOTTOM of the "V"
if(touch.phase == TouchPhase.Began) {
CheckTouchAndAdd(Input.touches[0], Input.touches[1]);
}
//There was some movement, so let's check what it is
if(touch.phase == TouchPhase.Moved) {
//The movement in this touch is at least as much as we want
//So, we add both the touches, and we move to the next iteration
//Here, I want both the X & Y delta positions to meet my minimum
//delta distance. You can change this to either X or Y.
if(Mathf.Abs(touch.deltaPosition.x) >= minimumDeltas.x &&
Mathf.Abs(touch.deltaPosition.y) >= minimumDeltas.y) {
CheckTouchAndAdd(Input.touches[0], Input.touches[1]);
}
else {
Debug.Log("There was too less of delta!");
}
}
//The touch / touches have ended.
//So let's clear the lists for the next trial
if(touch.phase == TouchPhase.Ended) {
firstTouches.Clear();
secondTouches.Clear();
}
}//Iterate over touches in Input.touches ends
}//Input.touchCount == 2 ends
}
private void CheckTouchAndAdd (Touch touch1, Touch touch2) {
if(!firstTouches.Contains(touch1) && !secondTouches.Contains(touch2)) {
firstTouches.Add(touch1);
secondTouches.Add(touch2);
CheckForV();
}
}
private void CheckForV () {
if(firstTouches.Count < 5 || secondTouches.Count < 5) {
Debug.Log("Not enough touches to perform the check! ");
return;
}
//First, let's check if the two initial touch points
//were relatively close enough to warrant a "V"
//If they're not, we'll have an early exit
Vector3 firstTouchInitPos = Camera.main.ScreenToWorldPoint(firstTouches[0].position);
Vector3 secondTouchInitPos = Camera.main.ScreenToWorldPoint(secondTouches[0].position);
//First we check if the X distance falls within our limit of maximum distance
if(Mathf.Abs(secondTouchInitPos.x - firstTouchInitPos.x) > maxDistBetInitPos) {
Debug.Log (string.Format("The X values were too far apart! Exiting check First {0}," +
"Second {1}, Distance {2}",
new object[] { firstTouchInitPos.x, secondTouchInitPos.x,
Mathf.Abs(secondTouchInitPos.x - firstTouchInitPos.x)} ));
return;
}
//Then we check the same for Y
if(Mathf.Abs(secondTouchInitPos.y - firstTouchInitPos.y) > maxDistBetInitPos) {
Debug.Log (string.Format("The Y values were too far apart! Exiting check First {0}," +
"Second {1}, Distance {2}",
new object[] { firstTouchInitPos.y, secondTouchInitPos.y,
Mathf.Abs(secondTouchInitPos.y - firstTouchInitPos.y)} ));
return;
}
//If we reach this point, both the X & the Y positions are within the maximum distance
//we want. So, they're close enough that we can calculate the average between the two Vectors
//and assume that both these Vectors intersect at the average point. (i.e. the average point
//is the corner at the BOTTOM of the "V")
//Note that there are more elegant ways of doing this. You can always use trignometry to do so
//but for the sake of this example, this should yield fairly good results.
Vector3 bottomCornerPoint = new Vector3( (firstTouchInitPos.x + secondTouchInitPos.x) * 0.5f,
(firstTouchInitPos.y + secondTouchInitPos.y) * 0.5f );
//Now that we have our bottom point, we then calculate the Vector between this common
//bottom point, and the last touch point added to each list. From this point
//I'll refer to these two Vectors as the ARMS of the "V"
Vector3 arm1 = new Vector3( firstTouches[firstTouches.Count - 1].position.x - bottomCornerPoint.x,
firstTouches[firstTouches.Count - 1].position.y - bottomCornerPoint.y );
Vector3 arm2 = new Vector3( secondTouches[secondTouches.Count - 1].position.x - bottomCornerPoint.x,
secondTouches[secondTouches.Count - 1].position.y - bottomCornerPoint.y );
//Now let's calculate the angle between the ARMS of the "V".
//If the angle is too small (< 15 degrees), or too large (> 60 degrees),
//it's not really a "V", so we'll exit
//Note: Vector2.Angle / Vector3.Angle perform a DOT product of the two vectors
//Therefore in certain cases, you're going to get incorrect results.
//TODO : If anyone can, please change the below to use a cross product
//to calculate the angle between the Vectors.
if(Vector3.Angle(arm1, arm2) < vAnglesMinMax.x ||
Vector3.Angle(arm1, arm2) > vAnglesMinMax.y) {
Debug.Log (string.Format("The angle was outside the allowed range! Angle {0}",
new object[] { Vector3.Angle(arm1, arm2) } ));
return;
}
//If we reach this point, everything's great, we have a "V"!
Debug.Log ("There's a V gesture here!");
}
}
代码背后的逻辑
我假设如下
- "V"总是用两根手指开始并拢,然后逐渐远离。
- 当手指彼此远离时,它们在一个轴上的移动方向相同,而在另一个轴上的移动方向相反。 (比如"V"画的跟字母一模一样,那么两根手指都往Y轴正方向移动,一根手指往X轴负方向移动,另一根手指往X轴正方向移动)
- 手指靠得比较近,所以可以取两点的平均值作为"V"两臂的交点。 (请阅读替代机制的代码)
在下面以图形方式表达我的想法的糟糕尝试