How to prevent taps in an area on the screen - iphone

I designed an app where the user taps the ball as many times as they can within 30 seconds called iTapping. In the game, the user is able to tap anywhere on the screen for the ball to be tapped. I thought of editing the app so that there would be 'dead spots' where the user would not be able to tap the ball. For example, if the ball is in the upper right-hand corner (lets say in an area of about 100 sq. pts.), and the user taps the ball nothing happens. How would I code this? Please let me know if this is not clear enough.
Here is the .m file:
CGPoint Destination;
CGFloat xamt, yamt;
CGFloat speed21 = 40;
CGFloat xMin21 = 24;
CGFloat xMax21 = 297;
CGFloat yMin21 = 74;
CGFloat yMax21 = 454;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.view];
if ([self Intersecting:location :Ball]) {
number21++;
int xRange = xMax21 - xMin21;
int yRange = yMax21 - yMin21;
int xRand = (arc4random() % xRange) + xMin21;
int yRand = (arc4random() % yRange) + yMin21;
Destination = CGPointMake(xRand, yRand);
xamt = ((Destination.x - Ball.center.x) / speed21);
yamt = ((Destination.y - Ball.center.y) / speed21);
if (number21 == 65) {
[timer invalidate];
}
}
}
-(BOOL)Intersecting:(CGPoint)loctouch:(UIImageView *)enemyimg {
CGFloat x1 = loctouch.x;
CGFloat y1 = loctouch.y;
CGFloat x2 = enemyimg.frame.origin.x;
CGFloat y2 = enemyimg.frame.origin.y;
CGFloat w2 = enemyimg.frame.size.width;
CGFloat h2 = enemyimg.frame.size.height;
if ((x1>x2)&&(x1<x2+w2)&&(y1>y2)&&(y1<y2+h2))
return YES;
else
return NO;
}

I suggest to put the touch management back to the ball itself (see this answer). So whenever a touch is received, you can be sure it's clicking on the ball. All you need to do is to check whether the ball is currently in the dead zone, thus ignore the touch.

Related

iPhone: how to quantize the position of a touched object

Hi all you smart people out there!
I want to create a touch interface to an iOS app, that allows the user to drag an object on the screen around.
However, this object should be restricted to move along the perimeter of a circle, so that if the user is trying to drag the object outside that path, it would stick to the nearest point of that circle.
I have done some iPhone programming, but my math is poor. Please help!
All you have to do is set the frame of the view to follow the equation of a circle (of the form: (x-a)^2 + (y-b)^2 = r^2). Once you detect the touch point, you can restrict the view's frame according to the x or the y coordinate of the touch point (both ways are the same).
#define circleRadius 60.0 // r in the above eqtn
#define circlesCenter_X 160.0 // a in the above eqtn
#define circlesCenter_Y 200.0 // b in the above eqtn
#define circleCenter_y(x) sqrtf(circleRadius*circleRadius - (x-circlesCenter_X)*(x-circlesCenter_X))
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event touchesForView:firstPieceView] anyObject];
CGPoint previousLocation = [touch previousLocationInView:self.view];
CGPoint location = [touch locationInView:self.view];
CGFloat delta_x = previousLocation.x - location.x; // constrained by x in this eg.
CGFloat newX = firstPieceView.center.x-delta_x;
// do limit the view's x-coordinate for possible solutions
if(newX<circlesCenter_X - circleRadius)
newX = circlesCenter_X - circleRadius;
if(newX>circlesCenter_X + circleRadius)
newX = circlesCenter_X + circleRadius;
firstPieceView.center = CGPointMake(newX, circleCenter_y(newX)*(location.y>=circlesCenter_Y?1:-1) + circlesCenter_Y);
}
EDIT- Better solution:
#define circleRadius 60.0 // r in the above eqtn
#define circlesCenter_X 160.0 // a in the above eqtn
#define circlesCenter_Y 200.0 // b in the above eqtn
#define slope(x,y) (y-circlesCenter_Y)/(x-circlesCenter_X)
#define pointOnCircle_X(m) circleRadius/(sqrtf(m*m + 1))
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event touchesForView:self.view] anyObject];
CGPoint location = [touch locationInView:self.view];
CGFloat slope;
CGPoint pointOnCircle;
if(location.x==circlesCenter_X){// case for infinite slope
pointOnCircle.x = circlesCenter_X;
if(location.x<circlesCenter_X){
pointOnCircle.y = circlesCenter_Y - circleRadius;
}else{
pointOnCircle.y = circlesCenter_Y + circleRadius;
}
}else{
slope = slope(location.x,location.y);
if(location.x<circlesCenter_X){
pointOnCircle.x = circlesCenter_X - pointOnCircle_X(slope);
}else{
pointOnCircle.x = circlesCenter_X + pointOnCircle_X(slope);
}
pointOnCircle.y = slope * (pointOnCircle.x - circlesCenter_X) + circlesCenter_Y;
}
firstPieceView.center = pointOnCircle;
}
This can be applied similarly for Android, Blackberry, etc too!

iOS: Single Finger rotation and translation of an image

Currently i am following this Link to perform Single finger rotation on an image and its working fine.But i am wondering after performing rotation, how to perform translation operation if i want to move the image from one postion of screen to any other position.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
// We can look at any touch object since we know we
// have only 1. If there were more than 1 then
// touchesBegan:withEvent: would have failed the recognizer.
UITouch *touch = [touches anyObject];
// A tap can have slight movement, but we're not interested
// in a tap. We want more movement. So if a tap is detected
// fail the recognizer.
if ([self state] == UIGestureRecognizerStatePossible) {
[self setState:UIGestureRecognizerStateBegan];
} else {
[self setState:UIGestureRecognizerStateChanged];
}
// To rotate with one finger, we simulate a second finger.
// The second figure is on the opposite side of the virtual
// circle that represents the rotation gesture.
UIView *view = [self view];
CGPoint center = CGPointMake(CGRectGetMidX([view bounds]), CGRectGetMidY([view bounds]));
CGPoint currentTouchPoint = [touch locationInView:view];
CGPoint previousTouchPoint = [touch previousLocationInView:view];
// use the movement of the touch to decide
// how much to rotate the carousel
CGPoint line2Start = currentTouchPoint;
CGPoint line1Start = previousTouchPoint;
CGPoint line2End = CGPointMake(center.x + (center.x - line2Start.x), center.y + (center.y - line2Start.y));
CGPoint line1End = CGPointMake(center.x + (center.x - line1Start.x), center.y + (center.y - line1Start.y));
//////
// Calculate the angle in radians.
// (From: http://iphonedevelopment.blogspot.com/2009/12/better-two-finger-rotate-gesture.html )
CGFloat a = line1End.x - line1Start.x;
CGFloat b = line1End.y - line1Start.y;
CGFloat c = line2End.x - line2Start.x;
CGFloat d = line2End.y - line2Start.y;
CGFloat line1Slope = (line1End.y - line1Start.y) / (line1End.x - line1Start.x);
CGFloat line2Slope = (line2End.y - line2Start.y) / (line2End.x - line2Start.x);
CGFloat degs = acosf(((a*c) + (b*d)) / ((sqrt(a*a + b*b)) * (sqrt(c*c + d*d))));
CGFloat angleInRadians = (line2Slope > line1Slope) ? degs : -degs;
//////
[self setRotation:angleInRadians];
}
I am not sure that my answer will help you, but I fear that you cannot do "one-touch" rotation and "one-touch" translation at the same time. Indeed, your code always interprets a single touch as for rotation, by "simulating" the presence of a second finger touching the display.
What you could do is trying and differentiate two single-finger gestures so to associate one with rotation and the other with translation. For example, the gesture for translation could be a "long touch" (i.e., you touch and keep touching for some time, then you move the object).
Hope this helps, anyway...

UIView with Png image - ignore touch in transparent areas

I have a PNG of a circle with a transparent background added as a subview. I'm using this type of method to rotate it:
CGPoint location = [touch locationInView:self.view];
if(CGRectContainsPoint(wheelfrom.frame, location))
{
}
the problem is that the transparent area's of the image are registering as part of the UIView. Is there a way to ignore those area's when touched? Is there a better way for me to set up the UIView to recognize the transparency?
thanks!
you can check the rbga pixel colour of the image and see if a (=alpha value) is == 0 (or <= aLowValue)... as suggested by Igor Pchelko...
but in your case it may be easier...
you are using a 2D circle, so just check how the finger click is far from the circle center and see if it's out of its radius... just a Pitagora's theorem application...
EDIT:
ok, so, if you create a new class for your button subclassing UIButton:
in YourButton.h:
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#interface YourButton : UIButton {
}
#end
in YourButton.m just add this code:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
CGPoint touchPoint = [touch locationInView:self];
NSLog(#"Touch x : %f y : %f", touchPoint.x, touchPoint.y);
float circleRadius = self.frame.size.height / 2; // considering a circle inscricted in a quadRect (width = height)
float deltaTouchOnCenterX = touchPoint.x - circleRadius;
float deltaTouchOnCenterY = touchPoint.y - circleRadius;
float touchDistanceFromCenter = sqrt((deltaTouchOnCenterX * deltaTouchOnCenterX) + (deltaTouchOnCenterY * deltaTouchOnCenterY) );
// or: float touchDistanceFromCenter = hypot(deltaTouchOnCenterX,deltaTouchOnCenterY);
NSLog(#"sqrt_val: %f", touchDistanceFromCenter);
NSLog(#"Touch on center x : %f y : %f", deltaTouchOnCenterX, deltaTouchOnCenterY);
if (touchDistanceFromCenter <= circleRadius) {
// your code here
NSLog(#"___ OK: You are inside the circle!!");
}
}
Swift solution:
class RadiusTouchButton: UIButton {
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
let radius = frame.size * 0.5
let delta = point - CGPoint(x: radius.height, y: radius.width)
return hypot(delta.x, delta.y) <= radius.height
}
}

Calculate angle for rotation in Pie Chart

I want to rotate the image around its center point.The problem i am facing is i need to get the angle to calculate in touch moved event (i dont want to use multi touch).I am current using the below code
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
NSArray *allTouches = [touches allObjects];
gestureStartPoint = gestureMovedPoint;//i am getting the gestureStartPoint on touch began event
gestureMovedPoint = [[allTouches objectAtIndex:0] locationInView:[self superview]];
NSLog(#"gestureMovedPoint = %#",NSStringFromCGPoint(gestureMovedPoint));
}
CGFloat previousAngle = [self angleBetweenPoints:gestureStartPoint second11:gestureMovedPoint]; // atan2(gestureMovedPoint.y - gestureStartPoint.y, gestureMovedPoint.x - gestureStartPoint.x) * 180 / M_PI;
CGFloat currentAngle =atan2(self.transform.b, self.transform.a);//atan2(gestureMovedPoint.y - gestureStartPoint.y,gestureMovedPoint.x - gestureStartPoint.x) * 180 / M_PI;
CGFloat angleToRotate = currentAngle - previousAngle;
float xpoint = (((atan2((gestureMovedPoint.x - gestureStartPoint.x) , (gestureMovedPoint.y - gestureStartPoint.y)))*180)/M_PI);
CGAffineTransform transform = CGAffineTransformMakeRotation(angleToRotate-100);
self.transform = transform;
Kindly help me find the solution as i am stuck here and need to complete this application very soon as there is a dead line.
Thanks in advance
Glad I remember triginometry
-(void)degreesToRotateObjectWithPosition:(CGPoint)objPos andTouchPoint:(CGPoint)touchPoint{
float dX = touchPoint.x-objPos.x; // distance along X
float dY = touchPoint.y-objPos.y; // distance along Y
float radians = atan2(dY, dX); // tan = opp / adj
//Now we have to convert radians to degrees:
float degrees = radians*M_PI/360;
return degrees;
}
Once you have your nice method, just do this in the touch event method. (I forgot what it's called...)
CGAffineTransform current = view.transform;
[view setTransform:CGAffineTransformRotate(current, [self degreesTorotateObjectWithPosition:view.frame.origin andTouchPoint:[touch locationInView:parentView]]
//Note: parentView = The view that your object to rotate is sitting in.
This is pretty much all the code that you'll need.The math is right, but I'm not sure about the setTransform stuff. I'm at school writing this in a browser. You should be able to figure it out from here.
Good luck,
Aurum Aquila
Have to think at this. But I will prefer rotating the view with two touches. It will be much simpler.
I did struggle a bit with how to get a touch driven rotation, even more so because I want 100% understanding of the code I am using. So I ended up, after many failed attempts, with this:
- (CGFloat) pointToAngleFromCenter: (CGPoint) point {
// transform point to a self.center'ed origin based coordinate system
point.x = point.x - self.center.x ;
// ditto for y, but compensate for y going downwards to y going upwards
point.y = self.center.y - point.y ;
return ::atan2(point.y, point.x) ;
}
If anyone has a better name for this method, I'm all ears.
What it does is that it takes a point in parent view coordinates, remaps it relative to the center of the view (which is in parent view coordinate), and computes the angle between this remapped point and the axis [0X]. To do so, it normalizes y to the normal mathematical coordinates (y goes up when its value increases, not down), hence self.center.y - point.y and not the opposite.
Finally, in touchesMoved:
- (void) touchesMoved: (NSSet *) touches withEvent: (UIEvent *) event {
UITouch * touch = [touches anyObject] ;
CGFloat currA = [self pointToAngleFromCenter:[touch locationInView:self.superview]] ;
CGFloat prevA = [self pointToAngleFromCenter:[touch previousLocationInView:self.superview]] ;
// the current value of the rotation angle
CGFloat tranA = ::atan2(self.transform.b, self.transform.a) ;
// the angle difference between last touch and the current touch
CGFloat diffA = currA - prevA ;
// the new angle resulting from applying the difference
CGFloat angle = tranA - diffA ;
CGAffineTransform t = ::CGAffineTransformMakeRotation(angle) ;
self.transform = t ;
[self setNeedsDisplay] ;
}

Rotate UIView using UITouch

I have a question on how I should approach rotating a UIView with touch based events.
Quite simply, I want to rotate a UIView around an anchorpoint, depending on where I touch on and off within that view. Imagine a volume knob on a hifi, which you turn with one finger.
I've built a rotation method using CAKeyframeAnimation which carries out a transform.rotation.z, however what I am not sure is if (a) I should use that in conjunction with touch methods, and (b) how I can get the coordinate/angle of the touch in relation to the underlying UIView, and subsequently turn it to point to the touch.
I hope I am making senseā€¦ Can anyone make any suggestions?
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint newLocationPoint = [[touches anyObject] locationInView:self.superview];
int x = self.superview.center.x;
int y = self.superview.center.y;
float dx = newLocationPoint.x - x;
float dy = newLocationPoint.y - y;
double angle = atan2(-dx,dy);
self.layer.position = self.superview.center;
self.layer.transform = CATransform3DMakeRotation(angle, 0, 0, 1);
NSLog(#"%f,%f ", dx,dy);
}
Put this in your UIView Subclass and Voila!
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint Location = [[touches anyObject] locationInView:self];
int x = ImageView.center.x;
int y = ImageView.center.y;
float dx = Location.x - x;
float dy = Location.y - y;
double a = atan2(-dx,dy);
ImageView.layer.position = diagramImageView.center;
ImageView.layer.transform = CATransform3DMakeRotation(a, 0, 0, 1);
}