简体   繁体   English

使按钮在屏幕上移动并记录手指手势的准确性

[英]Make button move around the screen and record finger gesture accuracy

I am trying to make an app in which the user has to follow a dot dragging his finger across the screen. 我正在尝试制作一个应用程序,其中用户必须跟随点在屏幕上拖动手指。 Each time the dot is reached by the user, it moves to the next point (there are 5 equidistant points in total, with specific coordinates). 每次用户到达该点时,它就会移动到下一个点(总共有5个等距点,并带有特定坐标)。

The length of the path traced by the finger is recorded between every two dots, stored into and array and the value is eventually averaged, to assess the accuracy of the user (comparing his own path to the ideal, shortest one). 手指跟踪的路径的长度记录在每两个点之间,存储到数组中并最终对其求平均值,以评估用户的准确性(将自己的路径与理想的最短路径进行比较)。

-(IBAction)button1Clicked:(UIButton *)sender {
    CGRect buttonFrame = sender.frame;

    int dotX = arc4random() % (int)(1000 - buttonFrame.size.width);
    int dotY = arc4random() % (int)(self.view.frame.size.height - buttonFrame.size.height);

    buttonFrame.origin.x = dotX;
    buttonFrame.origin.y = dotY;
    [sender setFrame:buttonFrame];
    NSLog(@"x = %f, y = %f", self.button1.frame.origin.x, self.button1.frame.origin.y);
}

I've tried to add the buttons programmatically using several buttons stored in an array, but also directly from the storyboard, and I still haven't figured out which would be the best way for the app to do what it's meant to. 我尝试使用存储在数组中的多个按钮以编程方式添加按钮,但也直接从情节提要中添加按钮,但我仍然没有弄清楚哪种方法是应用程序执行其意图的最佳方法。

My coding knowledge being still very poor, I've only managed to make an app with a dot shaped button that has to be clicked (touch down inside) in order for it to move around the screen, and when the user presses it it moves to a random point on the screen of my iPad. 我的编码知识仍然很贫乏,我只设法制作了一个带有点形按钮的应用程序,该按钮必须单击(在内部向下触摸)才能在屏幕上移动,而当用户按下它时,它就会移动到我iPad屏幕上的随机位置。 Instead would like the button to move around a specific path, a set number of times until the code stops running and the results are averaged (I will probably need to put some code inside a "for" loop for that), and the gesture should be touch drag inside rather than touch down. 而是希望按钮在特定路径上移动一定的次数,直到代码停止运行并将结果平均为止(为此,我可能需要将一些代码放入“ for”循环中),并且手势应该触摸内部而不是向下触摸。 It would be great if anyone could help me out giving me some hints! 如果有人可以帮助我给我一些提示,那就太好了!

I think you should only need to add one button. 我认为您只需要添加一个按钮。 Create an array of NSMutableDictionary, which contains values for each point that you want the user to navigate to, this includes, x and y coordinates, minimum distance between this coordinate and the last coordinate, and the actual distance travelled between this coordinate and the last coordinate. 创建一个NSMutableDictionary数组,其中包含要用户导航到的每个点的值,包括x和y坐标,此坐标与最后一个坐标之间的最小距离以及此坐标与最后一个坐标之间的实际距离坐标。 The following setup should work for you but it is untested: 以下设置应为您工作,但未经测试:

Storing your coordinate sets: The way you store your coordinate sets depends on how many sets of coordinates you have, and how many coordinates are in each. 存储坐标集:存储坐标集的方式取决于您拥有多少组坐标,以及每组中有多少坐标。 If you only have a few sets of coordinates, you could get away with writing them in the code like I have here. 如果只有几组坐标,则可以像在这里一样用代码编写它们。 If you have a lot of coordinate sets, you will most likely want to create a file which you will store in your bundle, and access it where needed, there are many SO questions related to this process already. 如果您有很多坐标集,那么您很可能希望创建一个文件,并将其存储在包中,并在需要时访问它,已经有很多与该过程相关的SO问题。

#import "ViewController.h"

@interface ViewController (){
    NSMutableArray *values;
    NSInteger buttonCount;
    __weak IBOutlet UIButton *button;
    BOOL hasStarted;
}

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    UIGestureRecognizer *gestureRecognizer = [[UIGestureRecognizer alloc] init];
    [gestureRecognizer setEnabled:YES];
    [gestureRecognizer setDelegate:self];
    [self.view addGestureRecognizer:gestureRecognizer];

    button.hidden = true;

    buttonCount = 0;
    values = [[NSMutableArray alloc]init];
    [self generateValuesArrayWithCoordiantes];
}

-(void)generateValuesArrayWithCoordiantes{
    // for every number between 0 and 20, create an nsdictionary with your desired values for x and y
    CGPoint lastCoord = CGPointZero;
    // you need to have your set of coordinates stored somewhere, so that they can put into the button values dictionary
    // here is an array of dictionary, with an x and y number for each array value, you will require 20 rows, one for each set of coords

    NSArray *coords = @[@{@"x":@317, @"y":@100},
                        @{@"x":@200, @"y":@250},
                        @{@"x":@120, @"y":@400},
                        @{@"x":@80, @"y":@380}];

    for (int i = 0; i<20; i++) {
        NSMutableDictionary *buttonValues = [[NSMutableDictionary alloc]init];

        // get the required coords from your coords array
        NSDictionary *currentCoord = [coords objectAtIndex:i];
        [buttonValues setValue:[currentCoord valueForKey:@"x"] forKey:@"x"];
        [buttonValues setValue:[currentCoord valueForKey:@"y"] forKey:@"y"];

        // set the distance travelled to 0. this will be updated as your view detects touches moved
        [buttonValues setValue:[NSNumber numberWithInt:0] forKey:@"distanceTravelled"];

        if (i>0) {
            // calculate the minimum distance required to get from this point to the previous point. not required for the first point
            CGFloat minDistance = [self distanceBetween:CGPointMake([[currentCoord valueForKey:@"x"]floatValue], [[currentCoord valueForKey:@"y"]floatValue]) and:lastCoord];
            [buttonValues setValue:[NSNumber numberWithFloat:minDistance] forKey:@"minDistance"];
        }
        lastCoord = CGPointMake([[currentCoord valueForKey:@"x"]floatValue], [[currentCoord valueForKey:@"y"]floatValue]);
        [values addObject:buttonValues];
    }
}


-(IBAction)button1Clicked:(UIButton *)sender {
    if (!hasStarted) {
        NSLog(@"It Has Begun");
        hasStarted = true;
    }
    buttonCount = buttonCount + 1;
    if (buttonCount == 20){
        // The button has been clicked 20 times, compare the minDistance of the dictionaries, to the actualDistance of the dictionaries
        NSLog(@"We are done");
        return;
    }
    //get the last frame of the button
    CGRect lastFrame = sender.frame;

    NSMutableDictionary *nextButtonValues = [values objectAtIndex:buttonCount];

    CGRect nextFrame = CGRectMake([[nextButtonValues valueForKey:@"x"]floatValue], [[nextButtonValues valueForKey:@"y"]floatValue], lastFrame.size.width, lastFrame.size.height);

    [sender setFrame:nextFrame];
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    button.hidden = false;
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
    // get this and last touch location and the distance moved between them
    UITouch *touch = [touches anyObject];
    CGPoint touchLocation = [touch locationInView:self.view];
    CGPoint lastLocation = [touch previousLocationInView:self.view];
    CGFloat distanceMoved = [self distanceBetween:touchLocation and:lastLocation];

    //NSLog(@"MOVED %.2f", distanceMoved);

    // get the current course from values, and update the distanceTravelled to include the distance moved
    NSMutableDictionary *currentCourse = [values objectAtIndex:buttonCount];
    CGFloat courseTravelled = [[currentCourse valueForKey:@"distanceTravelled"]floatValue];
    [currentCourse setValue:[NSNumber numberWithFloat:courseTravelled + distanceMoved] forKey:@"distanceTravelled"];

    // detect if the touch is inside the button frame
    for (UITouch *t in touches) {
        CGPoint touchPoint = [t locationInView:self.view];

        CGPoint testPoint = [self.view convertPoint:touchPoint toView:button];
        if ([button pointInside:testPoint withEvent:event]) {
            [self button1Clicked:button];
            return;
        }
    }
}

-(CGFloat)distanceBetween:(CGPoint)point1 and:(CGPoint)point2{
    CGFloat xDist = (point1.x - point2.x);
    CGFloat yDist = (point1.y - point2.y);
    return sqrt((xDist * xDist) + (yDist * yDist));
}

@end

When the view detects the initial touch, the button will be unhidden, and the game will begin 当视图检测到初始触摸时,该按钮将被隐藏,游戏将开始

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM