"Drag 'n' Drop" game animation - objective-c

I'm quite new to Objective-C and am looking to create a fairly simple Jigsaw. I'm currently just looking at making a 4-piece puzzle as a way of learning the method.
At the moment I have 4 pieces placed around the screen that when dragged to a specific place on screen, snap to that place.
My problem is trying to animate the touches. I want the image touched to expand a little but i'm having trouble with the syntax. I've looked at the MoveMe example that Apple provide but it's not helping me in this situation. Below is the code. I'd appreciate any help with this. Thanks.
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
//location of current touch
CGPoint location = [touch locationInView:self.view];
if ([touch view] == image1) {
image1.center = location;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
image1.transform = CGAffineTransformMakeScale(1.5, 1.5);
[UIView commitAnimations];
} else if ([touch view] == image2) {
image2.center = location;
animateFirstTouch:image2;
} else if ([touch view] == image3) {
image3.center = location;
image3.transform = CGAffineTransformMakeScale(1.5, 1.5);
} else if ([touch view] == image4) {
image4.center = location;
image4.transform = CGAffineTransformMakeScale(1.5, 1.5);
}
}
-(void) animateFirstTouch:(UIView *)image {
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
self.view.transform = CGAffineTransformMakeScale(1.5, 1.5);
[UIView commitAnimations];
}
The code for image1 works, and the image is scaled up over 0.5 seconds.
The code for image2 throws up an error: expression result unused for animateFirstTouch:image2.
The code for image3 and image4 scales up the images without the animation.

Refer to Kuldeep's answer from this link. I think that would work for you:
iPhone/iOS: How to implement Drag and Drop for subviews of a Scrollview?
Also as an alternative refer to iPhone's answer in this link:
iPhone App: implementation of Drag and drop images in UIView
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
//location of current touch
CGPoint location = [touch locationInView:self.view];
if ([touch view] == image1) {
[self animateFirstTouch:image1 withLocation:location];
} else if ([touch view] == image2) {
[self animateFirstTouch:image2 withLocation:location];
} else if ([touch view] == image3) {
[self animateFirstTouch:image3 withLocation:location];
} else if ([touch view] == image4) {
[self animateFirstTouch:image4 withLocation:location];
}
}
-(void) animateFirstTouch:(UIImageView *)image withLocation:(CGPoint)location {
image.center = location;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
image.transform = CGAffineTransformMakeScale(1.5, 1.5);
[UIView commitAnimations];
}
Hope this helps you.
Contact me if you need more help.

Related

How to move one image intersect by other image on view using UITouch

I am using UITouch methods for moving the imageView from left-to-right and right-to-left. For this I am using below patch and its working fine
-(void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
UITouch *touch1 = [[event allTouches] anyObject];
CGPoint location = [touch1 locationInView: self.view];
if ([touch1 view] == _ballimg)
{
if (location.x<=268 && location.x>=20)
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
CGRect rect = CGRectMake(location.x, _ballimg.frame.origin.y,_ballimg.frame.size.height, _ballimg.frame.size.width);
[_ballimg setFrame:rect];
[UIView commitAnimations];
}
}
if ([touch1 view] == _ballimg1)
{
if (location.x<=312 && location.x>=64)
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:1.0];
CGRect rect = CGRectMake(location.x, _ballimg1.frame.origin.y,_ballimg1.frame.size.height, _ballimg1.frame.size.width);
[_ballimg1 setFrame:rect];
[UIView commitAnimations];
}
}
}
But now when two images are intersecting then I have to push the intersecting imageView from the current touched imageView either left-to-right or right-to-left. What will be the best approach?

using the tableview as horizontal scroll and animating the views and also animating the text like marquee

//To Drag the image View on the iphone screen
- (void) touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
point0 = [touch locationInView:self.view];
if ([touch tapCount] == 2) {
dropDownBool = NO;
pushUpBool = NO;
self.imageView.alpha = 0.4;
doublePressed = YES;
}
if(doublePressed)
{
point0 = [touch locationInView:self.view];
if (CGRectContainsPoint([self.imageView frame], [touch locationInView:[touch view]]))
{
self.imageView.center = [touch locationInView:nil];
}
}
}
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
point0 = [touch locationInView:self.imageView];
if(doublePressed)
{
UITouch *touch = [[event allTouches] anyObject];
point0 = [touch locationInView:self.imageView];
//animating the view...
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.5];
CGAffineTransform transform =CGAffineTransformTranslate(CGAffineTransformIdentity,0.0f, 0.0f);
self.imageView.transform = transform;
[UIView commitAnimations];
doublePressed = NO;
self.imageView.alpha = 1.0;
}
}
// To drop down a view as you swipe on top of the screen
-(void)handleSwipeGesture:(UISwipeGestureRecognizer *) sender
{
//Gesture detect - swipe up/down , can be recognized direction
if(sender.direction == UISwipeGestureRecognizerDirectionUp)
{
pushUpBool = YES;
}
else
if(sender.direction == UISwipeGestureRecognizerDirectionDown)
{
dropDownBool = YES;
}
if(dropDownBool && (point0.y < 80.0f))
{
NSLog(#"%f",point0.y);
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25];
self.dropDownView.center = CGPointMake(originalCenter.x,30.0 );
self.dropDownView.alpha = 0.8;
dropDownBool = NO;
}
if(pushUpBool && (point0.y < 80.0f))
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.25];
pushUpBool = NO;
self.dropDownView.center = originalCenter;
self.dropDownView.alpha = 0.0;
}
}
// animates from left to right like Marqee...
-(void) scrollLeft
{
CABasicAnimation *scrollText;
scrollText=[CABasicAnimation animationWithKeyPath:#"position.x"];
scrollText.duration = 6.0;
scrollText.repeatCount = 10000;
scrollText.autoreverses = NO;
scrollText.fromValue = [NSNumber numberWithFloat:500];
scrollText.toValue = [NSNumber numberWithFloat:-120.0];
[[self.detailView layer] addAnimation:scrollText forKey:#"scrollTextKey"];
}
// Making the table View scroll horizontally place this code in viewDidLoad.
CGAffineTransform transform = CGAffineTransformMakeRotation(-1.5707963);
self.horizontalTableView.transform = transform;
// now in tableview method transform the cell back.
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
CGAffineTransform transform = CGAffineTransformMakeRotation(1.5707963);
cell.transform = transform;
}
Using the above Methods one can transform the table view look like a horizontal scroll view. and you can drag the image view by double clicking on the image and moving it across the screen.
if you have any question please feel free.

Custom animation when hiding UINavigationBar

I'm making an application which shows/hides (in custom animation) the UINavigationBar on single tap.
I have created two functions (one for showing and the other for hiding). The function for showing the UINavigationBar works perfectly:
- (void) showNavigationBar {
[UINavigationBar beginAnimations:#"NavBarFadeIn" context:nil];
self.navigationController.navigationBar.alpha = 0;
[UINavigationBar setAnimationCurve:UIViewAnimationCurveEaseIn];
[UINavigationBar setAnimationDuration:0.5];
[UINavigationBar setAnimationTransition:UIViewAnimationOptionTransitionFlipFromTop
forView:self.navigationController.navigationBar
cache:YES];
self.navigationController.navigationBar.alpha = 1;
[UINavigationBar commitAnimations];
}
But the function for hiding it, even if it's the same, doesn't work. The UINavigationBar disappears suddenly with no animation.
- (void) hideNavigationBar {
[UINavigationBar beginAnimations:#"NavBarFadeOut" context:nil];
self.navigationController.navigationBar.alpha = 1;
[UINavigationBar setAnimationCurve:UIViewAnimationCurveEaseIn];
[UINavigationBar setAnimationDuration:0.5];
[UINavigationBar setAnimationTransition:UIViewAnimationOptionTransitionCurlUp
forView:self.navigationController.navigationBar
cache:YES];
self.navigationController.navigationBar.alpha = 0;
[self.navigationController setNavigationBarHidden:YES animated:NO];
[UINavigationBar commitAnimations];
}
The calling:
- (void)contentView:(ReaderContentView *)contentView touchesBegan:(NSSet *)touches
{
if( [[self navigationController] isNavigationBarHidden] == NO)
{
if (touches.count == 1) // Single touches only
{
UITouch *touch = [touches anyObject]; // Touch info
CGPoint point = [touch locationInView:self.view]; // Touch location
CGRect areaRect = CGRectInset(self.view.bounds, TAP_AREA_SIZE, TAP_AREA_SIZE);
if (CGRectContainsPoint(areaRect, point) == false) return;
}
[mainToolbar hideToolbar];
[mainPagebar hidePagebar]; // Hide
[self hideNavigationBar];
lastHideTime = [NSDate new];
}
}
Anybody has a clue about why this is happening?
It is happening, because you are calling [self.navigationController setNavigationBarHidden:YES animated:NO]; in the animation code but boolian values are not animatable. There is no "in between values" for bool values.
You should call [self.navigationController setNavigationBarHidden:YES animated:NO]; in a method which you schedule after the animation with
[UINavigationBar setAnimationDidStopSelector: #selector(myCoolMethod:)];

How to drag only one image with iPhone SDK

I want to create a little app that takes two images and i want to make only the image over draggable.
After research, i found this solution:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[ event allTouches] anyObject];
image.alpha = 0.7;
if([touch view] == image){
CGPoint location = [touch locationInView:self.view];
image.center = location;
}
It works but the problem is that the image is draggable from its center and I don't want that.
So I found another solution:
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
// Retrieve the touch point
CGPoint pt = [[touches anyObject] locationInView:self.view];
startLocation = pt;
[[self view] bringSubviewToFront:self.view];
}
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event {
// Move relative to the original touch point
CGPoint pt = [[touches anyObject] locationInView:self.view];
frame = [self.view frame];
frame.origin.x += pt.x - startLocation.x;
frame.origin.y += pt.y - startLocation.y;
[self.view setFrame:frame];
}
It works very well but when I add another image, all the images of the view are draggable at the same time. I'm a beginner with the iPhone development and I have no idea of how I can only make the image over draggable.
You can use if condition in the touchesBegan: method, See this-
-(void)ViewDidLoad
{
//Your First Image View
UIImageView *imageView1 = [UIImageView alloc]initWithFrame:CGRectMake(150.0, 100.0, 30.0, 30.0)];
[imageView1 setImage:[UIImage imageNamed:#"anyImage.png"]];
[imageView1 setUserInteractionEnabled:YES];
[self.view addSubview:imageView1];
//Your Second Image View
UIImageView *imageView2 = [UIImageView alloc]initWithFrame:CGRectMake(150.0, 200.0, 30.0, 30.0)];
[imageView2 setImage:[UIImage imageNamed:#"anyImage.png"]];
[imageView2 setUserInteractionEnabled:YES];
[self.view addSubview:imageView2];
}
//Now Use Touch begin methods with condition like this
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches]anyObject];
if([touch view] == imageView1)
{
CGPoint pt = [[touches anyObject] locationInView:imageView1];
startLocation = pt;
}
if([touch view] == imageView2)
{
CGPoint pt = [[touches anyObject] locationInView:imageView2];
startLocation = pt;
}
}
//Use same thing with touch move methods...
- (void) touchesMoved:(NSSet *)touches withEvent: (UIEvent *)event
{
UITouch *touch = [[event allTouches]anyObject];
if([touch view] == imageView1)
{
CGPoint pt = [[touches anyObject] previousLocationInView:imageView1];
CGFloat dx = pt.x - startLocation.x;
CGFloat dy = pt.y - startLocation.y;
CGPoint newCenter = CGPointMake(imageView1.center.x + dx, imageView1.center.y + dy);
imageView1.center = newCenter;
}
if([touch view] == imageView2)
{
CGPoint pt = [[touches anyObject] previousLocationInView:imageView2];
CGFloat dx = pt.x - startLocation.x;
CGFloat dy = pt.y - startLocation.y;
CGPoint newCenter = CGPointMake(imageView2.center.x + dx, imageView2.center.y + dy);
imageView2.center = newCenter;
}
}
These two images will move only when you touch on it and move it. I hope my tutorials will help you.
Simply use these two methods
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
myImage.center = location;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesBegan:touches withEvent:event];
}
Let's break it down. You should have a main containerView (object of UIView) in your view controller. Within that, you should have DragableImageView objects.
DragableImageView inherits UIImageView and within that, you add your touches code. (Right now you are doing self.frame = position which is wrong - and obviously it will move all images at once - because if I understand correctly, you are adding these touches in your view controller).
Create only DragableImageView first, test it. Then add two DragableImageView instances. test them in different configurations.. you might want to hit test in the containerView to see which DragableImageView should be dragged (e.g. if you have jigsaw pieces, you might want to pick the one that is at the back rather than the front one).

Rotate view using CGAfffineTransformRotate

I have a circular image which I am trying to rotate, so that the yellow and black striped circle stays under the user's finger and rotates in both directions. I have this so far:
- (void)handleJogShuttle:(UIPanGestureRecognizer *)recognizer {
UIView *shuttle = [recognizer view];
if ([recognizer state] == UIGestureRecognizerStateBegan ||
[recognizer state] == UIGestureRecognizerStateChanged) {
[recognizer view].transform = CGAffineTransformRotate([[recognizer view] transform],M_PI / 20.0f);
[recognizer setTranslation:CGPointZero inView:[shuttle superview]];
}
}
Also, currently, the slightest movement can cause the view to rotate in a full circle, which is obviously not desired.
#import "RotationTestViewController.h"
#interface RotationTestViewController()
-(void)transformSpinnerwithTouches:(UITouch *)touchLocation;
-(CGPoint)vectorFromPoint:(CGPoint)firstPoint toPoint:(CGPoint)secondPoint;
-(void)animateView:(UIView *)theView toPosition:(CGAffineTransform) newTransform;
#end
#implementation RotationTestViewController
- (void)viewDidLoad {
[super viewDidLoad];}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches)
{
// Send to the dispatch method, which will make sure the appropriate subview is acted upon
// currentTouch=touch;
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches){
// Sends to the dispatch method, which will make sure the appropriate subview is acted upon
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch=[[event allTouches]anyObject];
if (touch.view==Spinner)
{
[self transformSpinnerwithTouches:touch];
}
}
-(void)transformSpinnerwithTouches:(UITouch *)touchLocation
{
CGPoint touchLocationpoint = [touchLocation locationInView:self.view];
CGPoint PrevioustouchLocationpoint = [touchLocation previousLocationInView:self.view];
//origin is the respective piont from that i gonna measure the angle of the current position with respective to previous position ....
CGPoint origin;
origin.x=Spinner.center.x;
origin.y=Spinner.center.y;
CGPoint previousDifference = [self vectorFromPoint:origin toPoint:PrevioustouchLocationpoint];
CGAffineTransform newTransform =CGAffineTransformScale(Spinner.transform, 1, 1);
CGFloat previousRotation = atan2(previousDifference.y, previousDifference.x);
CGPoint currentDifference = [self vectorFromPoint:origin toPoint:touchLocationpoint];
CGFloat currentRotation = atan2(currentDifference.y, currentDifference.x);
CGFloat newAngle = currentRotation- previousRotation;
temp1=temp1+newAngle;
NSLog(#"Angle:%F\n",(temp1*180)/M_PI);
newTransform = CGAffineTransformRotate(newTransform, newAngle);
[self animateView:Spinner toPosition:newTransform];
}
-(void)animateView:(UIView *)theView toPosition:(CGAffineTransform) newTransform
{
[UIView setAnimationsEnabled:YES];
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationCurve:UIViewAnimationCurveLinear];
[UIView setAnimationBeginsFromCurrentState:YES];
[UIView setAnimationDuration:0.0750];
Spinner.transform = newTransform;
[UIView commitAnimations];
}
//-(CGFloat)distanceFromPoint:(CGPoint)fromPoint toPoint:(CGPoint)toPoint
//
//{
//float x = toPoint.x - fromPoint.x;
//float y = toPoint.y - fromPoint.y;
//return hypot(x, y);
//}
-(CGPoint)vectorFromPoint:(CGPoint)firstPoint toPoint:(CGPoint)secondPoint
{
CGFloat x = secondPoint.x - firstPoint.x;
CGFloat y = secondPoint.y - firstPoint.y;
CGPoint result = CGPointMake(x, y);
//NSLog(#"%f %f",x,y);
return result;
}
-(void) dealloc
{
[Spinner release];
[super dealloc];
}
I suspect this method gets called A LOT. Try using NSLog and check how many time it does.
Anyway, you are not calculating the angle properly, you could try using
-(CGPoint)translationInView:(UIView *)view
from the recognizer to calculate the correct angle to rotate.