Reputation: 23
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).
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. 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. It would be great if anyone could help me out giving me some hints!
Upvotes: 1
Views: 177
Reputation: 808
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. 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.
#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
Upvotes: 2