I am trying to simulate a modal view in cocos2d by displaying a few sprites over my scene and showing a menuitemsprite as a continue button. In the code below, i show my game over modal and have the menu set up with a CCMenuItemSprite; which does not respond to touches, and a CCMenuItemImage; which does work.
-(void) gameOver {
CGSize size = [[CCDirector sharedDirector] winSize];
self.menu.isTouchEnabled = NO;
CCLayer *modalLayer = [[CCLayer alloc] init];
[self addChild:modalLayer z:20];
CCSprite *spriteGameOver = [CCSprite spriteWithFile:#"game_over.png"];
spriteGameOver.position = ccp( size.width/2,size.height/2);
CCLabelTTF *lblGameOver = [CCLabelTTF labelWithString:[NSString stringWithFormat:#"Game Over!\nScore %d/%d",numCorrect,questionIdx] dimensions:CGSizeMake(380, 300) alignment:CCTextAlignmentCenter fontName:#"Trebuchet MS" fontSize:50.0f];
// position the label on the center of the screen
lblGameOver.position = ccp(size.width/2-200, size.height/2-100);
lblGameOver.color = ccc3(20, 20, 20);
lblGameOver.opacity = 0;
// add the label as a child to this Layer
[spriteGameOver addChild: lblGameOver];
spriteGameOver.opacity = 0;
[modalLayer addChild:spriteGameOver];
CCSprite *spriteGameOverBtn = [CCSprite spriteWithFile:#"mainButton.png" rect:CGRectMake(0,0,300,60)];
spriteGameOverBtn.position = ccp( size.width/2,size.height/2-100);
CCLabelTTF *lblGameOverBtn = [CCLabelTTF labelWithString:#"Continue" dimensions:CGSizeMake(300, 60) alignment:CCTextAlignmentCenter fontName:#"Trebuchet MS" fontSize:40.0f];
//lblGameOverBtn.position = ccp(size.width/2-200, size.height/2-300);
[lblGameOverBtn setAnchorPoint:ccp(0.0f,0.1f)];
lblGameOverBtn.color = ccc3(20, 20, 20);
lblGameOverBtn.opacity = 0;
// add the label as a child to this Layer
[spriteGameOverBtn addChild: lblGameOverBtn];
spriteGameOverBtn.opacity = 0;
CCMenuItemImage *itemH = [CCMenuItemImage itemFromNormalImage:#"backArrow.png" selectedImage:#"backArrowS.png" target:self selector:#selector(goToMain:)];
itemH.position = ccp( size.width/2,size.height/2-100);
CCMenuItemSprite *mGameOverBtn = [CCMenuItemSprite itemFromNormalSprite:spriteGameOverBtn selectedSprite:nil disabledSprite:nil target:self selector:#selector(goToMain:)];
CCMenu *menuGO = [CCMenu menuWithItems: itemH,mGameOverBtn, nil];
menuGO.position = ccp( 0, 0);
[modalLayer addChild:menuGO z:21];
[lblGameOverBtn runAction:[CCSequence actions:[CCDelayTime actionWithDuration: 1.75f],[CCFadeIn actionWithDuration: 1.75f],nil]];
[spriteGameOverBtn runAction:[CCSequence actions:[CCDelayTime actionWithDuration: 1.75f],[CCFadeIn actionWithDuration: 1.75f],[CCDelayTime actionWithDuration: 3.75f],nil]];
[lblGameOver runAction:[CCSequence actions:[CCDelayTime actionWithDuration: 1.75f],[CCFadeIn actionWithDuration: 1.75f],[CCDelayTime actionWithDuration: 3.75f],nil]];
[spriteGameOver runAction:[CCSequence actions:[CCDelayTime actionWithDuration: 1.75f],[CCFadeIn actionWithDuration: 1.75f],[CCDelayTime actionWithDuration: 3.75f],nil]];
//[self runAction:[CCSequence actions:[CCDelayTime actionWithDuration: 2.75f],[CCCallFunc actionWithTarget:self selector:#selector(goToMain:)], nil]];
}
I'm having the same problem with CCMenuItemSprite too. It looks like the CCMenuItemSprite-class is a bit buggy. In my case it doesn't respond to touches. But I found out it has something to do with multi-layered Sprites inside the CCMenuItemSprite. So when I use a single-layered Sprite it works, but when I use a Sprite which contains multiple embedded sprites it doesn't.
My 'not-ready-yet' solution right now is setting the contentSize to the appropriate size of the CCMenuItemSprite right after it has been initialized:
CCMenuItemSprite * menuItem = [CCMenuItemSprite itemWithNormalSprite:multiLayeredSprite selectedSprite:nil target:self selector:#selector(clickHandler:)];
[s setContentSize:backgroundSprite.contentSize];
CCMenu * menu = [CCMenu menuWithItems:
menuItem,
nil];
It's receiving touch-events now. The only problem I now have is the positioning of the Rectangle... it's still in the upper-right corner. I'll try to found out how to fix this now.
Hopefully this is clarifying a bit of the problem.
Have you have registered your scene with the touch dispatcher and your selectors actually do something?
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:NO]
Related
i'm trying to do a scrollable layer with cocos2d
what i want is for the layer to start scrolling from the top to bottom but no matter what i do when it enters the scene the layer is positioned at (0,0) aka..bottom
i've tried a couple of things but nothing seems to work
-(id) init
{
if( (self=[super init] )) {
self.isTouchEnabled = YES;
isDragging = NO;
yvel = 0.0f;
contentHeight = 1000.0f;
scrollLayer = [CCLayerColor layerWithColor:ccc4(200, 200, 200, 240)];
scrollLayer.contentSize = CGSizeMake(320,contentHeight);
scrollLayer.anchorPoint = ccp(0,1);
scrollLayer.position = ccp(0, 480);
[self addChild: scrollLayer];
CCLabelTTF *label = [CCLabelTTF labelWithString:[NSString stringWithFormat:#"test label"]
fontName:#"Marker Felt"
fontSize:24];
label.position=ccp(100, 100);
[scrollLayer addChild:label];
[self scheduleUpdate];
}
return self;
}
the other methods are update and touches handlers so the problem couldn't be there
with this code...shouldn't it initialize with the content at the top left of the screen?
after a painful few hours i finally solved the problem...but i still dont know why it works
instead of scrollLayer.position = ccp(0, 480); i replaced with scrollLayer.position =ccp(0,-contentHeight); and deleted scrollLayer.anchorPoint = ccp(0,1); cuz it wasnt doing anything
and i have absolutely no idea why it works
can someone explain this?
im new to programming, i have been experimenting with cocos2d, heres the problem, i have made a simple game, device in portrait, it has falling sprites, and i want the sprite to disappear when the position of the top of the sprite < screen.height/2 how can this be done?
heres some code you may be interested in:
this is the falling sprite, it falls from the top of the screen to the bottom
-(void)addRock {
CCSprite *rock = [CCSprite spriteWithFile:#"rock.png"
rect:CGRectMake(0, 0, 27, 40)];
// Determine where to spawn the target along the X axis
CGSize winSize = [[CCDirector sharedDirector] winSize];
int minX = rock.contentSize.width/2;
int maxX = winSize.width - rock.contentSize.width/2;
int rangeX = maxX - minX;
int actualX = (arc4random() % rangeX) + minX;
// Create the target slightly off-screen along the right edge,
// and along a random position along the X axis as calculated above
rock.position = ccp(actualX, 500);
[self addChild:rock];
// Determine speed of the target
int actualDuration = spriteDuration;//speed of sprite
// Create the actions
id actionMove = [CCMoveTo actionWithDuration:actualDuration position:ccp(actualX,-winSize.height+ rock.contentSize.height)];
id actionMoveDone = [CCCallFuncN actionWithTarget:self selector:#selector(spriteMoveFinished:)];
[rock runAction:[CCSequence actions:actionMove, nil]];
}
when the sprite move has finished
-(void)spriteMoveFinished:(id)sender {
CCSprite *sprite = (CCSprite *)sender;
[self removeChild:sprite cleanup:YES];
}
To fade your sprite out halfway of the Animation you can use CCSpawn to combine the falling animation with the fadeOut. But as you want it to fade out after a given time, you need to create a Sequence of CCDelayTime and CCFadeOut.
double fadeStart = 0.5;
id wait = [CCDelayTime actionWithDuration: actualDuration * fadeStart];
id fadeOut = [CCFadeOut actionWithDuration: actualDuration * (1.0 - fadeStart)];
id waitThenFade = [CCSequence actions: wait, fadeOut, nil];
id actionMove = ...;
id fullAnimation = [CCSpawn actions:actionMove, waitThenFade, nil];
[rock runAction:[CCSequence actions:fullAnimation, actionMoveDone, nil]];
In case you want the fading to start earlier or later you simply have to move the fadeStart value. 0 will start immediately, 1 will actually not fade, so better pick a value in between.
Maybe something like this?
CGSize size = [[CCDirector sharedDirector] winSize];
CCSprite* img = [[CCSprite alloc] initWithFile:#"yourSprite.png"];
img.position = ccp(size.width/2,size.height + img.boundingBox.size.height/2);
[img runAction:[CCSequence actions:
[CCMoveTo actionWithDuration:3 position:ccp(img.position.x,size.height/2 - img.boundingBox.size.height/2)],
[CCFadeOut actionWithDuration:1],
[CCCallFuncN actionWithTarget:nil selector:#selector(spriteMoveFinished:)],
nil]];
I am using 3 CCLayers in one Scene and I want simultaneous game play on all three layers, while user will play the game by switching between these layers. I can switch between these layers easily but my scheduled methods are not being called at all
Thats how I am doing it in the init() method of my scene and the line [self schedule:#selector(gameLogic:) interval:1.0]; is not working for me
Please help me where I am getting it wrong.
layer1 = [CCLayer node];
layer2 = [CCLayer node];
layer3 = [CCLayer node];
// add layer as a child to scene
[self addChild:layer1];
[self addChild:layer2];
[layer2 setVisible:NO];
[self addChild:layer3];
[layer3 setVisible:NO];
CCLabelTTF *layer1Label = [CCLabelTTF labelWithString:#"Layer1" fontName:#"Marker Felt" fontSize:64];
CGSize size = [[CCDirector sharedDirector] winSize];
layer1Label.position = ccp( size.width /2 , size.height/2 );
[layer1 addChild: layer1Label];
CCLabelTTF *layer2Label = [CCLabelTTF labelWithString:#"Layer2" fontName:#"Marker Felt" fontSize:64];
layer2Label.position = ccp( size.width /2 , size.height/2 );
[layer2 addChild: layer2Label];
CCLabelTTF *layer3Label = [CCLabelTTF labelWithString:#"Layer3" fontName:#"Marker Felt" fontSize:64];
layer3Label.position = ccp( size.width /2 , size.height/2 );
[layer3 addChild: layer3Label];
[self schedule:#selector(gameLogic:) interval:1.0];
}
return self;
}
Ohh dear I got it set myself. The problem was nowhere in init(). [super onEnter] was missing in -(void)onEnter method. Now all my scheduled methods are doing fine.
I have added a sprite and added a label as the child of the sprite.
Now I want to click the sprite and get the corresponding label text .Help me with some solution.
bubblesprite = [CCSprite spriteWithFile:#"bubble2.png"];
bubblesprite.position=CGPointFromString([self positioning]);
[self addChild:bubblesprite];
label = [CCLabelTTF labelWithString:[tempArray2 objectAtIndex:i] fontName:#"Marker Felt" fontSize:30];
label.color = ccc3(233,34,19);
[bubblesprite addChild: label z:1];
CGSize s = [bubblesprite contentSize];
label.position = ccp(s.width/2, s.height/2);
To access your labelstring use your tempArray2 [tempArray2 objectAtIndex:i]
I suggest to use CCMenu for your demand.
NSString* labelString = #"test";
CCLabelTTF* aLabel = [CCLabelTTF labelWithString:labelString fontName:#"Maker Felt" fontSize:24];
aLabel.position = ccp(100, 100);
[self addChild:aLabel];
CCMenuItemImage* button = [CCMenuItemImage itemFromNormalImage:#"Icon.png" selectedImage:#"Icon.png" target:self selector:#selector(buttonPress)];
button.position = ccp(100, 100);
CCMenu* menu = [CCMenu menuWithItems:button, nil];
menu.position = ccp(0, 0);
[self addChild:menu];
-(void)buttonPress
{
CCLog("%#", labelString);
}
To change the text from the label use its setText: method. This method is slow. For a fast version use CCLabelBMFont http://www.cocos2d-iphone.org/api-ref/0.99.5/interface_c_c_label_b_m_font.html
i am adding overlays to a cocos2d layer in preparation for a screenshot...
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCScene* currentScene = [[CCDirector sharedDirector] runningScene];
GameLayer* topLayer = (GameLayer *)[currentScene.children objectAtIndex:0];
CCSprite *middleBackground = [CCSprite spriteWithFile:#"mid_bg.png"];
middleBackground.position = ccp(winSize.width * 0.5,winSize.height * 0.55);
[topLayer addChild:middleBackground z:3 tag:111];
CCSprite *bottomBackground = [CCSprite spriteWithFile:#"bot_bg.png"];
bottomBackground.position = ccp(winSize.width * 0.5,winSize.height * 0.1);
[topLayer addChild:bottomBackground z:3 tag:112];
CCSprite *topBackground = [CCSprite spriteWithFile:#"top_bg.png"];
topBackground.position = ccp(winSize.width * 0.5,winSize.height * 0.94);
[topLayer addChild:topBackground z:3 tag:113];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
CCSprite *topBackground2 = [CCSprite spriteWithFile:#"statusCover2.png"];
topBackground2.position = ccp(winSize.width * 0.5,winSize.height * 0.992);
[topLayer addChild:topBackground2 z:3 tag:114];
[[topLayer popoverController] dismissPopoverAnimated:YES];
then
[UIImage imageWithCGImage:UIGetScreenImage()];
However the later is not taking the overlays into account. It is taking a screenshot of the layer before the overlays are added.
Is there anyway I can tell the cocos2d scene/layer to update the frame NOW?
Because cocos2d is asynchronous you can't tell it to do something like that. However, you can schedule a callback to happen in two seconds and have that callback do the screen capture.
[self schedule: #selector(screenshot:) interval:2.0];
then define the selector like this:
-(void) screenshot:(id)sender {
[UIImage imageWithCGImage:UIGetScreenImage()];
[self unschedule:#selector(screenshot:)];
}
don't forgot to unschedule it.