Trying to use CCEaseOut to slow CCSprite Movement - iphone

I am trying to make my CCSprite come a gliding stop instead of an abrupt halt however I'm not too sure how to do this. I'm moving a CCSprite using CCActionMoveTo and CCEaseOut based on where the user taps; the sprite does move however doesn't glide to a halt. My code is below:
-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchLoc = [touch locationInNode:self];
CCActionMoveTo *actionMove = [CCActionMoveTo actionWithDuration:0.2f position:ccp(touchLoc.x, 150)];
id ease = [CCEaseOut actionWithAction:actionMove rate:2];
[_playerSprite runAction: ease];
}

Increase the easing rate to see a more profound effect. 2 is low, and it might not be obvious at that value. Perhaps you would like CCEaseExponentialOut as well.

I would recommend you to read http://www.raywenderlich.com/24824/introduction-to-ai-programming-for-games tutorial, specifically the part on "Steering"

Related

casting and parameters to move a sprite cocos2d

I can't work out how to pass the touch location in touch began into my method that is ran when touch began starts.
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
[self schedule:#selector(moveSprite:)];
return TRUE;
}
-(void)ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
[self unschedule:#selector(moveSprite:)];
}
-(void)moveSprite:(ccTime) delta
{
CGPoint spriteCenter = CGPointMake(player.contentSize.width /2,player.contentSize.height /2);
CGPoint touchPoint; //how to get this touch began?
float distanceX = touchPoint.x - spriteCenter.x;
float distanceY = touchPoint.y - spriteCenter.y;
float angle = atan2f(distanceY,distanceX); // returns angle in radians
player.rotation = angle;
}
I also have a question about [self schedule:#selector: Will this continuously call my move sprite method? As I'm going to want the sprite to continuously move and change rotation accordingly as the touch is held down and the sprites position changes.
My final question is about moving the sprite to the x coordinate of the touch. If I use ccmoveto I can't use velocity to make the sprite slowly increase its speed can I? How would I move the sprite to the touched point increasing velocity? I'm guessing its something to do with delta.
Actually, I don't see any need in your scheduled method. You just can implement
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
method and place your sprite rotation logic there.
To get changeable move velocity, you can use one of CCActionEase subclasses. Wrap your move action in one of them and you will see velocity changes during movement. Something like
id move_ease_in = [CCEaseIn actionWithAction:yourMoveAction rate:3.0f];
[player runAction: move_ease_in];
you can see few examples here

iPhone : How do I drag or move UIImage/UIButton as shown below?

I dont know How to get following type of functionality in my app.
As shown in above figure user can slide(drag) different image parts and user can assemble image.
Can any one tell me which control is this ? Or any tutorial for it ?
Check out the MoveMe sample app. It will show you how to allow movement of subviews by touch and drag.
You can then create imageViews for each of your puzzle pieces that can be moved around.
Once you have accomplished this you need to check during movement of a piece to see when it gets close enough to it's correct spot in the puzzle so it can snap into place when then user lets go of the piece.
http://developer.apple.com/library/ios/#samplecode/MoveMe/Introduction/Intro.html
That all depends on the kind of implementation you want to do.
It can be UIImageView,UIbutton etc.
The advantage with UIIMageView could be you can easily implement UIGestureRecognizer to move the views..
For an app I built I used the touches functions:
- (void) touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event
- (void) touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event
- (void) touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event
for dragging UIImageViews around. Then you can use the CGRectContainsRect or CGRectContainsPoint to detect if the puzzle piece is in the right location.
If we talk about UIKit,
this could be a UIImageView with images having partial transparent areas.
My first attack on this problem would be as follows:
(1) subclass UIImageView to hold each piece of the puzzle.
(2) Customize your UIImageView subclass by initializing it with a UIPanGestureRecognizer. Something like:
self.panRecognizer = 
  [[UIPanGestureRecognizer alloc] 
    initWithTarget: self 
    action: #selector(handlePan:)];
[self addGestureRecognizer: 
  self.panRecognizer];
(3) In the action method associated with the pan gesture recognizer, update the object's location based on messages from the puzzle piece's pan gesture recognizer. Something like the following ought to work:
-(void) handlePan: 
  (UIGestureRecognizer *)sender
{
  UIPanGestureRecognizer *panRecognizer = 
    (UIPanGestureRecognizer *)sender;
  if (panRecognizer.state == 
        UIGestureRecognizerStateBegan ||
      panRecognizer.state == 
        UIGestureRecognizerStateChanged)
  {
    CGPoint currentPoint = 
      self.center;
    CGPoint translation = 
      [panRecognizer translationInView: 
        self.superView];
    self.center = CGPointMake
      (currentPoint.x + translation.x, 
        currentPoint.y + translation.y);
    [panRecognizer setTranslation: CGPointZero 
      inView: self.superView];
  }
}
This is not that easy. You need to write the code first for how to move the image views. There are a lot of samples in Apple references. Then you need to get the boundaries of each image to do this.
Here is the code how to move imgTest which is an UIImageView. Tested, work like a charm.
[[self imgTest]setUserInteractionEnabled:YES];
//Save the first touch point
CGPoint firstTouchPoint;
//xd,yd destance between imge center and my touch center
float xd;
float yd;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch* bTouch = [touches anyObject];
if ([bTouch.view isEqual:[self imgTest]]) {
firstTouchPoint = [bTouch locationInView:[self view]];
xd = firstTouchPoint.x - [[bTouch view]center].x;
yd = firstTouchPoint.y - [[bTouch view]center].y;
}
}
{
UITouch* mTouch = [touches anyObject];
if (mTouch.view == [self imgTest]) {
CGPoint cp = [mTouch locationInView:[self view]];
[[mTouch view]setCenter:CGPointMake(cp.x-xd, cp.y-yd)];
}
}
source

Jittery movement when using CGAffineTransformMakeRotation

I'm having a problem with a jumping movement with using CGAffineTransformMakeRotation. It seems to work fine until I get to the top of quadrants 1 and 2. Below is the code I am using and youtube link that shows what happens. Any insight would be really appreciated.
My goal is to rotate a UIWebView with an svg inside. Since I can't easily detect touch on the UIWebView alone, I'm putting a blank UIImageView over it. This allows me to detect the touch and prevent the copy dialog from popping up.
http://www.youtube.com/watch?v=x_OmS0MPdEE&feature=youtu.be
- (void)touchesMoved: (NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
NSArray *allTouches = [touches allObjects];
CGPoint location = [[allTouches objectAtIndex:0] locationInView:self.view];
if(selected == 1) {
CGFloat rads = atan2f(location.y - (grid1.frame.size.height/2),location.x - (grid1.frame.size.width/2));
grid1.transform = grid1Btn.transform = CGAffineTransformMakeRotation(rads);
}
}
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
NSArray *allTouches = [touches allObjects];
CGPoint location = [[allTouches objectAtIndex:0] locationInView:self.view];
if(CGRectContainsPoint(grid1Btn.frame, location))
{
selected = 1;
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
selected = -1;
}
You use some frame.size.* in your computations. Note, that those values (unlike bounds.size.*) are affected by transform. Use grid1.center instead. It is also more logical (you rotate around center).
The next thing you need to fix is that it should not jump to new position when touches start :)
The jerkiness is caused by the inherent inaccuracy of touch event locations.
Touch events that are located sufficiently close to the center of the frame have a high likelihood of straying to the diagonally opposite quadrant of the frame whilst a circle is being traced about the center of the frame.
This will result in a sudden jump of 90 degrees as observed in your video.
One way to avoid the problem is to introduce a dead zone about the center of the frame. Any touch that is located within a given radius of the center of the frame would not trigger the rotation to be recalculated.
Hope this helps.

Smoothly drag a Sprite in cocos2d - iPhone

I have implemented a drag on a sprite object as follows..
-(BOOL)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * touch = [touches anyObject];
CGPoint location = [[Director sharedDirector] convertCoordinate: [touch locationInView:touch.view]];
[diskSprite setPosition:ccp(location.x , location.y )];
return kEventHandled;
}
but this dragging is not smooth.....
when i drag fast with my thumb the object left from the path.
Thanks
Probably a little bit late but I was searching for a similar thing.
I found this great Tutorial which explained everything:
http://www.raywenderlich.com/2343/how-to-drag-and-drop-sprites-with-cocos2d
- (void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
CGPoint oldTouchLocation = [touch previousLocationInView:touch.view];
oldTouchLocation = [[CCDirector sharedDirector] convertToGL:oldTouchLocation];
oldTouchLocation = [self convertToNodeSpace:oldTouchLocation];
CGPoint translation = ccpSub(touchLocation, oldTouchLocation);
CGPoint newPos = ccpAdd(mySpriteToMove.position, translation);
mySpriteToMove.position = newPos;
}
I had this same issue with my game. Dragging operations appeared jerky. I believe the reason is that touch events aren't generated fast enough to give a smooth appearance.
To solve the problem I smoothed the motion out by running an action on the sprite toward the desired location, instead of setting the position immediately.
I'm not exactly sure what you mean by "the object left from the path". I suppose what you mean is that if you drag your finger over the screen in an arc or circle, that the sprite will "jump" from point to point, instead of follow your finger precisely. Is this correct?
If you want your sprite to follow an exact path, you will have to create a path and then set the sprite to follow it. What you do now is simply set the sprite's position to the touch position, but a "dragged" touch will not create an event for every pixel it touches.
It is fairly easy to create a path for touches received, and code samples can be found here and there. However, if the sprite's speed (in pixels per frame) is too high, you will always see it "jump", even if you use a smooth path.
Example:
You can animate a sprite over a circular path. If you animate this to complete the path in 1 second, you will likely see smooth animation. But if it runs at a high speed, like a full circle in 4 frames, you will just see your sprite at 4 places, not in a smooth circle.
If you wish to 'correct' that, you will need to look into blending, or determine what the maximum speed is for acceptable motion, and slow your sprite down when it's too fast.
I hope that answers your question. If it's not clear, feel free to edit your question, or add a comment to my answer.
look here, what I suggest you to try in such case:
-(void)ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event {
if (_binCaptured) {
CGPoint location = [self convertTouchToNodeSpace:touch];
[_sprite stopAllActions];
id move = [CCEaseIn actionWithAction:[CCMoveTo actionWithDuration:0.1 position:ccp(location.x, _sprite.position.y)]];
[_sprite runAction:move];
}
}
And it really work smoothly.
I enjoyed this easy way.

Detect touch *anywhere on the screen* in cocos2d?

I'm really sorry, I realize there have been several questions asked about cocos2d touch detection (including this answer which helped me a bunch), but I just can't get any of them to work. I would have commented on the answer I linked instead of asking my own question, but i don't have enough rep to leave comments.
All I want to do is stop animation as soon as a user taps anywhere on the screen.
Here's my code so far:
- (BOOL)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"Touches Began");
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView: [touch view]];
location = [[Director sharedDirector] convertCoordinate: location];
CGRect mySurface = (CGRectMake(100, 100, 320, 480));
if(CGRectContainsPoint(mySurface, location)) {
NSLog(#"Event Handled");
return kEventHandled;
[[Director sharedDirector] stopAnimation];
}
return kEventIgnored;
NSLog(#"Event Ignored");
}
I've tried both BOOL and void, ccTouchesBegan and touchesBegan, in a layer file and a cocosNode file, and many other things. Nothing happens. Nothing shows in the log, and the animation continues on its merry little way. What am I doing wrong?
The main problem is that you've got the [[Director sharedDirector] stopAnimation]; after the return kEventHandled; rather than before it. return exits the function as soon as it's called, so anything after it will never get reached.
I don't have my mac in front of me to check the rest of your code, but it seems fine, so I'm guessing that's the main problem. If you're not even seeing the NSLog(#"Touches Began"); then you need to make sure that you're doing this in a CocosNode that extends Layer.
Another useful thing(once you're seeing the touches) is the NSStringFromCGPoint function, which allows you to easily display and debug the values in a CGPoint, so you could do something like:
NSLog(#"This layer was touched at %#", NSStringFromCGPoint(location));