Move a UIView only Horizontally - cocoa-touch

I have 2 UIViews (placardView, and PlacardView2) that I would like to constrain them when touched to move horizontally but not vertically using the touchesMoved Method. My thought was to make the Y co-ordinate equal to itself, but I cannot get that to work syntactically in Xcode as I am new to this sort of thing.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
// If the touch was in the placardView, move the placardView to its location
if ([touch view] == placardView) {
CGPoint location = [touch locationInView:self];
placardView.center = location;
placardView.center.y = placardView.center.y;//error is here
return;
}
if ([touch view] == placardView2) {
CGPoint location = [touch locationInView:self];
placardView2.center = location;
placardView2.center.y = placardView2.center.y;//error is here
return;
}
}

You won't change anything by assigning center.y to itself - plus it is already changed by placardView2.center = location; assignment. Instead, you should probably assign just the new x coordinate:
CGPoint placardCenter = placardView2.center;
placardCenter.x = location.x;
placardView2.center = placardCenter;

Related

Drag multiple UIImageViews in an Array

This is what I have so far
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
for (UIImageView *imageView in _imageViewArray) {
CGPoint Location = [touch locationInView:touch.view];
imageView.center = Location;
}
}
The problem I am facing is when I move one image they all jump to the same place.
Thanks to cyberpawn this it what I did it get it to work
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint oldPoint = [touch previousLocationInView:touch.view];
CGPoint newPoint = [touch locationInView:touch.view];
CGPoint diff = CGPointMake(newPoint.x - oldPoint.x, newPoint.y - oldPoint.y);
for (UIImageView *imageView in _imageViewArray) {
if (CGRectContainsPoint(imageView.frame, newPoint)) {
CGPoint cntr = [imageView center];
[imageView setCenter:CGPointMake(cntr.x + diff.x, cntr.y + diff.y)];
}
}
}
Thats because you are moving them all to same location, you need to calculate the difference between touch locations and add that displacement to all views. Below code should solve your problem! Forget touchesBegan and Just override touchesMoved method like that.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint oldPoint = [touch previousLocationInView:touch.view];
CGPoint newPoint = [touch locationInView:touch.view];
CGPoint diff = CGPointMake(newPoint.x - oldPoint.x, newPoint.y - oldPoint.y);
for (UIImageView *imageView in _imageViewArray) {
CGPoint cntr = [imageView center];
[imageView setCenter:CGPointMake(cntr.x + diff.x, cntr.y + diff.y)];
}
}
If You want to move them separately when any of them is clicked than use below code instead!
float oldX, oldY;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint pt = [touch locationInView:touch.view];
for (UIImageView *imageView in _imageViewArray) {
if(CGRectContainsPoint(imageView.frame, pt)) {
oldX = imageView.center.x - imageView.frame.origin.x - pt.x;
oldY = imageView.center.y - imageView.frame.origin.y - pt.y;
break;
}
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[event allTouches] anyObject];
CGPoint pt = [touch locationInView:touch.view];
for (UIImageView *imageView in _imageViewArray) {
if (CGRectContainsPoint(imageView.frame, pt)) {
[self setCenter:CGPointMake(pt.x+oldX, pt.y+oldY)];
}
}
Enjoy Programming!
Here you coded like that only. If you want to move a single image, then you have to find that image and you should move that image alone.

Prevent view object from jumping when moving with finger touch

I've created a 200x200 circle in a custom UIView. I am using the following script to move the view object around the screen on the iPad.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
if([touch view] == newShape)
{
newShape.center = currentPoint;
}
[self.view setNeedsDisplay];
}
Everything works fine, I can move the circle anywhere on the screen. However, if I don't touch dead center on the circle object, it jumps slightly. By reading the code, this is quite obvious because newShape.center is being set to wherever the touch happens and ultimately snapping quickly to that position.
I'm looking for a way to move an object without snapping to the touch position. I'm thinking I would use xy coordinates to achieve this, but I'm not sure how to implement it.
Thanks!
Declare CGPoint prevPos; in .h file.
Here my view is _rectView.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
prevPos = currentPoint;
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:self.view];
if([touch view] == _rectView)
{
float delX = currentPoint.x - prevPos.x;
float delY = currentPoint.y - prevPos.y;
CGPoint np = CGPointMake(_rectView.frame.origin.x+delX, _rectView.frame.origin.y+delY);
//_rect.center = np;
CGRect fr = _rectView.frame;
fr.origin = np;
_rectView.frame = fr;
}
//[self.view setNeedsDisplay];
prevPos = currentPoint;
}
Use the above code. You will not get that 'jump' effect.
An obvious way to do it is to store the offset of the touch from the shape's center in -touchesBegan:withEvent: and apply the offset in -touchesMoved:withEvent:.

Cocos2d rotation on touches moved problem

I have a spear like sprite. It rotation is decided by touchesMoved method. whenever the user slides his finger it points towards that touch. This is my method:
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch* touch = [touches anyObject];
CGPoint location = [touch locationInView: [touch view]];
float angleRadians = atanf((float)location.y / (float)location.x);
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
spear.rotation = -1 * angleDegrees;
}
This kinda works, but only from 0 to 45 degrees. and it goes opposite. So as I am moving from finger for bottom to top, it rotates clockwise (it should follow direction of fnger and rotate counter clockwise). From 45 to 90, it works fine (moves counter clickwise) but only if i start the touch in upper diagonal of the screen.
What am i doing wrong?
Thanks
#define PTM_RATIO 32
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
for( UITouch *touch in touches ) {
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL: location];
b2Vec2 locationWorld = b2Vec2(location.x/PTM_RATIO, location.y/PTM_RATIO);
spriteBody->SetTransform(locationWorld,spriteBody->GetAngle());
}
}
-(void) tick: (ccTime) dt
{
//It is recommended that a fixed time step is used with Box2D for stability
//of the simulation, however, we are using a variable time step here.
//You need to make an informed choice, the following URL is useful
//http://gafferongames.com/game-physics/fix-your-timestep/
int32 velocityIterations = 8;
int32 positionIterations = 1;
// Instruct the world to perform a single step of simulation. It is
// generally best to keep the time step and iterations fixed.
m_world->Step(dt, velocityIterations, positionIterations);
// for (int i = 0; i < (int)birds.size(); i++)
// birds[i]->render();
//Iterate over the bodies in the physics world
for (b2Body* b = m_world->GetBodyList(); b; b = b->GetNext())
{
if (b->GetUserData() != NULL) {
//Synchronize the AtlasSprites position and rotation with the corresponding body
CCSprite *myActor = (CCSprite*)b->GetUserData();
myActor.position = CGPointMake( b->GetPosition().x * PTM_RATIO, b->GetPosition().y * PTM_RATIO);
myActor.rotation = -1 * CC_RADIANS_TO_DEGREES(b->GetAngle());
}
}
}
Figured out what was wrong. I needed to change the CGPoint I got from the touches into GL point like this:
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL: location];
Silly me. Should have thought about this before.
CGPoint touchLocation = [touch locationInView: [touch view]];
touchLocation = [[CCDirector sharedDirector] convertToGL:touchLocation];
touchLocation = [self convertToNodeSpace:touchLocation];
GPoint diff = ccpSub(touchLocation, _player.position);
//rotate to face the touch
CGPoint diff = ccpSub(_player.position, touchLocation);
float angleRadians = atanf((float)diff.y / (float)diff.x);
float angleDegrees = CC_RADIANS_TO_DEGREES(angleRadians);
float cocosAngle = -1 * angleDegrees;
if(diff.x < 0)
{
cocosAngle += 180;
}
id actionRotateTo = [CCRotateTo actionWithDuration:0.1 angle:cocosAngle];
[_player runAction:actionRotateTo];

How to get last touch in ccTouchesMoved?

I'm working with cocos2d. How to get last touch in ccTouchesMoved?
Add a global Variable in your ccTouchesBegan,
CGPoint touchPoint = [touch locationInView:[touch view]];
startPosition = [[CCDirector sharedDirector] convertToGL:touchPoint];
in your ccTouchesMoved just use startPosition to check whether your hand moved
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [[touches allObjects] objectAtIndex: 0];
// The last location you touch
CGPoint lastLocation = [touch previousLocationInView:self.view];
// Current location
CGPoint currentLocation = [touch locationInView:self.view];
}
You can do like that :)

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).