





















































In this article by Ben Trengrove, author of the book Cocos2D Game Development Essentials, we will see how can we update our sprite position according to the touch movement.
(For more resources related to this topic, see here.)
Very often in development with Cocos2d you will want the ability to drag a node around the screen. It is not a built in behavior but it can be easily coded. To do it you will need to track the touch information. Using this information you will move the sprite to the updated position anytime the touch moves.
@interface HelloWorldScene ()
@property (nonatomic, assign) BOOL dragging;
@end
-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchLoc = [touch locationInNode:self];
if (CGRectContainsPoint(_sprite.boundingBox, touchLoc)) {
self.dragging = YES;
NSLog(@"Start dragging");
}
}
- (void)touchMoved:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchLoc = [touch locationInNode:self];
if (self.dragging) {
_sprite.position = touchLoc;
}
}
- (void)touchEnded:(UITouch *)touch withEvent:(UIEvent *)event {
self.dragging = NO;
}
@property (nonatomic, assign) CGPoint dragOffset;
-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchLoc = [touch locationInNode:self];
CGPoint touchOffset = [touch locationInNode:_sprite];
if (CGRectContainsPoint(_sprite.boundingBox, touchLoc)) {
self.dragging = YES;
NSLog(@"Start dragging");
self.dragOffset = touchOffset;
}
}
Notice that using the locationinnode method, you can calculate the position of the touch relative to the node. This information is only useful if the touch was indeed inside of the node so you only store it if that is the case.
- (void)touchMoved:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchLoc = [touch locationInNode:self];
//Check if we are already dragging
if (self.dragging) {
CGPoint offsetPosition = ccpSub(touchLoc, self.dragOffset);
//Calculate an offset to account for the anchor point
CGPoint anchorPointOffset = CGPointMake(_sprite.anchorPoint.x * _sprite.boundingBox.size.width, _sprite.anchorPoint.y * _sprite.boundingBox.size.height);
//Add the offset and anchor point adjustment together to get the final position
CGPoint positionWithAnchorPoint = ccpAdd(offsetPosition, anchorPointOffset);
_sprite.position = positionWithAnchorPoint;
}
}
The offset position is subtracted from the touch location using the Cocos2d convenience function ccpSub. CcpSub subtracts a point from another point.
For reference, here is the complete scene.
@interface HelloWorldScene ()
@property (nonatomic, assign) BOOL dragging;
@property (nonatomic, assign) CGPoint dragOffset;
@end
- (id)init
{
// Apple recommend assigning self with supers return value
self = [super init];
if (!self) return(nil);
// Enable touch handling on scene node
self.userInteractionEnabled = YES;
// Create a colored background (Dark Grey)
CCNodeColor *background = [CCNodeColor nodeWithColor:[CCColor colorWithRed:0.2f green:0.2f blue:0.2f alpha:1.0f]];
[self addChild:background];
// Add a sprite
_sprite = [CCSprite spriteWithImageNamed:@"Icon-72.png"];
_sprite.position = ccp(self.contentSize.width/2,self.contentSize.height/2);
_sprite.anchorPoint = ccp(0.5, 0.5);
[self addChild:_sprite];
// Create a back button
CCButton *backButton = [CCButton buttonWithTitle:@"[ Menu ]" fontName:@"Verdana-Bold" fontSize:18.0f];
backButton.positionType = CCPositionTypeNormalized;
backButton.position = ccp(0.85f, 0.95f); // Top Right of screen
[backButton setTarget:self selector:@selector(onBackClicked:)];
[self addChild:backButton];
// done
return self;
}
// -----------------------------------------------------------------------
#pragma mark - Touch Handler
// -----------------------------------------------------------------------
-(void) touchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchLoc = [touch locationInNode:self];
CGPoint touchOffset = [touch locationInNode:_sprite];
if (CGRectContainsPoint(_sprite.boundingBox, touchLoc)) {
self.dragging = YES;
NSLog(@"Start dragging");
self.dragOffset = touchOffset;
}
}
- (void)touchMoved:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchLoc = [touch locationInNode:self];
if (self.dragging) {
CGPoint offsetPosition = ccpSub(touchLoc, self.dragOffset);
CGPoint anchorPointOffset = CGPointMake(_sprite.anchorPoint.x * _sprite.boundingBox.size.width, _sprite.anchorPoint.y * _sprite.boundingBox.size.height);
CGPoint positionWithAnchorPoint = ccpAdd(offsetPosition, anchorPointOffset);
_sprite.position = positionWithAnchorPoint;
}
}
- (void)touchEnded:(UITouch *)touch withEvent:(UIEvent *)event {
self.dragging = NO;
}
In this article, we saw how to update your sprite position according to the touch movement.
Further resources on this subject: