Cocos2d adding a background image to a layer? - iphone

I just finished reading some of the cocos2d documentation, and as far as I understand to add a background image to a layer you have to do something like:
Sprite * bg = [Sprite spriteWithFile:#"Background.png"];
[layer addChild:bg z:0];
Allthough as far as my testing goes you can just directly add the sprite to the scene like this:
#implementation IntroScene
- (id) init {
self = [super init];
if (self != nil) {
Sprite * bg = [Sprite spriteWithFile:#"Background.png"];
[bg setPosition:ccp(240, 160)];
[self addChild:bg z:0];
[self addChild:[MenuLayer node] z:1];
}
return self;
}
What is the difference between this 2 options, and what is the better way to set a background for a layer?. Any help will be greatly appreciated.

You do not need to have a layer, but they are handy. Think of the layers as a way of grouping sprites (both visually and organizationally). You may want your background images grouped as a layer and all the enemies in a game as another layer. This allows you to deal with each set more cleanly. e.g. You can remove a specific layer instead of finding all of the enemies and removing them.
If it helps, play with layers in Photoshop or a graphics editing program. Layers in cocos2d work similarly.
For a simple scene, adding the background to a layer or to a scene won't make much difference. But it doesn't take long before the benefits of layering kicks in.

Also layers control drawing order (over and above any inter-layer z ordering).
In geoSpark, for example, I have a background layer, a spark layer, a UI layer, etc. (Simplified). But this allows me to make sure my UI stuff is always above any game stuff (the spark layer) and all that is above the background.
If your game does only additive rendering, draw order won't matter much. :)
-- David

scene is a blackboard, layer is a page... news is wrote on page, but, if you want you can write on the board. If you want erase all new.

In cocos2d we can add any node on any node. But it depends on level of hierarchy.
You can add Layers on Scenes. If you want same property or look for all layers that you add on a CCScene you can add those in CCScene (as in your second case). but if you want to have different feature on each layer add those to CCLayer.
CCLayer is meant for grouping a set of nodes/sprites for some purpose. For example you can add a layer which includes options after pausing a game, or HUD layer for displaying som kind always on screen along with some scrolling layer (liken in some scrolling platform games).
Finally you can even CCNode on a CCScene, a layer on another layer, and even a CCNode on a CCSprite.
But the order of drawing in graphics context in cocos2d differs.
Hope you got the difference.
Good luck!

Related

Is it good choice to move a Sublayer around a view using UIPanGestureRecognizer?

I have a CALayer and as sublayer to this CALayer i have added an imageLayer which contains an image of resolution 276x183.
I added a UIPanGestureRecognizer to the main view and calculation the coordinates of the CALayer as follows:
- (void)panned:(UIPanGestureRecognizer *)sender{
subLayer.frame=CGRectMake([sender locationInView:self.view].x-138, [sender locationInView:self.view].y-92, 276, 183);
}
in viedDidLoad i have:
subLayer.backgroundColor=[UIColor whiteColor].CGColor;
subLayer.frame=CGRectMake(22, 33, 276, 183);
imageLayer.contents=(id)[UIImage imageNamed:#"A.jpg"].CGImage;
imageLayer.frame=subLayer.bounds;
imageLayer.masksToBounds=YES;
imageLayer.cornerRadius=15.0;
subLayer.shadowColor=[UIColor blackColor].CGColor;
subLayer.cornerRadius=15.0;
subLayer.shadowOpacity=0.8;
subLayer.shadowOffset=CGSizeMake(0, 3);
[subLayer addSublayer:imageLayer];
[self.view.layer addSublayer:subLayer];
It is giving desired output but a bit slow in the simulator. I have not yet tested it in Device. so my question is - Is it OK to move a CALayer containing an image??
Yes, it is OK to move a CALayer containing an image.
If all you want to do with the panning gesture is move the image, then instead of updating the whole frame, you should just update the layer's position property. Like thus:
- (void)panned:(UIPanGestureRecognizer *)sender {
subLayer.position=CGPointMake([sender locationInView:self.view].x, [sender locationInView:self.view].y);
}
Two things:
First, you can't draw ANY conclusions based on the performance of the simulator. Some things on the simulator are an order of magnitude faster than on a device, and other things are significantly slower. Animation is especially a mixed bag.
If you're doing performance-critical work, test it on the device, early and often.
Second, you can certainly animate a layer using a gesture recognizer, but that is an awfully round-about way to do it. Gesture recognizers are designed to work on views, and it's much easier and cleaner to tie the recognizer to a subview rather than a sub layer.
One of the big problems you will have with using a layer is hit-testing. If you let go of your image, then try to drag it some more, you'll have to have the gesture on the containing view, take the gesture coordinates and do hit testing on the layer. Ugh.
Take a look at the gesture based version of the touches sample app from Apple. It shows you how to cleanly move UIView objects around the screen using gestures.
Note that you can create a view that has custom layer content, and drag that around.

How to add transition effect in Current running scene in cocos2d iphone

How to add transition effect in Current running scene in cocos2d iphone. Means I am making a game and after each goal I want to give a fade effect or any type of effect on the current running scene.
If I write this, It replace current scene to its new scene. But I don't want to replace scene.
[[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:1.0f scene:[GamePage scene]]];
Is there some way to show effect on the current page like this. I know that it is wrong but I want something like this :
[self transitionEffect:[CCTransitionFade actionWithDuration:0.5]];
For Scene,Layer (Subclass of CCNode) action related to Opacity will not work. !
You can Either Use transition, or Must have to apply CCFadeTo to all of your sprite.
But If you are choosing to CCFadeTo to all sprites, this will require allocation of lots of actions suddenly ! FPS slow down !!
Another best approach:
Tell to your designer, to make 1 x 1 pixel Square black dot image.
Add this code at last in the init method.
CCSprite *temp=[CCSprite spriteWithFile:#"squaredotBlack.png"];
temp.position=ccp(s.w/2,s.h/2);
[self addChild:temp z:50000]; //set as most top layer
temp.scaleX=s.w;
temp.scaleY=s.h;
temp.opacity=0;
Then Apply, For "Fade out" process of whole screen, Increase the opacity.
temp.opacity=0;
[temp runAction:[CCFadeTo actionWithDuration:1 opacity:255]]; //0 to 255
Then Apply, For "Fade In" process of whole screen, decrease the opacity.
temp.opacity=255; // this will cover whole screen with black color
[temp runAction:[CCFadeTo actionWithDuration:1 opacity:0]]; //255 to 0
you can run an action on the entire CCLayer
[self runAction:[CCFadeOut actionWithDuration:0.5f]];
or you can use CCFadeTo to fade to a desired opacity.

How can I make a scrolling game using Cocos2D without a tile map?

I want to move the background when I tilt the iPhone so it will look like it is moving your character. So if I tilt it forward, my background will go backwards.
Use a CCParallaxNode.
Here is a good article / blog, about using CCParallaxNode in a 2d scrolling game. In this person's example, they are moving the background on every frame, but you could modify it to only move when tilting the iphone by using the UIAcceleration delegate.
Here is the link: here
In terms of how to handle accelerometer input: In the init method of your layer, add:
self.isAccelerometerEnabled = YES;
Then, implement the method:
-(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration
You can get the accelerometer values by doing
accX = acceleration.x; //etc...
Now in terms of the animation, there's a couple ways to do it. One way you could do it is just make a large image, add it to a layer, and then adjust its position based on accelerometer input. However, this is very memory inefficient and not ideal. Why are you so opposed to using tile maps? They are quite useful for what you have in mind. A good resource for an introduction to them is at: http://www.raywenderlich.com/1163/how-to-make-a-tile-based-game-with-cocos2d

how to create transparent ccscene in cocos2d?

I need to show ccscene on game pause. But it should be transparent. Can anyone please help me with this??
Thank you,
Anks
I suggest you should not create a separate scene for pause layer. What you can do is, create a layer similar to HUD Layer.
Second option would be going for something like this.Just dont set the background color of the layer.
Hope that helps.
I know you already have an answer, but wanted to share my solution because I hit this link when researching the same issue. I also posted this in the cocos2d forums.
- (void)pauseSchedulerAndActionsRecursive:(CCNode *)node {
[node pauseSchedulerAndActions];
for (CCNode *child in [node children]) {
[self pauseSchedulerAndActionsRecursive:child];
}
}
- (void)resumeSchedulerAndActionsRecursive:(CCNode *)node {
[node resumeSchedulerAndActions];
for (CCNode *child in [node children]) {
[self resumeSchedulerAndActionsRecursive:child];
}
}
I have one scene and two layers, a stage/gameplay layer and a menu layer. My menus animate in and out, and I wanted my pause menu to be able to animate in and out as well. So I just added the above functions to my stage/gameplay layer. Then when the user hits pause, I call pauseSchedulerAndActionsRecursive: on my stage/gameplay layer and add my menu layer to the scene on top. My menu swallows all the touches, so touching is also disabled on the stage/gameplay layer while the menu layer is up. Then just call resumeSchedulerAndActionsRecursive: method to resume. Hope this helps someone out.

iPhone Dev: Animating PNG Sequences

What is the best or recommended technique for animating PNG Sequences.
Heres what I've learned:
Do it Manually
Using MutableArrays containing Strings, you can animate a UIImageView with a timer which increments an index number
UIImage - animation methods
This works, the only problem is to find if an image has completed its animation, you have to check the isAnimating BOOL, and to do that you need a timer.
What is the best and recommended?
Looking to do Oldschool game sprite animations,
ie:
Idle Animation
Attack Animation
Walk Animation
ect...
Let me know if any one has something.
#lessfame
Example to animate arrows
UIImage* img1 = [UIImage imageNamed:#"fleche1.png"];
UIImage* img2 = [UIImage imageNamed:#"fleche2.png"];
NSArray *images = [NSArray arrayWithObjects:img1,img2, nil];
UIImageView* imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0, 0.0, 160.0, 160.0)];
[imageView setAnimationImages:images];
[imageView setAnimationRepeatCount:100];
[imageView setAnimationDuration:3.0];
imageView.center = myView.center;
[imageView startAnimating];
[myView addSubview:imageView];
[imageView release];
Easiest way is to use Core Animation layers to do sprite animation:
Make a 'multi-cell' image strip (could be PNG or JPG) of all the various moves for the sprite. Make each 'cell' be a fixed height or width.
Put the image in a UIImageView.
Take the CALayer of the view, and adjust the contentsRect property of the layer. This acts as a clipping rectangle for the sprite. To animate sprite all you have to do is move the contentsRect over to the next cell position in the image strip.
Something like this will do it (assuming you've already calculated the newSpritePosition.
[CATransaction begin];
[CATransaction setDisableActions:YES];
spriteLayer.contentsRect = newSpritePosition;
[CATransaction commit];
(If you don't do the second line, then you'll get a default slide animation instead of a 'jump' to the next state.)
With this technique you can rotate through all the frames of the sprite -- much like a flipbook. CALAyer transactions are optimized so you should get pretty fast frame rates. You can set an animationDidStop completion handler to move to the next state of the sprite or loop back to the beginning frame.
It depends on how you are going to use the sprites. If you just need a simple looping sprite then the UIImage method is great. If you want more granular control then you will be happier loading the images into an array and cycling them using a NSTimer to handle the timing. Personally I use the array method most often because it leaves me more options in the future (like detecting when animations have completed). One more suggestion would be to check out the cocos2d project. Its sprite is alot more powerful than either of these suggestions.
As I said in another answer, I found this to be a good way: PNG Animation method by Moses DeJong
From his words:
This example implements an animation oriented view controller that simply waits to read the PNG image data for a frame until it is needed. Instead of alllocating many megabytes, this class run in about a half a meg of memory with about a 5-10% CPU utilization on a 2nd gen iPhone.
I'm still unsure exactly how it's done. I believe it basically uses UIImageView to cache up AVAudioPlayer.