odd behavior when transition of different scenes - ios

I hope to make some custom picture(e.x some logo and information of the game developer)before game is launched.In the cocos2d temple,there is only a IntroLayer to show logo,so I decide to add more scene to display other information before entering the main menu of the game.In IntroLayer.h
//this is the template code
#interface IntroLayer : CCLayer
{
}
+(CCScene *) scene;
#end
//this is the new scene,I hope to display after the IntroLayer
#interface SecondScene : CCLayer
{
}
+(CCScene*) scene;
#end
//In IntroLayer.m
#implementation IntroLayer
//I change the replaceScene function from [HelloWorldLayer node] to[SecondScene scene]
-(void) onEnter
{
[super onEnter];
[[CCDirector sharedDirector] replaceScene:
[CCTransitionFade transitionWithDuration:1.0 scene:[SecondScene scene]]];
}
#end
#implementation SecondScene
+(CCScene*)scene
{
CCScene *scene = [CCScene node];
SecondScene *layer = [SecondScene node];
[scene addChild:layer];
return scene;
}
-(id)init
{
if (self = [super init]) {
CGSize size = [[CCDirector sharedDirector] winSize];
CCSprite *background = [CCSprite spriteWithFile:#"LOGO.png"];
background.position = ccp(size.width/2, size.height/2);
[self addChild: background];
}
return self;
}
//I hope the main game scene display after the SecondScene
-(void)onEnter{
[[CCDirector sharedDirector] replaceScene:
[CCTransitionFade transitionWithDuration:1.0 scene:[HelloWorldLayer scene]]];
[super onEnter];
}
#end
But when I run this code,I found it doesn't run as I expected.The SecondScene and the HelloWorldLayer display nearly at the same time,actually at last there is only SecondScene left in the screen and the HelloWorldLayer quickly disappear.I am really confused with that.Can anyone give some advice?Really Thanks for that.

If you want the second transition to follow the first, you need to override the onEnterTransitionDidFinish method:
-(void)onEnterTransitionDidFinish{
[super onEnterTransitionDidFinish];
[[CCDirector sharedDirector] replaceScene:
[CCTransitionFade transitionWithDuration:1.0 scene:[HelloWorldLayer scene]]];
}

Related

Touch event Cocos2d iPhone

I have doubts about touch event in cocos2d, in particular:
I have two layers:
GameLayer.m
-(id)init
{
if(self=[super init])
{
NSLog(#"GAME");
CCSprite*game=[CCSprite spriteWithFile:#"alien.png"];
CGSize size=[CCDirector sharedDirector].winSize;
self.contentSize=CGSizeMake(50,50);
self.touchEnabled=YES;
game.position=CGPointMake(40,40);
[self addChild:game];
//NSLog(#"%d",[[self children] count]);
//NSLog(#"%f",self.position.x);
}
return self;
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"GAME");
}
UserInterfaceLayer.m
-(id)init
{
if(self=[super init])
{
NSLog(#"USER");
self.touchEnabled=YES;
CCSprite*game=[CCSprite spriteWithFile:#"spiders.png"];
CGSize size=[CCDirector sharedDirector].winSize;
self.contentSize=CGSizeMake(20,20);
game.position=CGPointMake(40,40);
[self addChild:game];
//NSLog(#"%d",[[self children] count]);
//NSLog(#"%f",self.position.x);
}
return self;
}
-(void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(#"USER");
}
Both are children of one scene:
MultiLayerScene.m
-(id)init
{
if(self=[super init])
{
sharedMultiLayerScene = self;
self.contentSize=CGSizeMake(30, 30);
CGSize size=[CCDirector sharedDirector].winSize;
// The GameLayer will be moved, rotated and scaled independently
GameLayer* gameLayer = [GameLayer node];
gameLayer.position=CGPointMake(250,250);
[self addChild:gameLayer z:1 tag:1];
//gamelayerposition = gameLayer.position;
// The UserInterfaceLayer remains static and relative to the screen area.
UserInterfaceLayer* uiLayer = [UserInterfaceLayer node];
uiLayer.position=CGPointMake(-100, -100);
[self addChild:uiLayer z:-1 tag:2];
}
return self;
}
My problem is that I touch on screen at any position their ccTouchesBegan event run.
For example if I touch only on GameLayer runs both the GameLayer touches event and the other.
I try also to insert the two layer in two different position(as you can see from the code) , but the problem still persist.
How Do I resolve this problem?
I would like ,for example,if I touch on Gamelayer respond only its touch event.
Try this
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
Priority: lower number = higher priority.

How can I make sprite universal in Cocos2d iOS for garbage cleanup?

I'm currently learning Cocos2D and I can't figure out how to access my sprite '_imgStudio' to make it universal so I can clean it up the image after my "removeStudio" timer finishes. I'd like to be able to move both the CCSprite draw functions into the spawnStudio function and to kill it once the timer finishes running.
However, I get an error saying 'Use of undeclared identifier '_imgStudio' so my removeStudio timer right now is pretty much useless.
Here's part of my helloWorldFile.
#implementation GameEngine
+(CCScene *) scene
{
CCScene *scene = [CCScene node];
GameEngine *layer = [GameEngine node];
[scene addChild: layer];
return scene;
}
#pragma mark Main Initializer
//Initalizes GameSetup
-(id) init
{
if( (self=[super init]) ) {
NSLog(#"Game Setup Worked!");
CGSize winSize = [CCDirector sharedDirector].winSize;
CCSprite *_imgStudio = [CCSprite spriteWithFile:#"Studio~ipad.png"];
_imgStudio.opacity = 0;
_imgStudio.position = ccp(winSize.width/2, winSize.height/2);
[_imgStudio runAction:[CCFadeTo actionWithDuration:2.5f opacity:255]];
[self addChild:_imgStudio];
[self scheduleOnce: #selector(spawnStudio:) delay:10];
[self scheduleOnce: #selector(removeStudio:) delay:20];
}
return self;
}
-(void) spawnStudio: (ccTime) dt {
NSLog(#"TEST");
}
-(void) removeStudio: (ccTime) dt {
[_imgStudio removeFromParentAndCleanup:YES];
NSLog(#"ImageRemoved");
}
Thanks!

Not accessing function in Objective-C

I'm currently trying to access a function on another file.(another layer, to be more precise).
Both layers are on a scene.
Third layer is trying to get a function from first layer...
Here's how I'm doing this:
Here's my scene in scene.h
#import "firstLayer.h"
#import "secondLayer.h"
#import "thirdLayer.h"
#interface myScene : CCScene
{
// custom instance vars here...
}
#end
Here's how I cast my scene in scene.m
-(id)init {
self = [super init];
if(self != nil){
firstLayer *firstLayerz = [firstLayer node];
[firstLayerz setTag:111];
[self addChild:firstLayerz z:0];
secondLayer *secondLayerz = [secondLayer node];
[secondLayer setTag:112];
[self addChild:secondLayer z:2];
thirdLayer *thirdLayerz = [thirdLayer node];
[thirdLayerz setTag:113];
[self addChild:thirdLayerz z:4];
Here's how I cast the function in thirdLayer.m
#import "scene.h"
#implementation thirdLayer.m
-(id)init {
self = [super init];
if(self != nil){
firstLayer* firstLayerz = (firstLayer*)[self.parent getChildByTag:111];
[firstLayerz functionNeeded];
}
Here's functionNeeded in firstLayer.m (right below init(
-(void)functionNeeded {
NSLog(#"inside fnnction needed");
}
Of course the log ain't showing...
I do the proper cast in firstLayer.h
#interface firstLayer : CCLayer {
}
-(void)functionNeeded;
#end
In your firstLayer's init method write
self.tag = 111;
Now in your ThirdLayer where you want to call method of first layer write :
CCScene *current = [[CCDirector sharedDirector] runningScene];
if (current) {
id layer = [current getChildByTag:111];
if (layer) {
[layer functionNeeded];
}
}

Linking HUDLayer to GameplayLayer properly

I'm trying to pass the touch location from GameplayLayer to HUDLayer to see if user presses control buttons.
HudLayer.mm
-(void) handleTouchAtLocation:(CGPoint) location {
NSLog(#"Touch passed to HUD");
}
Gameplay.mm
enum {
kHudLayer = 2;
};
+(CCScene *) scene {
CCScene *scene = [CCScene node];
HudLayer *hud = [HudLayer node];
[scene addChild:hud z:kHudLayer];
GameplayLayer *layer = [GameplayLayer node];
[scene addChild:layer];
return scene;
}
-(void) ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for( UITouch *touch in touches ) {
CGPoint location = [touch locationInView: [touch view]];
location = [[CCDirector sharedDirector] convertToGL: location];
[self handTouchAtPoint:(location)];
}
}
-(void) handleTouchAtPoint:(CGPoint)location {
NSLog(#"Touch At Point");
HudLayer *h1 = (HudLayer *)[self.parent getChildWithTag:kHudLayer];
[h1 handleTouchAtLocation:location];
}
HudLayer.h is imported in GameplayLayer.h.
I'm getting the "Touch At Point" log but it's not going through to HUD layer for some reason..
The only explanation is that self.parent has no child with the tag kHudLayer. If you set a breakpoint in handleTouchAtPoint you'll notice h1 being nil after the getChildWithTag line did execute.

Touch location CCLayer

*Working Code Now*
OK, I thought that this would be easy to get working but it turns out to not work like I expected.
I am trying to get the Touch location from a CCLayer that can be moved or zoomed, not the location on the screen itself? here is how I thought that it would work but it crashes?
Interface
#import "cocos2d.h"
#interface TestTouch : CCLayer {
CCLayerColor *layer;
}
+(CCScene *) scene;
#end
Implementation
#import "TestTouch.h"
#implementation TestTouch
+(CCScene *) scene
{
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
TestTouch *layer = [TestTouch node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
- (id)init
{
self = [super init];
if (self) {
CGSize winsize = [[CCDirector sharedDirector]winSize];
CCLayerColor *layer = [CCLayerColor layerWithColor:ccc4(255, 255, 255, 255)];
// layer.scale = 0.7f;
layer.contentSize = CGSizeMake(640, 960);
layer.position = CGPointMake(winsize.width/2, winsize.height/2);
layer.isRelativeAnchorPoint = YES;
[self addChild:layer z:0];
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:layer priority:0 swallowsTouches:YES];
}
return self;
}
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchStart = [[CCDirector sharedDirector] convertToGL:[touch locationInView:[touch view]]];
touchStart = [layer convertToNodeSpace:touchStart];
NSLog(#"Touch:%f,%f",touchStart.x, touchStart.y);
return YES;
}
#end
If I change this line to include "self":
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
It will obviously work but then I get the location relevant to the screen and not the layer, which is what I need.
You need to convert the location on the screen to the layer's "node space":
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchStart = [[CCDirector sharedDirector] convertToGL:[touch locationInView:[touch view]]];
// convert touch location to layer space
touchStart = [self convertToNodeSpace:touchStart];
NSLog(#"Touch:%f,%f",touchStart.x, touchStart.y);
return YES;
}

Resources