Moving Ball with pan - iphone

I'm using pan gesture and after it moves I'm trying to get it to move at the angle that the touch happen. I though to get the point of the touch when the pan happened and then when the user lifted their finger. After that calculate the angle of the points and use that to move. I'm not sure what I'm doing wrong here.
-(void) dragging:(UIPanGestureRecognizer *)p{
UIView *v = p.view;
CGPoint velocity;
if(p.state == UIGestureRecognizerStateBegan){
self.origC = v.center;
self.pointIn = [p locationInView:[UIApplication sharedApplication].keyWindow];
//NSLog(#"%f",self.pointIn.x);
//pointInWindow = CGPointMake(pointIn.x, pointIn.y);
}
//NSLog(#"%f,%f orig %f, %f",pointInWindow.x, pointInWindow.y,self.origC.x,self.origC.y);
//velocity = [p velocityInView:v.superview];
//NSLog(#"x=%f",velocity.x);
//NSLog(#"y=%f",velocity.y);
[UIView animateWithDuration:1 delay:0 options:UIViewAnimationCurveEaseInOut animations:^{
CGPoint delta = [p translationInView:v.superview];
CGPoint c = self.origC;
c.x += delta.x;
c.y += delta.y;
v.center = c;
}completion:nil];
if(p.state == UIGestureRecognizerStateEnded){
CGPoint lastPoint = [p locationInView:[UIApplication sharedApplication].keyWindow];
NSLog(#"orig %f , last %f",self.pointIn.x,lastPoint.x);
self.lateC = v.center;
CGFloat deltaX = self.pointIn.x - lastPoint.x;
CGFloat deltaY = self.pointIn.y - lastPoint.y;
double angle = atan(deltaX/deltaY) * 180/M_PI;
if(angle < 0)
angle += 360;
//NSLog(#"%f",angle);
self.addy = angle;
self.addx = angle;
}
}
This is in my ViewController :
-(void) animateBalls:(NSTimer*) time{
for(Ball *balls in self.view.subviews){
[UIView beginAnimations:nil context:nil];
//[UIView setAnimationRepeatAutoreverses:NO];
CGFloat x;
CGFloat y;
for(Ball *subBalls in self.view.subviews){
if(balls != subBalls)
if((CGRectIntersectsRect([balls frame], [subBalls frame]))){
[subBalls changeDirectionX];
[subBalls changeDirectionY];
}
}
CGPoint point = balls.center;
if(point.x + 25 > self.view.bounds.size.width)
[balls changeDirectionX];
if(point.x - 25 < 0)
[balls changeDirectionX];
if(point.y + 25 > self.view.bounds.size.height)
[balls changeDirectionY];
if(point.y - 25 < 0)
[balls changeDirectionY];
if(balls.directionX == 1){
x = point.x + (2 * cos(balls.addx));
}
else{
x = point.x - (2 * cos(balls.addx));
//balls.addx;
}
if(balls.directionY == 1){
y = point.y + (2 * sin(balls.addx));
}
else
y = point.y - (2 * sin(balls.addx));
//balls.addy;
//CGFloat x = (CGFloat) random()/(CGFloat) RAND_MAX * self.view.bounds.size.width;
//CGFloat y = (CGFloat) random()/(CGFloat) RAND_MAX * self.view.bounds.size.height;
CGPoint squarePostion = CGPointMake(x, y);
balls.center = squarePostion;
[UIView commitAnimations];
//[self.view setNeedsDisplay];
}
}

Related

Make UIPanGestureRecognizer stretch when pulling past certain threshold

I'm trying to implement something similar to how Mac/iOS web pages are implemented, where if you pull past a certain threshold, the main view becomes "stretchy" and moves based on the velocity of the pull.
The difference, though, is I'm trying to do this horizontally for UITableViewCells with a UIPanGestureRecognizer.
I've got a handlePan method:
- (void)handlePan:(UIPanGestureRecognizer *)recognizer
{
[recognizer setMaximumNumberOfTouches:1];
CGPoint velocity = [recognizer velocityInView:self];
int panDelta = ([recognizer locationInView:self].x - [recognizer locationInView:self.superview].x);
if (recognizer.state == UIGestureRecognizerStateBegan) {
_originalCenter = self.center;
}
if (recognizer.state == UIGestureRecognizerStateChanged) {
CGPoint translation = [recognizer translationInView:self];
float xVal = 0;
if (panDelta <= 38) {
xVal = _originalCenter.x + translation.x;
} /*else {
// this is where I struggle.
xVal = _originalCenter.x;
}*/
self.center = CGPointMake(xVal, _originalCenter.y);
}
if (recognizer.state == UIGestureRecognizerStateEnded) {
CGRect newFrame;
int xOffset = 0;
newFrame = CGRectMake(xOffset, self.frame.origin.y,
self.bounds.size.width, self.bounds.size.height);
[UIView animateWithDuration:0.2 animations:^{
self.frame = newFrame;
}];
}
}
I don't have any specific algorithm to create the "stretchiness"; all I'm trying to do is make it so the sliding doesn't go as wide as the user's interaction is, and is fluid.
Ideas?
I think you are looking for a simple function with a horizontal asymptote indicating a maximum offset:
// this is where I struggle.
CGFloat maxOffset = 50.0; // change as you like
CGFloat elementWidth = ?; // fill in the width of your view animated, eg: self.frame.size.width
CGFloat absPannedOffset = fabsf(translation.x);
CGFloat rico = powf(elementWidth, 2) / maxOffset;
CGFloat absOffset = (((- 1 / rico) * powf(absPannedOffset - elementWidth, 2)) + maxOffset);
if (pannedOffset < 0) {
xVal = -absOffset;
} else {
xVal = absOffset;
}

Check Rotation in iphone SDk

In my app, i used SMRotatory wheel for rotation. It is working fine as rotation regarding.
But i want to detect that rotation is clockwise or anti-clockwise??
//My code is as follow:
- (BOOL)continueTrackingWithTouch:(UITouch*)touch withEvent:(UIEvent*)event
{
CGFloat radians = atan2f(container.transform.b, container.transform.a);
// NSLog(#"rad is %f", radians);
CGPoint pt = [touch locationInView:self];
float dx = pt.x - container.center.x;
float dy = pt.y - container.center.y;
float ang = atan2(dy,dx);
float angleDifference = deltaAngle - ang;
// NSLog(#"%f",angleDifference);
if (angleDifference>=0) {
//NSLog(#"positive");
[[NSUserDefaults standardUserDefaults]setValue:#"positive" forKey:#"CheckValue"];
}
else
{
// NSLog(#"negative");
[[NSUserDefaults standardUserDefaults]setValue:#"negative" forKey:#"CheckValue"];
}
container.transform = CGAffineTransformRotate(startTransform, -angleDifference);
bg.transform=CGAffineTransformRotate(startTransform, -angleDifference);
return YES;
}
Try something like this:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint currentTouch1=[touch locationInView:self.superview];
CGPoint currentTouch2=[touch previousLocationInView:self.superview];
CGFloat x = currentTouch2.x - currentTouch1.x;
CGFloat y = currentTouch2.y - currentTouch1.y;
CGFloat dist = sqrtf(x*x + y*y);
CGFloat cx = currentTouch1.x - self.superview.bounds.size.width / 2;
CGFloat cy = currentTouch2.y - self.superview.bounds.size.height / 2;
CGFloat cdist = sqrtf(cx*cx + cy*cy);
CGFloat angle = atan2(dist, cdist);
//NSLog(#"%f",angle);
CGFloat radians = atan2f(super.transform.b, super.transform.a);
mDegrees = radians * (180 / M_PI);
if (mDegrees < 0.0)
{
mDegrees+=360;
}
NSLog(#"Angle is = %f",angle); //positive is clockwise, negative is counterclockwise
CGAffineTransform transform = CGAffineTransformRotate(self.transform, angle);
self.transform = transform;
touch1 = currentTouch1;
touch2 = currentTouch2;
}

Rotating an Image flips suddenly

I am using the following code to rotate an image by starting gesture on left and right arrows.While moving arrows along the rotation.
- (void)handleRotation:(UIPanGestureRecognizer *)recognizer
{
UIView* cview = self.superview.superview;
UIView* lView = self.superview;
CGPoint origin = [lView convertPoint: self.center toView: cview];
if (recognizer.state == UIGestureRecognizerStateBegan)
{
if (recognizer.view == leftImage)
{
initialP= [self convertPoint: leftImage.center toView: cview];
}
else
{
initialP = [self convertPoint: rightImage.center toView: cview];
}
}
CGPoint currentP = [recognizer translationInView:cview];
currentP.x += initialP.x;
currentP.y += initialP.y;
CGFloat angle = 0;
CGFloat a = initialP.x - origin.x;
CGFloat b = initialP.y - origin.y;
CGFloat c = currentP.x - origin.x;
CGFloat d = currentP.y - origin.y;
angle = acosf( ((a*c) + (b*d)) / ((sqrt(a*a + b*b)) * (sqrt(c*c + d*d))));
angle += lastReleasedAngle;
if (currentP.y < (currentP.x *(initialP.y - origin.y) + (initialP.x * origin.y - initialP.y * origin.x)) / (initialP.x - origin.x))
{
angle = -angle;
}
if (recognizer.view == leftImage)
{
angle = -angle;
}
if(recognizer.state == UIGestureRecognizerStateBegan ||
recognizer.state == UIGestureRecognizerStateChanged || recognizer.state == UIGestureRecognizerStateEnded)
{
[self setTransform: CGAffineTransformMakeRotation(angle)];
}
if (recognizer.state == UIGestureRecognizerStateEnded)
{
lastReleasedAngle = angle;
}
First time when starts rotating it works perfectly fine.Say,right arrow is at 0 degree now..when i start rotation from here and release here it works fine.When i release the rotation anywhere else then tries to rotate ,image starts flipping exact to 180 degree after moving 180 degree.
check out the example over here of rotation with left ,right and depend on position wise download from here

Bounds checking for the center of a UIView while dragging it around

I have UIView elements that i want to drag around the screen. But i want that no-matter what, their center should be always inside the bounds of their superview.
I added to them an UIPanGestureRecognizer and i making the bounds checking as follows:
-(void) dragInProgress : (UIPanGestureRecognizer *) recognizer
{
if ([self.delegate hallElement:self shouldMove:recognizer])
{
CGPoint translation = [recognizer translationInView:self.view.superview];
CGPoint currentCenter = self.view.center;
CGFloat maxX = self.view.superview.bounds.size.width;
if (currentCenter.x + translation.x < 0 )
{
translation.x = (0 - currentCenter.x);
}
if (currentCenter.x + translation.x >= maxX )
{
translation.x = (maxX - currentCenter.x - 1);
}
CGFloat maxY = self.view.superview.bounds.size.height;
if (currentCenter.y + translation.y < 0 )
{
translation.y = (0 - currentCenter.y);
}
if (currentCenter.y + translation.y >= maxY )
{
translation.y = (maxY - currentCenter.y - 1);
}
[recognizer setTranslation:translation inView:self.view.superview];
CGPoint translationInViewCoordiateSystem = [recognizer translationInView:self.view];
self.view.transform = CGAffineTransformTranslate(self.view.transform, translationInViewCoordiateSystem.x , translationInViewCoordiateSystem.y );
[recognizer setTranslation:CGPointZero inView:self.view];
}
}
But this bound checking is not working at the best case, and usually results in weird behavior.
How can i ensure that the center will remain within the bounds of the superview?
Your centre isn't always going to be within the actual bounds -- it can go over by 1 pixel in the maximum X and Y directions. Not sure if that's causing your problem, but this code should fix that bounds issue:
CGPoint translation = [recognizer translationInView:self.view.superview];
CGPoint currentCenter = self.view.center;
CGFloat maxX = self.view.superview.bounds.size.width;
if (currentCenter.x + translation.x < 0 )
{
translation.x = (0 - currentCenter.x);
}
if (currentCenter.x + translation.x >= maxX ) // A CHANGE HERE
{
translation.x = (maxX - currentCenter.x - 1); // A CHANGE HERE
}
CGFloat maxY = self.view.superview.bounds.size.height;
if (currentCenter.y + translation.y < 0 )
{
translation.y = (0 - currentCenter.y);
}
if (currentCenter.y + translation.y >= maxY ) // A CHANGE HERE
{
translation.y = (maxY - currentCenter.y - 1); // A CHANGE HERE
}
I figured out what was the problem:
The transform translation is not changing the center of the view, so the bounds checking for the center is never really efficient because the center always stay the same even though the view is actually traveling across the screen.
So the solution will be to replace the following lines:
[recognizer setTranslation:translation inView:self.view.superview];
CGPoint translationInViewCoordiateSystem = [recognizer translationInView:self.view];
self.view.transform = CGAffineTransformTranslate(self.view.transform, translationInViewCoordiateSystem.x , translationInViewCoordiateSystem.y );
[recognizer setTranslation:CGPointZero inView:self.view];
With:
currentCenter.x += translation.x;
currentCenter.y += translation.y;
self.view.center = currentCenter;
[recognizer setTranslation:CGPointZero inView:self.view.superview];

How to rotate UIButton or UIImage view that follows finger (Touch and hold)?

I need some help.How to rotate UIButton or UIImageView that follows finger (Touch and hold, UILongPressGestureRecognizer)? Thx 4 help
UPD: Don't understand what i'm doing wrong?
- (void)viewDidLoad {
UITapGestureRecognizer *tapgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(tap:)];
[self.view addGestureRecognizer:tapgr];
[tapgr release];
[super viewDidLoad];
}
-(void)tap:(UITapGestureRecognizer *)gesture {
CGPoint touch = [gesture locationInView:self.view];
CGPoint center = myImage.center;
float dx,dy,wtf;
dx = touch.x-center.x;
dy = touch.y-center.y;
wtf = atan2f(dy, dx);
[self rotateImage:self.myImage withAngle:wtf];
}
- (void)rotateImage:(UIImageView *)image withAngle:(float)newAngle
{
image.transform = CGAffineTransformMakeRotation(newAngle);
}
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
- (void) LongPress:(UILongPressGestureRecognizer *)gesture {
CGPoint p = [gesture locationInView:self.view];
CGPoint zero;
zero.x = self.view.bounds.size.width / 2.0;
zero.y = self.view.bounds.size.height / 2.0;
CGPoint newPoint;
newPoint.x = p.x - zero.x;
newPoint.y = zero.y - p.y;
angle = atan2(newPoint.x, newPoint.y);
UIViewAnimationOptions options = UIViewAnimationOptionBeginFromCurrentState|UIViewAnimationOptionAllowUserInteraction;
[UIView animateWithDuration:0.2 delay:0.0 options:options
animations:^{myButton.transform = CGAffineTransformRotate(CGAffineTransformIdentity, angle);}
completion:^(BOOL finished) {
[UIView animateWithDuration:1.0 delay:0.5 options:options animations:^{
myButton.transform = CGAffineTransformRotate(CGAffineTransformIdentity, [self detectQuarter:angle]);
} completion:nil];
}];
}
#define M_PI_3_4 3*M_PI_4
-(CGFloat)detectQuarter:(CGFloat)anAngle {
if ((anAngle >= -M_PI_4)&&(anAngle <= M_PI_4)) return 0;
if ((anAngle > M_PI_4) && (anAngle <= 3*M_PI_4)) return M_PI_2;
if ((anAngle >= -M_PI_3_4) && (anAngle < -M_PI_4)) return -M_PI_2;
else return M_PI;
}