I wanted to go a bit more into the base classes of the framework. So far we’ve seen a bit of scenes and sprites. Let’s look at one of the most important base classes, CocosNode.
CocosNode is “the main element. Anything thats gets drawn or contains things that get drawn is a CocosNode.”
So Scene derives from CocosNode, as does Sprite, as do most of the other visual objects you’ll be dealing with. Think of it as DisplayObject in Flash. CocosNode has a static method called “node” which is basically a factory method returning a new CocosNode. Of course, Sprite’s node method will return a new Sprite, and Scene’s method will return a new Scene. We saw that in the last example when we said:
[c]Scene *scene = [Scene node];[/c]
Another important class in this structure is Layer. A layer is mainly a way to organize the objects in your scene. So you might have a background layer, an objects layer, a player layer, etc. Layers aren’t mandatory. You can add Sprites and other objects directly to a Scene, but they can certainly help organize things, especially when you start subclassing them. For example you could have an EnemiesLayer class that extends Layer. It has code to create and control enemy characters. You say something like:
[c][gameScene addChild:[EnemiesLayer node]];[/c]
Layers are also UIAccelerometerDelegates and TouchEventDelegates, whereas Scenes are not. So if you need accelerometer or touch data, you might want to create a Layer for that in your scene.
Now in the last example, we created a generic Scene and added a background image to it. Generally, that’s not the way you would do it. Again, a Scene represents a particular state of a game, so it would probably contain its own logic and graphics. Thus, you’d probably subclass Scene and add the background from within. Let’s do that.
Add a new file to the project in the Classes group. Choose NSObject subclass and name it MainScene. In the interface file, import Scene.h and have the class subclass Scene:
[c]#import <foundation/Foundation.h>
#import “Scene.h”
@interface MainScene : Scene {
}
@end[/c]
In the implementation file, import Sprite.h and cocos2d.h. Then add an init method, create the background sprite like before, and add it as a child to self:
[c]#import “MainScene.h”
#import “Sprite.h”
#import “cocos2d.h”
@implementation MainScene
– (id) init
{
self = [super init];
if (self != nil) {
Sprite *background = [Sprite spriteWithFile:@“background.png”];
background.position = ccp(240, 160);
[self addChild:background];
}
return self;
}
@end[/c]
Now that MainScene takes care of creating its own background, we can remove that code from the app delegate, and just create a MainScene instead of a generic Scene:
[c]- (void)applicationDidFinishLaunching:(UIApplication *)application {
window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[window setUserInteractionEnabled:YES];
[window setMultipleTouchEnabled:YES];
[[Director sharedDirector] setPixelFormat:kRGBA8];
[[Director sharedDirector] setDeviceOrientation:CCDeviceOrientationLandscapeLeft];
[[Director sharedDirector] attachInWindow:window];
[window makeKeyAndVisible];
MainScene *mainScene = [MainScene node];
[[Director sharedDirector] runWithScene:mainScene];
}[/c]
Don’t forget to import your new “MainScene.h” file.
Now that you have a custom scene, you could start adding other layers, objects, and logic to it.
Now let’s add a custom Layer. Let’s display some other non-fullscreen graphic in this layer. I’ve added another picture to my project called iphone.png. Create another NSObject subclass named PictureLayer, and have it extend Layer. Here’s the interface:
[c]#import <foundation/Foundation.h>
#import “Layer.h”
@interface PictureLayer : Layer {
}
@end[/c]
In the implementation, do the same thing we did with the scene’s background, but add this new picture insted:
[c]#import “PictureLayer.h”
#import “Sprite.h”
#import “cocos2d.h”
@implementation PictureLayer
– (id) init
{
self = [super init];
if (self != nil) {
Sprite *pic = [Sprite spriteWithFile:@“iphone.png”];
pic.position = ccp(240, 160);
[self addChild:pic];
}
return self;
}
@end[/c]
Now, back in MainScene, let’s create add this layer:
[c]- (id) init
{
self = [super init];
if (self != nil) {
Sprite *background = [Sprite spriteWithFile:@“background.png”];
background.position = ccp(240, 160);
[self addChild:background];
PictureLayer *pictureLayer = [PictureLayer node];;
[self addChild:pictureLayer];
}
return self;
}[/c]
You wind up with something looking like this:
I know, it’s not high art, but we got the mechanics down, so lets be happy with it!
So I didn’t get into motion yet, but I thought it was important to cover scenes and layers before we went any further. That’s it for today.