Layer or Scene? - cocos2d-iphone

Learning cocos2d/kobold2d and puzzled by the scenes and layers. As I understand a scene usually contains layers where the layers contain UI elements like buttons and all the logic.
My first project is based on the kobold2d helloworld example and there I see that the layer is subclassed from CCLayer instead of CCScene. While searching about this topic I saw the helloworld example is with the layer derived from CCScene. Anyway, why does the helloworld example not derive from CCScene while it apparently did before?
I looked at some other examples (doodle and pinball) and there also CCLayer is used and not CCScene.
Is there a definitive guide on scenes and layers? Does kobold2d promote using just layers or how should I look at this?
Regards,
Rob

In Kobold2D, if your first class derives from CCLayer instead of CCScene, Kobold2D silently wraps it in a CCScene object. That way you don't have to write the +(id) scene method anymore.
This is great for scenes that only use a single layer, less code to write. And you can still add more layers to the scene by adding them to the layer's parent (which is the scene): [self.parent addChild:..]
Btw, if your first class is indeed a CCScene class or it implements the +(id) scene method, then that scene is used.

Related

Cocos2d: the best way to compose an object that will contain several Sprites

I need to create an object that contains several sprites (2 for simplicity: the game object and its' shadow).
I need to compose them into the same class, so having the following questions:
what is the best ancestor class to the described one?
I used CCNode for this purpose. I overridden its draw method in the following way:
- (void)draw {
[super draw];
[_item draw];
[_itemShadow draw];
}
and suddenly found that need to change all other CCNode methods in the same way. For ex. change position, visible, etc. in order to change these properties in both Sprites my custom container aggregates:
#interface NBChecker : CCNode {
CCSprite *_item;
CCSprite *_itemShadow;
}
#end
There is the other way I see - to make both sprites parent property pointing to self. This should synchronise positions, visibility, etc. for these sprites.
Who has better ideas?
Would like to use aggregation and not sure I'm right in my thoughts.
Thanks!
Scrap the draw code. All you need to do is to add the two sprites as children of the CCNode subclass. Write your logic code in the CCNode subclass and have two ivars for each sprite for easier access (like you already have).
You don't need to draw the sprites yourself as long as they are part of the scene graph.
The sprites will move and rotate relative to their parent automatically. Move the node to move the sprites in unison, etc.

DIfference between a scene and a layer in cocos2d

can anyone please make me clear about the difference between a Scene & a Layer in COCOS2D. I am bugged up with this.
Buddy, it is very simple. Whenever you use COCOS2D, you will be having a class which extends Layer. And which you are going call from Main activity. So for one displayable screen, there can be only one layer. In the class(which extends Layer) can have any number of scenes. You can even set the dimensions for the individual scenes too. But, make sure that, you release the memory immediately after you switch from one scene to another... Enjoy... :)

Role of the Scene

What is the role of the scene in Cocos2d?
The scene instantiates layers, like for instance a GameEngineLayer, a HUDLayer, etc.
I guess the GameEngineLayer class can be identical between scenes, but there will of cause be different objects in different scenes.
In scene1 there may be one Santa, and one Rudolf, whereas in scene2 there are just two Santa. Shall scene1 instantiate a santa, and one rudolf and pass them in a list of game objects to its instance of the gameEngine? And scene two instantiate two santa following the same pattern?
Shall the scenes also pass a list of events down to their respective gameEngine instance with time stamped events? For instance that santa shall feed Rudolf after a one minute?
Is the responsibility of the scene to do these kind of things?
I've started with a cocos2d/box2d game one week ago, so I'm a beginner. I've read lots of examples, but they usually code everything in a HelloWorldLayer class. :)
Added example:
http://www.raywenderlich.com/4666/how-to-create-a-hud-layer-with-cocos2d
The scene is defined inside ActionLayer.mm. Why?? Why not have Scene1.m that instantiates the ActionLayer?
The only reason why there's a CCScene in cocos2d is because CCDirector requires it as the base class for methods like runWithScene and replaceScene. Other than that, CCScene, CCLayer and CCNode are virtually identical to each other.
You can give scenes, layers, nodes, sprites, etc. any role you want.
But typically the Scene assumes the role of the state manager of the currently active game objects (nodes). A common use case is to declare the scene a singleton so that any child node can access the scene's base methods, for example to send other unrelated nodes messages, or to check if the game is over, and so on.
For propagating events I'm in favor of passing events down, since there's no easy way to pass events up as there is in UIKit. However it depends on what kind of events and what type of design you prefer.
Whether Santa sends a message to Rudolf in order to feed it, or Rudolf frequently asking Santa whether it is has something to eat, is also up to you. There are pros and cons to both approaches.
The reason why many examples instantiate the CCScene object inside the CCLayer class is simply because of that requirement of Cocos2D having to have a scene. Personally I think it's a bad case of a bad example that has become a de facto standard over the years. It would have been better to always create a CCScene class, and inside that create all the layers and other nodes that you want. It would have made the relation between scenes and layers and other nodes more obvious. As it is, there's many many projects out there whose scene class simply does nothing but contain a single layer that runs all the code.

Can I layer a CCSprite between two CCTMXLayers?

I am making a top-down shooter that makes extensive use of TMX maps created with the "Tiled" application. Within my TMX map, I have a "Background" layer with floor tiles, which appears beneath my characters (CCSprites.)
I have another layer in the TMX file called "Foreground" which I would like to appear "above" my CCSprites, giving the illusion of them walking underneath various objects.
I tried using the vertexZ property of the CCNode class to do this:
CCTMXLayer *backgroundLayer = ...
CCSprite *spriteNode = ...
CCTMXLayer *foregroundLayer = ...
[backgroundLayer setVertexZ:1];
[spriteNode setVertexZ:2];
[foregroundLayer setVertexZ:3];
...but it turns out vertexZ actually alters the node's visual appearance within the openGL view. It effectively causes a CCNode to appear larger, or closer to the user when it has a higher vertexZ value. I don't want that- all I want is a sort of layers-of-an-impossibly-thin-cake effect, without any visual differences between the layers.
So I thought I would try altering the zOrder property of the nodes, like this:
[[backgroundLayer parent] reOrderChild:backgroundLayer z:1];
[[spriteNode parent] reOrderChild:backgroundLayer z:2];
[[foregroundLayer parent] reOrderChild:backgroundLayer z:3];
But I realized there's a fundamental problem with what I'm doing here, since my spriteNode is a direct child of the CCScene, but the background and foreground nodes are both children of my CCTMXTiledMap, which itself is a child of the CCScene.
So I'm basically trying to slip a CCSprite between two layers of the map, which, from the CCScene's perspective, are really just two parts of the same layer.
It seems I could create an additional instance of CCTMXTiledMap just to hold the foreground layer, but that also seems like overkill. My other thought was to create CCSprites to serve the same purpose, but it seems like there's got to be a better way.
Yes, I have used Tiled once very lightly and I do believe there is an option to add an Object Layer into your TMXTiledMap (Tiled -> Layer -> Add Object Layer...), then once imported into your build you can link up a CCSprite with the corresponding Object Layer you have created. I would post your question on the cocos2d forum, as people there are more experienced and equipped to answer this with examples.

Help Logically setting up Layers for Good Game Design (involving SpaceManager Physics, Music, and Game Logic)

Im in the middle of creating my first iPhone game - I have a background in OOP and in particular C++ so I had some questions with regards to how best to logically setup layers while maintaining functionality.
Currently I WANT for my game to have three main layers:
HUDLayer (All static objects on the screen are here - game controls, User score, pause button etc.)
PlayLayer (The Player, the main game loop and all of the game logic here)
Level Layer (The level images and the level physics objects that the player interacts with, and the background music specific to this level)
Notice I used the word WANT here - because for the life of me im constantly having to move logical objects around just to work within what appears to be Cocos2d's and spacemanagers structure.
Below are just some of the issues that I'm facing
I would like for my PlayLayer to be the scene thats loaded by the director - but if I do that then all of the HUDLayer objects get covered behind the PlayLayer, and dont stay in place like they should, hence the HUDLayer is my scene and I have had to do that just to make it work
I would like to play the background music (via simpleAudioEngine playBackgroundMusic) in the LEVEL layer because I want different levels to have different music. So far the ONLY way I have gotten background music to work is to have it in the TOP most layer i.e. in this case the HUDLayer
Because of the fact that I have to use an instance of the SpaceManagerCocos2d object to create physics bodies - it seems like my level layer has to be killed and just incorporated within my PlayLayer otherwise im having a nightmare of a time attempting to detect collisions between the player and the level.
Am I missing something very obvious here? is there a core understanding of layers that Im just not getting? More and more I feel like im being pushed by the framework to build the whole game inside of a single class and just to use layers as scenes.
Is anyone else having these problems? Am I approaching the architecture of the game wrong? Any help would really be appreciated.
Thanks in advance guys!
Well, each game is different. There are many good discussions on the cocos2d forums about architecture, some people prefer to use an MVC approach, some like using an Actor metaphor to contain physics objects, etc.
Here's my approach:
Use two CCLayer objects (GameLayer and HUDLayer) as child nodes of one CCScene (GameScene). These are the "view" objects.
Create a GameController singleton that can make changes to the game state (also stored in GameController, or in a separate file.) You could also subclass CCScene and call that your controller.
GameLayer is in charge of rendering the graphics of the game level and all actors in it; it also handles getting game input via touch events.
HUDLayer is placed at a higher z-index than the GameLayer and obviously has all of the CCSprite objects for the HUD and buttons.
Interaction between the HUDLayer and the GameLayer is managed via the GameController.
GameController does all of the state changing and game actions.
That's just my approach because it worked for my current game, and it by no means is the definitive answer.
I'd suggest that you look into using an Actor paradigm for your physics objects -- SpaceManager does a decent job, but you don't necessarily always want physics objects to extend CCSprite.