Cocos2D For iPhone Tutorial 3 – Moving Sprites

4 minute read

In our last tutorial, we covered making a sprite appear on the screen. In this tutorial, we will be moving a sprite across the screen by using a technique called “animation”. In animation, a succession of new positions are combined to give the illusion of movement. Think “Steamboat Willie”, the famous Walt Disney cartoon. It was created with thousands of drawings all strung together and played in quick succession. Similarly, we will set a new position for our sprite in every frame. This new position will be right next to the last, and when the app is opened, these frames containing the new positions will be played in quick succession. Unlike cartoons, however, this animation will only consist of the movement of a single static object.

YouTube Preview Image

To begin the coding process for animating our sprite, we must first have a sprite. We already did that in the last tutorial, so let’s simply work with that code. If you don’t already have it, go to the last tutorial and copy and paste the code into Xcode.

The things that we will need to add to our program in order to accomplish animation include a line that will call a method every frame, and the method that is called every frame.

#import "HelloWorldScene.h"
CCSprite *icon;
@implementation HelloWorld
+(id) scene
{
CCScene *scene = [CCScene node];
HelloWorld *layer = [HelloWorld node];
[scene addChild: layer];
return scene;
}
-(id) init
{
if( (self=[super init] )) {
icon = [CCSprite spriteWithFile:@"Icon.png"];
icon.position = ccp(300,200);
[self addChild:icon];
[self schedule:@selector(DoEveryFrame:)];
}
return self;
}
- (void) dealloc
{
[super dealloc];
}
-(void) DoEveryFrame: (ccTime)dt{
icon.position = ccp(icon.position.x + 150*dt, icon.position.y);
}
@end

 

[self schedule:@selector(DoEveryFrame:)];

This line will run the “schedule” method of the “self” object. When calling a method that is in the same class as the method you are working on, you use “self” instead of the name of your object to refer to the class. In this case, our class is CCLayer. The “schedule” method runs the method that is passed into it every frame. The method that we are passing into it is “DoEveryFrame.”

 

-(void) DoEveryFrame: (ccTime)dt{

icon.position = ccp(icon.position.x + 150*dt, icon.position.y);

}

This is the method “DoEveryFrame.” It requires that that the paramater “ccTime” be passed into it. The variable “dt” will be set equal to “ccTime” so that we can use it in our method code. ccTime will give us the difference in time from when the DoEveryFrame method was last called. The only line of code in our method is going to be the one that sets a new position for our sprite. It basically sets the position equal to the point with an x-coordinate that is the current x-coordinate plus 150 pixels times the difference in time since the last frame (usually fractions of a second), and a y-coordinate  that is the same as the current y-coordinate. The net effect is that our sprite will appear to slide right on our screen. The reason we use the difference in time is to make sure that the sprite moves 150 pixels a second no matter what the frame rate is.

If we run the program now, the cocos2d icon will appear on the screen and then slide to the right. It keeps on going even after it goes off the screen. The next thing we’re going to to is prevent it from going off screen by resetting its position to the left side of the screen once it’s reached the right side of the screen. We can do this with a simple if-else statement that essentially says “if the x-coordinate is greater than this value, then change the x-coordinate to this.”

#import "HelloWorldScene.h"
CCSprite *icon;
@implementation HelloWorld
+(id) scene
{
CCScene *scene = [CCScene node];
HelloWorld *layer = [HelloWorld node];
[scene addChild: layer];
return scene;
}
-(id) init
{
if( (self=[super init] )) {
icon = [CCSprite spriteWithFile:@"Icon.png"];
icon.position = ccp(300,200);
[self addChild:icon];
[self schedule:@selector(DoEveryFrame:)];
}
return self;
}
- (void) dealloc
{
[super dealloc];
}
-(void) DoEveryFrame: (ccTime)dt{
icon.position = ccp(icon.position.x + 150*dt, icon.position.y);
if (icon.position.x > 480+30) {
icon.position = ccp(-30, icon.position.y);
}
}
@end

 

if (icon.position.x > 480+30) {

icon.position = ccp(-30, icon.position.y);

}

This is the if-else statement. In plain English, it says “If the x-coordinate of the icon sprite is greater than 480 + 30, then set its  x-coordinate to -30 and leave the y-coordinate the same as it currently is.” The reason we chose 480 + 30 as the x-coordinate at which the position is reset is because the width of the screen is 480 pixels, and half the width of our sprite is 30 pixels. That way, the icon re-appears on the left side of the screen at the same time it disappears off the right side of the screen.

Upon running the above code, your sprite will move across the screen, re-appearing on the left side of the screen as it goes off the right side. I encourage you to mess around with the positions in the DoEveryFrame method. See if you can get the sprite to scroll vertically or even diagonally!

Leave a Comment