I have a UIViewController that has a touchesBegan function and outputs the positions.
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"in");
NSArray *touchesArray = [touches allObjects];
for(int i=0; i<1; i++)
{
UITouch *touch = (UITouch *)[touchesArray objectAtIndex:i];
CGPoint point = [touch locationInView:touch.view];
NSLog(#"point = %f %f",point.x,point.y);
}
}
If I double tap quickly towards the middle of the screen, I get the following output
2012-02-12 21:47:13.522 MoreMost[479:707] in
2012-02-12 21:47:13.523 MoreMost[479:707] point = 698.000000 86.000000
2012-02-12 21:47:13.617 MoreMost[479:707] in
2012-02-12 21:47:13.619 MoreMost[479:707] point = 39.000000 22.000000
why is that second tap being registered as (39,22)...which is like the top left corner of the iPad. However, I was tapping in the middle.
So, I'd like to solve this in two ways:
1) somehow, not let the user double tap (however it seems even when I double tap fast, the touchesBegan function is called on two separate occassions)
2) figure out why that 2nd tap is being registered with the wrong coordinates.
It should be CGPoint point = [touch locationInView:self.view];...not "touch.view"
Related
In my current objective C project I am coding a mechanic that when you drag your hand on one half of the screen an object moves in direct correlation and when you drag on the other half of the screen, the other object moves in direct correlation but the first does not. When I test my project the first object moves perfectly on the half screen, however the second object does not when the other half of the screen is touched
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
if (location.x <= 259 )
[Person setCenter:CGPointMake(location.x, Person.center.y)];
if (location.y >289)
[Person1 setCenter:CGPointMake(location.x, Person1.center.y)];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
if (location.x <= 259 )
[Person setCenter:CGPointMake(location.x, Person.center.y)];
if (location.y >289)
[Person1 setCenter:CGPointMake(location.x, Person1.center.y)];
}
Your objects should be moving just fine. However, if you're trying to split your screen in half (as you said in your question) then your if statements in your touch delegate methods are rather odd. Here is an image of which "Person" object will be moved depending on where you touch the screen (assuming 4" screen in portrait)
As you can see, there is a section of screen that will not move either object, and another (rather large) section that will move both of your objects. There is only a very small area that will move Person1 by itself.
If you're wanting to assign half of your screen to each object, I would suggest doing something like this to split the top and bottom half of the screen:
if(location.y <= self.view.frame.size.height / 2)
{
// move Person
}
else
{
// move Person1
}
You could obviously modify that to split the left/right halves of the screen.
If you're still having issues moving both objects, make sure that they're hooked up to the view if they're IBOutlets
I want to shift the position of some UILabels when the user swipes the screen--specifically, move them the same distance the user swiped their finger.
How would I go about detecting and implementing this?
Thanks
Override touchesBegan:withEvent and touchesMoved:withEvent:. Keep track of the starting location in touchesBegan:withEvent. If repeated calls to touchesDragged (it is called while the drag is happening) show that you are moving fast enough for the action to be a swipe versus just a drag, use the difference between the starting location and the current touch location to animate changing the UILabels.
You can do that by using following methods for UIView.
In touchesBegan you should store the position where the user first touches the screen. So you can identify the left or right swipe when touches ends.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
self.startPoint = [touch locationInView:self];
}
Record the final position on touchesEnded method. By comparing this two positions you can determine the direction of movement.
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint endPosition = [touch locationInView:self];
if (startPoint.x < endPoint.x) {
// Right swipe
} else {
// Left swipe
}
}
I hope this helps.
I'm building a game using Sprite Kit that needs quick precise movements following the user's touch. I need to detect if the user has touched on the "Player" in the view, and if they have, when they move, the player sprite needs to move with the touch accordingly.
I have this working now, however, it's not very precise... the more movement input (without lifting your finger), the more offset the sprite gets from the touch location.
Here's the code I'm using right now.
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
if (self.isFingerOnPlayer) {
UITouch* touch = [touches anyObject];
CGPoint touchLocation = [touch locationInNode:self];
CGPoint previousLocation = [touch previousLocationInNode:self];
// Calculate new position for player
int playerX = player.position.x + (touchLocation.x - previousLocation.x);
int playerY = player.position.y + (touchLocation.y - previousLocation.y);
// Limit x and y so that the player will not leave the screen any
playerX = MAX(playerX, player.size.width/2);
playerX = MIN(playerX, self.size.width - player.size.width/2);
playerY = MAX(playerY, (player.size.width/2)-3+inBoundsOffset);
playerY = MIN(playerY, (self.size.height - ((player.size.width/2)-3) - inBoundsOffset));
// Update position of player
player.position = CGPointMake(playerX, playerY);
}
}
-(void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event {
UITouch* touch = [touches anyObject];
CGPoint touchLocation = [touch locationInNode:self];
SKPhysicsBody* body = [self.physicsWorld bodyAtPoint:touchLocation];
if (body && [body.node.name isEqualToString: #"player"]) {
NSLog(#"Began touch on player");
self.isFingerOnPlayer = YES;
}
}
-(void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event {
self.isFingerOnPlayer = NO;
}
It detects the touch location, checks to make sure that you're touching the player sprite, if you are, then when you move, so does the sprite... but it can get off quite quickly if you're slinging your finger around (as playing this game will cause the player to do).
Can anybody suggest a more accurate way of accomplishing this, that will keep the sprite under the user's finger even when moving around a lot without lifting your finger?
You have to keep in mind that -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event ONLY gets called when the moving finger writes (sorry couldn't help the Inspector Clouseau reference).
In effect what happens is that the user can very quickly move his/her finger from one location to the next and as soon the the finger is lifted, your position updates stops.
What I suggest you do is create a CGPoint property and have -(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event store the location in the CGPoint property.
Then in your -(void)update:(CFTimeInterval)currentTime you add the code that actually moves the player to the finger coordinates. This should make things a lot smoother.
I want to rotate a gun based on the user dragging their finger on the screen. I figure i will need my cartesian points in polar coordinates and that i will need a long press gesture which is both things that i have. I am just wondering how i would go about programming this? sorry i'm really new to sprite kit i have read all of apple's documentation and i'm having a hard time finding this. My anchor point is 0,0.
-(void)shootBullets:(UILongPressGestureRecognizer *) gestureRecognizer
{
double radius;
double angle;
SKSpriteNode *gun = [self newGun];
}
i figured out how to get the angle but now my zrotation wont work. Like i nslog and the angles are right but when i click gun.zrotation and i tap nothing happens? please help i'm getting uber mad.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:touch.view];
SKSpriteNode *gun = [self newGun];
self.gunRotation = atanf(location.y/location.x)/0.0174532925;
gun.zRotation = self.gunRotation;
NSLog(#"%f",gun.zRotation);
}
This is a very old question, but here is what I did - hopefully it will help someone out there:
#import "MyScene.h"
#define SK_DEGREES_TO_RADIANS(__ANGLE__) ((__ANGLE__) * 0.01745329252f) // PI / 180
Then add this:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
CGPoint positionInScene = [touch locationInNode:self];
float deltaX = positionInScene.x - gun.position.x;
float deltaY = positionInScene.y - gun.position.y;
float angle = atan2f(deltaY, deltaX);
gun.zRotation = angle - SK_DEGREES_TO_RADIANS(90.0f);
}
}
Check out the answers I got to this question about how to implement a rotary knob, people have already figured out all the geometry, all you need to do is implement a transparent rotary knob, get its angle and pass it to your sprite kit object, using action rotate
My issue occurs when I drag the uiimageview accross the screen on, which is set to only be dragable in the x axis direction.
The code sort of works. The uiimageview is moving alright and it's limited to the x axis only, which is exactly what it should.
BUT when you start dragging outside the frame of the uiimageview, it stops moving along side my finger.
This obliviously has something to do with this method: CGRectContainsPoint.
Bare in mind it's very necessary in my code as I only want the uiimageview to move, when a user has set it's finger on it.
If I didn't use this method CGRectContainsPoint, the image would still move even when a users finger wouldn't touch the image. Any work around this is much appreciated.
here's my code:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"Touches Moved is running");
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.view];
if (CGRectContainsPoint(UIImageView, location) && UIImageView >= 40)
{
NSLog(#"Contains Point UIImageView Center!");
CGPoint xLocation = CGPointMake(location.x,UIImageView);
UIImageView = xLocation;
//here it comes.. big block of code//
if (location.x <= 40) {
NSLog(#"Start Dragging Point");
CGPoint newLocation = CGPointMake(40
, 402);
UIImageView = newLocation;
}
else if(location.x >= 273) {
NSLog(#"End Dragging Point");
CGPoint newLocation = CGPointMake(273
, 402);
UIImageView = newLocation;
}
}
Move CGRectContainsPoint(UIImageView, location) from -(void)touchesMoved:... to -(void)touchesBegan:....
Set an ivar there that points to the view only when you began the touch inside the view. Use this ivar from -(void)touchesMoved:... to boundlessly move the view. You can then unset this variable both in -(void)touchesEnded:... and -(void)touchesCancelled:....