0

我试图找出根据用户在屏幕上的触摸来确定移动方向的最佳方法。所以说我得到一个 2d 位置 23x 和 320y,然后我需要返回以下 LEFT、RIGHT、UP、DOWN 之一。

目前我使用的代码不是很可靠,我想知道是否有人可以建议我更好的方法。

谢谢

if (at_position.x <= width*2/3 && at_position.x >= width*1/3 && at_position.y <= this->screenHeight*2/3)
{
    return UP;

}
else if (at_position.x <= width*2/3 && at_position.x >= width*1/3 && at_position.y >= this->screenHeight*1/3)
{
    return DOWN;      
}
else if (at_position.x <= this->screenWidth*2/3 && at_position.y >= this->screenHeight*1/3 && at_position.y <= this->screenHeight*2/3)
{
   return LEFT;         
}
else if (at_position.x <= this->screenWidth*1/3 && at_position.y >= this->screenHeight*1/3 && at_position.y <= this->screenHeight*2/3)
{
   return RIGHT;        
}
4

4 回答 4

2

您可以根据旧位置和新位置计算矢量:newX - oldX, newY - oldY,这可以用作角度,用于确定方向只需将范围 0-360(角度)转换为 0-3(枚举值)。对于更精确的方法,在根据新位置确定方向之前进行短暂的延迟(0.1 秒)

用于将矢量转换为 [0 到 2*PI] 范围内的角度,请使用

C#:
float angle = Math.Atan2(newY - oldY, newX - oldX) + Math.PI;

将其转换为度数

C#:
angle = angle * (180 / Math.PI);

将此转换为枚举值

C#:
int e = (int)angle / 90; //will give 0 for 0-90, 1 for 90-180, 2 for 180-270...

那么你的枚举可能看起来像这样

C#:
enum dir {
    R = 0, D = 1, L = 2, U = 3 }
于 2012-07-20T07:58:57.033 回答
1

我建议计算方向矢量的角度并根据它提出建议

vec2 dir = ...
float angle = atan2f(dir.y, dir.x) + M_PI; //angle is in range [0, 2*PI] now
if (angle > 7 * M_PI / 4 && angle <= M_PI / 4) {//right}
else if (angle > M_PI / 4 && angle <= 3 * M_PI / 4) {//top}
//and so on

要计算dir你需要点。一个是 - 您当前的触摸位置。第二个可以是prev touch position位置或某个固定点(例如屏幕的中心)

如果您有以下几点:

vec2 dir = currentTouchPoint - prevPoint; //or origin
于 2012-07-20T07:53:10.557 回答
1

我不会像其他人建议的那样为复杂的解决方案而烦恼(比如计算一个向量到用户点击的点)。你不是在解决一个困难的数学问题,你只需要检查点是否在某个区域内。所以不要把事情过度复杂化。

//lets you check if point a is between the boundaies, which in your case are either 
//X or Y coordinates. 
bool isBetween( int a, int firstBoundary, int secondBoundary)
{
   return (a >= firstBoundary && a <= secondBoundary);
}

if (isBetween(at_position.x, width*1/3, width*2/3))
{
    if(at_position.y <= this->screenHeight*2/3)
        return UP;
    else if(at_position.y >= this->screenHeight*1/3)
        return DOWN;      
}
else if (isBetween(at_position.y, this->screenHeight*1/3, this->screenHeight*2/3))
{
    if(at_position.x <= this->screenWidth*2/3)
       return LEFT;         
    else if(at_position.y <= this->screenHeight*2/3)
       return RIGHT;
}

当然,这仍然不是最好看的代码,但考虑到它需要做的事情,我想这还不是最差的。

于 2012-07-20T08:05:55.350 回答
1

最简单的方法:

声明这个结构。

typedef enum {
    kDirecLeft = 1,
    kDirecRight,
    kDirecUp,
    kDirecDown,
}SwipDirection;

使用这两个成员变量:

CGPoint             mSwipTouch1;
CGPoint             mSwipTouch2;

在 TouchesBegan 中初始化 mSwipTouch1,在 TouchesEnded 中初始化 mSwipTouch2。

-(void)checkForDirection
{
    SwipDirection direction;

    bool isValidSwip = false;

    float swipXLength = ABS(mSwipTouch1.x-mSwipTouch2.x) ;
    float swipYLength = ABS(mSwipTouch1.y-mSwipTouch2.y) ;

    float swipDistance ; 

    if(swipXLength > swipYLength)  // Left/Right swip
    {
        swipDistance = swipXLength;

        if(swipXLength > MIN_SWIP_LENGHT)
        {
            if(mSwipTouch1.x > mSwipTouch2.x) //Left swip
            {
                DEBUG_LOG("Left swip\n") ;
                direction = kDirecLeft ; 
                isValidSwip = true;
            }
            else
            {
                DEBUG_LOG("Right swip\n") ;
                direction = kDirecRight ;
                isValidSwip = true;
            }
        }
    }
    else  // Up/Down Swip
    {
        swipDistance = swipYLength;

        if(swipYLength > MIN_SWIP_LENGHT)
        {
            if(mSwipTouch1.y > mSwipTouch2.y) //Left swip
            {
                DEBUG_LOG("Down swip\n") ;
                direction = kDirecDown ;
                isValidSwip = true;
            }
            else
            {
                DEBUG_LOG("Up swip\n") ;
                direction = kDirecUp ;
                isValidSwip = true;
            }
        }
    }

    if(isValidSwip)
        [self process:direction];
}

-(void)process:(SwipDirection)direc
{
    switch(direc)
    {
      case kDirecLeft:
           [self moveLeft];
            break;
        case kDirecRight:
            [self moveRight];
            break;

        case kDirecDown:
            [self moveDown];
            break;

        case kDirecUp:
            [self moveUp];
            break;
        default:
            break;    
    }
}
于 2012-07-20T08:14:35.620 回答