multiple touch in xcode iOS objective C - ios

I have a character in my game that I can move left/right and jump. I am using touchesBegan to do that. But when I move left ( keep touching the screen -> makes character faster and faster ), it only jumps when i release it. I would like to jump and move left at the same time.
Here is some of my code :
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
if((point.x < moveLeftButton.frame.size.width))
{
if((point.y > JumpButton.frame.size.height))
{
leftSide = YES;
sanchez.image = [UIImage imageNamed:#"characterL2"];
}
}
if((point.x) > (backGround.frame.size.width - moveRightButton.frame.size.width))
{
if((point.y > JumpButton.frame.size.height))
{
rightSide = YES;
sanchez.image = [UIImage imageNamed:#"characterR2"];
}
}
if( notJumping && (point.y < JumpButton.frame.size.height) && (sanchezStopAll == NO))
{
AudioServicesPlaySystemSound(jump);
sanchezJumping = 5.5;
notJumping = NO;
}
[self animation];
}
I am not using buttonPressed because they are hidden and I think you can't click hidden buttons.
This is how it looks like if its not hidden:
Thanks for any Help.

You'll only get a single touch by default unless you set multipleTouchEnabled = YES. Then your code should work as expected.
For example:
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.multipleTouchEnabled = YES;
}

Related

Make bigger field for touch and drag node, objective c

I'm making small paddle node whom can touch and drag in defined area. The problem is that paddle is small wich makes for finger unresponsive. My question is how can i make area around node bigger without making node bigger. Here are What Iam working on:
- (id)initWithName:(NSString *)name
{
self = [super init];
if (self) {
self = [PaddleNode spriteNodeWithImageNamed: #"board.png"];
self.userInteractionEnabled = YES;
self.name = name;
self.physicsBody = [SKPhysicsBody bodyWithRectangleOfSize:self.frame.size];
self.physicsBody.dynamic = NO;
self.physicsBody.usesPreciseCollisionDetection = YES;
self.physicsBody.categoryBitMask = paddleCategory;
self.physicsBody.collisionBitMask = emptyCategory;
self.currentTouchValue = nil;
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
self.previousTouchesTimestamp = event.timestamp;
for (UITouch *touch in touches) {
self.currentTouchValue = [NSValue valueWithNonretainedObject:touch];
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
self.currentTouchValue = nil;
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
NSValue *key = [NSValue valueWithNonretainedObject:touch];
if ([key isEqualToValue:self.currentTouchValue]) {
CGPoint touchPoint = [touch locationInNode:self.scene];
CGPoint movePoint = CGPointMake(self.position.x, touchPoint.y);
if ([self withinParentFrame:movePoint])
self.position = movePoint;
}
}
}
- (BOOL)withinParentFrame:(CGPoint)point
{
CGFloat offset = self.size.height / 2;
if (point.y >= offset && point.y <= self.scene.frame.size.height - offset)
return YES;
else
return NO;
}
Edited : I read
UITouch Class Reference
documentation. As I understand that, I can't do it in touchesMoved, but I find my old project, were are same code, but there I can put my finger anywhere on screen, and node will move in nodes defined area.
Edited 2 This question is still unanswered and important to me!

Overriding touches in Spritekit

In the game I am working on you can move a character from left to right by touching the left/right sides of the screen. What I'm trying to do is to make it that if you're touching the left side and then touch the right side, the character starts moving right instead of left; the action to move left is overridden. I have currently made it so that the game is single-touch but the method of overriding the previous touch is where I'm stuck at. My code:
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInNode:self];
if (location.x < screenWidth/2){
leftMovement = YES;
[player runLeft];
}
else {
rightMovement = YES;
[player runRight];
}
self.userInteractionEnabled = NO;
}
- (void) touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self playerStop];
self.userInteractionEnabled = YES;
}
- (void) update:(NSTimeInterval)currentTime {
if (isTouched && leftMovement){
player.physicsBody.velocity=CGVectorMake(-PLAYERSPEED,
player.physicsBody.velocity.dy);
}
else if (isTouched && rightMovement){
player.physicsBody.velocity=CGVectorMake(PLAYERSPEED,
player.physicsBody.velocity.dy);
}
}
One thing you should consider is to change the value of both leftMovement and rightMovement when the user touches the other side of the screen, otherwise, the right movement in update method will never be invoked.
if (location.x < screenWidth/2){
leftMovement = YES;
rightMovement = NO;
[player runLeft];
}
else {
rightMovement = YES;
leftMovement = NO;
[player runRight];
}

Drag UIImageView images using UITouch Methods

I have a UITableViewCell with UIImageViews embedded. I understand it's not common practice but I'm using the UITouch methods to accomplish horizontal swipes. I retrieve images from a url/api . The issue is I wish to drag one image at a time from either left to right. The problem is, when i drag my finger on across the imageView, all loaded images slide through quickly. I want to focus on one image at a time during the drag. Hope I was clear.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
startLocation = [[touches anyObject] locationInView:self];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
CGPoint point = [[touches anyObject] locationInView:self];
UITouch * touch = [touches anyObject];
self.viewOne.center = CGPointMake(self.viewOne.center.x+point.x - startLocation.x, self.viewOne.center.y);
if (startLocation.x < point.x) {
//Swipe Right
if ([self.photo.photoURLS isKindOfClass:[NSArray class]]) {
if (self.isSwiping == NO) {
self.isSwiping = YES;
self.currentImage--;
if (self.currentImage == -1) {
self.currentImage = 12;
}
self.viewBack.frame = CGRectMake(-self.frame.size.width,0.0f, self.frame.size.width, self.frame.size.height);
self.viewBack.hidden = NO;
self.loadingImage.hidden = NO;
NSURL *imageURL = [[NSURL alloc] initWithString:self.photo.photoURLS[self.currentImage]];
[self asyncLoadImageFromURL:imageURL andPhotoID:self.photo.id withCallback:^(UIImage *image, NSString *photoID) {
self.loadingImage.hidden = YES;
[imageCache setImage:image forKey:self.photo.photoURLS[self.currentImage]];
self.viewBack.image = image;
//new
self.viewOne.frame = CGRectMake(0.0f, 0.0f, self.frame.size.width, self.frame.size.height);
self.viewOne.image = self.viewBack.image;
self.isSwiping = NO;
self.pageControl.currentPage = self.currentImage;
self.viewBack.hidden = YES;
}];
}
}
}
} else {
//Swipe Left
}
}
It's not entirely clear what you're asking or what the issue is, but the following lines are suspect:
CGPoint point = [[touches anyObject] locationInView:self.vehicleImage];
self.viewOne.center = CGPointMake(self.viewOne.center.x+point.x -startLocation.x, self.viewOne.center.y);
if (startLocation.x < endLocation.x)
You are not setting endLocation until after you've finished touching the screen. During your touchesMoved responder, you'll be using bad endLocation data. You should be using the value of point in this function to determine motion.
It's also not really clear what is the relationship between self.vehicleImage and self.viewOne. If self.vehicleImage is a subview of self.viewOne (or otherwise moves during your frame changes), your locationInView will return seemingly inconsistent values, exaggerating the motion of your finger. Instead, you should be picking a view that will stay static during this process (perhaps your ViewController's self.view).

iOS touchesBegan issue

I have an NSArray whit 15 UIImageViews:
#interface ViewController : UIViewController{
NSArray *ArrayImages1;
NSArray *ArrayImages2;
}
in viewDidLoad:
ArrayImages1 = [[NSArray alloc] initWithObjects: a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, nil];
Where a1, a2... are the outlets of the UIImageViews
And the same for ArrayImages2
TouchesBegan and TouchesMoved:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
UIImageView *posible;
int imagen;
if (point.x < 161) {
imagen = Contador1;
if (Contador1 > 14) {imagen = Contador1 - 15;}
imagen--;
posible = [ArrayImages1 objectAtIndex:imagen];
}
else if (point.x > 159) {
imagen = Contador2;
if (Contador2 > 14) {imagen = Contador2 - 15;}
imagen--;
posible = [ArrayImages2 objectAtIndex:imagen];
}
if ([touch view] != posible) { return; }
original2 = posible.center;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self.view];
UIImageView *posible;
int imagen;
if (point.x < 161) {
imagen = Contador1;
if (Contador1 > 14) {imagen = Contador1 - 15;}
imagen--;
posible = [ArrayImages1 objectAtIndex:imagen];
}
else if (point.x > 159) {
imagen = Contador2;
if (Contador2 > 14) {imagen = Contador2 - 15;}
imagen--;
posible = [ArrayImages2 objectAtIndex:imagen];
}
if ([touch view] != posible) { return; }
posible.center = point;
}
I have to know if the touch was in one of the two posible UIImageViews, and if it was, move it.
The Contador1 and Contador2 ints, are counters that counts how many UIImageView are visible, the user only can move the last 2 of them.
It works, the thing is when i touch outside, it makes the app crash.
If i change in touchesBegan and TouchesMoved, the index of "posible = [ArrayImage..", for 0, it only works for the first UIImageView (i understand why), but it doesent crash.
Any ideas?
I have to know if the touch was in one of the two possible UIImageViews
I can't follow your code very well but it seems like you could simplify things if you first check if the point is within the rect of a view. Then base your logic off of the result. Something like
Using CGRectContainsPoint:
bool CGRectContainsPoint (
CGRect rect,
CGPoint point
);
UIImageView *foundView
for(UIImageView* theView in ArrayImages1){
if (CGRectContainsPoint(theView.frame, touchPoint){
foundView = theView;
break;
}
}
Then...
if (foundView != nil){
// do some logical thing
}
Or...
if ([foundView isEqual:someOtherView]){
// I may have the syntax wrong on the above
}

Detect diagonal swipe gestures in a UIView

I want to detect a two-finger diagonal swipe that starts from the bottom right of the screen to the middle. I tried adding UISwipeGestureRecognizer with direction set as "UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionLeft" but to no vail as the handler is getting invoked even if I start the swipe from the middle of the screen to the top left.
Do I need to sub-class UIGestureRecognizer or can I handle this using touchesBegan and touchesMoved ?
You need to subclass it to use touchesBegan and touchesMoved anyway. I'd do UISwipeGestureRecognizerDirectionUp | UISwipeGestureRecognizerDirectionLeft like you said, then set up two CGRects, one for acceptable starting points, one for acceptable end points. Then use the UIGestureRecognizerDelegate method gestureRecognizer:shouldReceiveTouch:, and check if the touch point is in the acceptable start rect by using CGRectContainsPoint(). Then (I think) in your UISwipeGestureRecognizer subclass, override touchesEnded:withEvent:, and check if the end touch is in the acceptable rect. If it's not, set the state to UIGestureRecognizerStateCancelled (or however you're supposed to cancel a gesture). Also make sure the view it's attached to has its multipleTouchEnabled property set. I haven't actually tried this, but something of the sort should do it. Good luck!
EDIT
Actually, if you didn't want to have to worry about specific rect values for the acceptable start/end points, and make it device independent, you could do this:
//swap in whatever percentage of the screen's width/height you want in place of ".75f"
//set the origin for acceptable start points
CGFloat startRect_x = self.view.frame.size.width * .75f;
CGFloat startRect_y = self.view.frame.size.height * .75f;
//set the size
CGFloat rectWidth = self.view.frame.size.width - startRect_x;
CGFloat rectHeight = self.view.frame.size.height - startRect_y;
//make the acceptable start point rect
CGRect startRect = CGRectMake(startRect_x, startRect_y, rectWidth, rectHeight);
//set the origin for the accepable end points
CGFloat endRect_x = self.view.center.x - rectWidth/2;
CGFloat endRect_y = self.view.center.y - rectHeight/2;
//make the acceptable end point rect
CGRect endRect = CGRectMake(endRect_x, endRect_y, rectWidth, rectHeight);
the touches method of cause can do every Gesture, the Gesture is supported since ios3.2.
i can give you a simple code , you maybe modify by yourself.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
isTwoFingersBegin = NO;
isTwoFingersEnd = NO;
UITouch *touch = [touches anyObject];
UIView *touchView = [touch view];
if ([touches count] == 2)
{
isTwoFingersBegin = YES;
}
touchStartPoint = [touch locationInView:self.view];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
isSwip = YES;
}
#define TOUCH_MOVE_EFFECT_DIST 30
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
UIView *touchView = [touch view];
touchEndPoint = [touch locationInView:self.view];
if ([touches count] == 2)
{
isTwoFingersEnd = YES;
}
CGPoint deltaVector = CGPointMake(touchEndPoint.x - touchStartPoint.x, touchEndPoint.y - touchStartPoint.y);
if (fabsf(deltaVector.x) > TOUCH_MOVE_EFFECT_DIST
&&fabsf(deltaVector.y) > TOUCH_MOVE_EFFECT_DIST
&& isSwip &&isTwoFingersBegin&&isTwoFingersEnd) {
theSwipGesture=RightUpGesture;
}
else if (fabsf(deltaVector.x) <- TOUCH_MOVE_EFFECT_DIST
&& fabsf(deltaVector.y) <- TOUCH_MOVE_EFFECT_DIST
&& isSwip&&isTwoFingersBegin&&isTwoFingersEnd) {
theSwipGesture=LeftDownGesture;
}
isSwip = NO;
}
You can use a UIPanGestureRecognizer
- (void)viewPanned:(UIPanGestureRecognizer *)panGR
{
CGPoint translation = [panGR translationInView:self];
CGFloat threshold = self.bounds.size.width/2;
// Detect
Direction direction = DirectionUnknown;
if (translation.x > threshold) {
if (translation.y > threshold) {
direction = DirectionBottomRight;
} else if (translation.y < -threshold) {
direction = DirectionTopRight;
} else {
direction = DirectionRight;
}
} else if (translation.x < -threshold) {
if (translation.y > threshold) {
direction = DirectionBottomLeft;
} else if (translation.y < -threshold) {
direction = DirectionTopLeft;
} else {
direction = DirectionLeft;
}
} else {
if (translation.y > threshold) {
direction = DirectionBottom;
} else if (translation.y < -threshold) {
direction = DirectionTop;
}
}
}
One possible solution would be to map off a group of coordinates on the iPhone's screen where the swipe could potentially start, and another where it could potentially end. Then in the touchesBegan: and touchesMoved: methods, you could compare the starting and ending points of the swipe and determine whether it qualified as diagonal.
Thanks Guys!
I ended up writing custom code in touchesBegan, touchesMoved and touchesEnded and ot works like charm.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if ([touches count] == 2) {
CGPoint nowPoint = [[touches anyObject] locationInView:self];
if( nowPoint.x >= ALLOWED_X)
swipeUp = YES;
}
[super touchesBegan:touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
if ([touches count] == 2 && swipeUp) {
CGPoint nowPoint = [[touches anyObject] locationInView:self];
CGPoint prevPoint = [[touches anyObject] previousLocationInView:self];
if( nowPoint.x <= prevPoint.x && nowPoint.y <= prevPoint.y){
}
else {
swipeUp = NO;
}
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesEnded:touches withEvent:event];
CGPoint nowPoint = [[touches anyObject] locationInView:self];
if ([touches count] == 2 && swipeUp && nowPoint.x <= DELTA_X && nowPoint.y <= DELTA_Y) {
NSLog(#"Invoke Method");
}
swipeUp = NO;
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesCancelled:touches withEvent:event];
swipeUp = NO;
}

Resources