Dragging a sprite with cocos2d produces a lag - ios

I have the following piece of code to drag a sprite around the screen using cocos2D:
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
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([mySprite position], translation);
[mySprite setPosition:newPos];
}
The sprite is shown on the screen and I can drag it around the screen with my finger, but the sprite is slower than my finger lagging behind about a quarter of an inch.
What can I do to avoid this lag?
Thanks,
GA

Related

Drag a SKSpriteNode (follow your finger movements) with SKPhysics (collision)

Want to drag a SKSpriteNode (follow your finger movements) with SKPhysics (collision enabled)
2 failed solutions:
1)
a) Solution: Change the position of the SKSpriteNode
b) Problem: The SKSpriteNode will "magically" pass through a wall unexpectedly when user drags the spriteNode quickly through the wall (Physics seems not to work)
c) code:
#property (nonatomic) CGPoint translationBy;
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
[self selectNodeForTouch:positionInScene];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
CGPoint previousPosition = [touch previousLocationInNode:self];
CGPoint translation = CGPointMake(positionInScene.x - previousPosition.x, positionInScene.y - previousPosition.y);
[self panForTranslation:translation];
}
- (void)panForTranslation:(CGPoint)translation {
CGPoint position = [_selectedNode position];
if([[_selectedNode name] isEqualToString:PLAYER_NAME]) {
[_selectedNode setPosition:CGPointMake(position.x + translation.x, position.y + translation.y)];
}
}
2) After searching around here found this advice by #LearnCocos2D "When you use physics, stick to moving the physics body through force, impulse or changing the body velocity directly." So I tried:
a) Solution: Apply impulse on the sprite node.
b) Problem: The sprite node will keep on moving even if I didn't drag the sprite node. (Behaving like a floating boat. Expect it to act like a car once the drag is stopped the sprite node will stop; once drag begins it will follow the finger.)
c) Code:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
[self selectNodeForTouch:positionInScene];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
CGPoint previousPosition = [touch previousLocationInNode:self];
CGPoint translation = CGPointMake(positionInScene.x - previousPosition.x, positionInScene.y - previousPosition.y);
CGVector forceVector = CGVectorMake(translation.x, translation.y);
[self.player.physicsBody applyImpulse:forceVector];
//[self.player.physicsBody setVelocity:CGVectorMake(0, 0)];
}
-->>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
Updated:
From the comment:
"i) You could determine the distance of the node to the finger location, then set the velocity every update: so that it will exactly be on the finger's position the next frame. ii) If both finger and node position are identical this will cancel out any movement, otherwise the node will stick to your finger while performing all physics collisions and will continue to push objects between itself and the finger in cases where it is obstructed."
a) Question: How to disable flick?
b) Problem: The sprite node will move very far away with a minor (accidental) flick.
c) code:
#property (nonatomic) CGPoint translationBy;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
CGPoint previousPosition = [touch previousLocationInNode:self];
// 1) You could determine the distance of the node to the finger location,
CGPoint xyTranslation = CGPointMake(positionInScene.x - previousPosition.x, positionInScene.y - previousPosition.y);
if (fabsf(positionInScene.x - previousPosition.x) < kPlayerMovementThreshold) {
xyTranslation.x = 0;
}
if (fabsf(positionInScene.y - previousPosition.y) < kPlayerMovementThreshold) {
xyTranslation.y = 0;
}
self.translationBy = xyTranslation;
}
static const CGFloat kPlayerMovementSpeed = 55.0f;
static const CGFloat kPlayerMovementThreshold = 1.0f;
-(void)update:(CFTimeInterval)currentTime{
// ii) then set the velocity every update: so that it will exactly be on the finger's position the next frame.
CGFloat dx = self.translationBy.x*kPlayerMovementSpeed;
CGFloat dy = self.translationBy.y*kPlayerMovementSpeed;
CGVector velocityVector = CGVectorMake(dx,dy);
[self.player.physicsBody setVelocity:velocityVector];
}
What I do is make an SKNode, let's call it 'a', with a very small physics body attached to it. This new node is connected via an SKPhysicsJointSpring to the node I want to move, let's call that 'b'. The new node a tracks my finger movement, and the spring makes sure the target node b follows that. Because the node b is positioned using physics, the collision detection works as expected.

Sprite Kit: How to make a node "jump" and also move it left or right, dependant on node position and length of touch?

This is my first post so go easy haha.
I'm new to 'iOS' 'coding', 'Xcode' and 'spritekit'. I'm looking to make an image node "jump" a distance on the positive y-axis if I touch anywhere on the screen, although if I touch somewhere to the left or right if the image and hold for a certain time, it moves in the respective left or right direction, a distance respective to the length of the touch.
Not sure if that's very clear, but any help would be appreciated! Thanks!
You could move a node like this
In touchesEnded: or touchesBegan: method:
{
node.position.y += 50;
}
In order for sprite to move somewhere you could also use actions, there is a family of actions like moveTo action.
I would suggest picking upa tutorial or a book about sprite kit. Good site with free tutorials is raywenderlich.com
Please Try this code :
a sprite move : left/right according to your touch direction anywhere on screen
// CGPoint initialPos; // in .h file
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint touchPt = [touch locationInView:touch.view];
initialPos = [[CCDirector sharedDirector] convertToGL:touchPt];
}
-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch=[touches anyObject];
CGPoint currentPos=[myTouch locationInView:[myTouch view]];
currentPos=[[CCDirector sharedDirector] convertToGL:currentPos];
float diffX = currentPos.x - initialPos.x;
float diffY = currentPos.y - initialPos.y;
CGPoint velocity = ccp(diffX, diffY);
initialPos = currentPos;
[Sprite setPosition:ccpAdd([SmileBall position], velocity)];
}
- (void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *myTouch=[touches anyObject];
CGPoint currentPos=[myTouch locationInView:[myTouch view]];
currentPos=[[CCDirector sharedDirector] convertToGL:currentPos];
float diffX = currentPos.x - initialPos.x;
float diffY = currentPos.y - initialPos.y;
CGPoint velocity = ccp(diffX, diffY);
initialPos = currentPos;
[Sprite setPosition:ccpAdd([SmileBall position], velocity)];
}
a sprite jump up: according to your touch on screen
-(void) ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
CCSprite *RunningChar;
RunningChar=(CCSprite *)[self getChildByTag:10];
UITouch *touch = [touches anyObject];
CGPoint touchPt = [touch locationInView:touch.view];
touchPt = [[CCDirector sharedDirector] convertToGL:touchPt];
float radian = ccpToAngle(ccpSub(touchPt, prevPoint));
float degrees = CC_RADIANS_TO_DEGREES(radian);
if (degrees >= 22.5 && degrees <= 112.5) // for upward direction :). otherwise you can write only code without ant condition
{
CCJumpTo *jump=[CCJumpTo actionWithDuration:0.7 position:CGPointMake(RunningChar.position.x, 87) height:110 jumps:1];
[RunningChar runAction:seq];
}
else
{
}
}
Try this :)

move Sprite with touches moved

i am moving a sprite using the touches moved method. currently the sprite jumps to the point on which the screen is touched but I want the sprite only to move when it is touched directly.
my code:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint location = [touch locationInNode:self];
CGPoint newPosition = CGPointMake(location.x, self.size.height/2);
self.sprite.position = newPosition;
}
}
check if the touch location is inside the sprite, like this:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint positionInScene = [touch locationInNode:self];
if(CGRectContainsPoint(self.sprite.boundingBox,positionInScene)) {
CGPoint newPosition = CGPointMake(positionInScene.x, self.size.height/2);
self.sprite.position = newPosition;
}
}

Moving a sprite by touching anywhere on the screen

In my game only one sprite responds to touches. How can I make a mousejoint move this sprite/body regardless of where I touch on the screen?
- (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL:location];
mySprite.position = location;
}
Make sure in your initmethod that self.isTouchEnabled = YES;

CCSprite rotation like Car Steering in Cocos2D

Is there any way to rotate a CCSprite to behave like a car Steering?If i release my touch with the CCSprite,it should automatically return to its original position in a smooth way exactly like a steering!Im using the below code,
-(void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch=[touches anyObject];
//acquire the previous touch location
CGPoint firstLocation = [touch previousLocationInView:[touch view]];
location = [touch locationInView:[touch view]];
CGPoint touchingPoint = [[CCDirector sharedDirector] convertToGL:location];
CGPoint firstTouchingPoint = [[CCDirector sharedDirector] convertToGL:firstLocation];
CGPoint firstVector = ccpSub(firstTouchingPoint, Steering.position);
CGFloat firstRotateAngle = -ccpToAngle(firstVector);
CGFloat previousTouch = CC_RADIANS_TO_DEGREES(firstRotateAngle);
CGPoint vector = ccpSub(touchingPoint, Steering.position);
CGFloat rotateAngle = -ccpToAngle(vector);
CGFloat currentTouch = CC_RADIANS_TO_DEGREES(rotateAngle);
dialrotation+=currentTouch-PreviousTouch;
sprite.rotation=dialrotation;
}
This rotates my CCSprite Smoothly,but i don't know how to return back to its original position like Car Steering.Is there any way to do so in Cocos2D?
In ccTouchesBegan method store the value of sprite.rotation somewhere, in ccTouchesEnded run CCRotateTo action on your sprite using this stored value.

Resources