progress time bar in cocos2d disappers after restart game - cocos2d-iphone

I've created a quiz game, that implements a time bar. In the first play it's all right, but if, after gameover, the player tap "restart", the game goes on properly, but the time bar disappears!
Here my code from GameOverLayer to Game:
-(void) restart {
[[CCDirector sharedDirector] replaceScene:[HelloWorldLayer node]];
}
Here the function to create a new question
-(void)creaDomanda{
//bar
CCProgressFromTo *to1 = [CCProgressFromTo actionWithDuration:MaxTime from:100 to:0];
bar = [CCProgressTimer progressWithFile:#"barra.png"];
bar.type = kCCProgressTimerTypeHorizontalBarLR;
[bar setPosition:ccp(size.width - 250 , size.height - 18)];
int randomValue = (arc4random() % 4) + 1;
NSString *stringa = [NSString stringWithFormat:#"Domanda%i", randomValue];
dictionary = [plistData objectForKey:stringa];
domanda = [dictionary valueForKey:#"Titolo"];
labelDomanda = [CCLabelTTF labelWithString:domanda fontName:#"Marker Felt" fontSize:24];
labelDomanda.position = ccp( size.width /2 , 400 );
[self addChild: labelDomanda];
int rispostaEsatta = [[dictionary valueForKey:#"Soluzione"] intValue];
menu = [CCMenu menuWithItems:nil];
for (int i = 1; i<5;i++)
{
if(rispostaEsatta == i){
item = [CCMenuItemFont itemFromString:[dictionary valueForKey:
[NSString stringWithFormat:#"Risposta%i",i] ]
target:self selector:#selector(corretto)];
}else{
item = [CCMenuItemFont itemFromString:[dictionary valueForKey:
[NSString stringWithFormat:#"Risposta%i",i] ]
target:self selector:#selector(sbagliato)];
}
[menu addChild:item];
}
//[..]
[self addChild:menu];
[self addChild:bar];
[bar runAction:to1];
}
And here one of the correct/wrong method (similar) that after all, create a new question:
-(void)sbagliato{
CCLOG(#"Sbagliato");
if (menu) [self removeChild:menu cleanup:YES];
if (labelDomanda) [self removeChild:labelDomanda cleanup:YES];
if (bar) [self removeChild:bar cleanup:YES];
labelRisultato = [CCLabelTTF labelWithString:#"Hai sbagliato!" fontName:#"Marker Felt" fontSize:24];
[labelRisultato setColor:ccc3(255, 1, 1)];
labelRisultato.position = ccp(size.width / 2, 280);
[self addChild:labelRisultato];
[self gameOver:2 punteggio:0];
// Richiamiamo il metodo per eliminare la label dopo 0,3 secondi
[self performSelector:#selector(eliminaLabel) withObject:nil afterDelay:0.5];
increment = increment - 20;
[pointLabel setString: [NSString stringWithFormat: #"Punti: %i", increment]];
// new question
[self performSelector:#selector(creaDomanda) withObject:nil afterDelay:0.5];
}
Can anyone explain to me please why when I restart the time bar desappers?
Thank You

My best guess:
The CCProgressFromTo action is still running. Since it progresses down to 0, the CCProgressTimer eventually doesn't display any part of it anymore. This may continue even if you run another CCProgressFromTo action on the progress timer.
Solution: be sure to stop any running CCProgressFromTo actions before running another.
If that doesn't fix it, then I imagine the CCProgressTimer needs to be reset by setting percentage back to 100.

Related

How to add multiple sprites with time interval of 3 seconds and run same CCAction for all in cocos2d

Please help me as am fed with the searches and new to cocos 2d. Only am getting is the last sprite got moving if i schedule addRed and i want all the sprites moving randomly in the screen. Any help will be Appreciated and thanks in advance.
-(void)addRed
{
redSprite = [CCSprite spriteWithImageNamed:#"Red.png"];;
CGSize screenSize = [[CCDirector sharedDirector] viewSize];
[redSprite setPosition:CGPointMake(screenSize.width/2, screenSize.height/2)];
[self resizeSprite:redSprite toWidth:80 toHeight:80];
[self addChild:redSprite z:10];
[self gameStart];
}
- (void)gameStart {
// Create the actions
CGSize result = [[UIScreen mainScreen] bounds].size;
CGPoint nextPoint;
if (redSprite.position.x == result.width-40.0) {
nextPoint.x = redSprite.position.x - kAccelXAxis;
backx = YES;
}
else {
if (redSprite.position.x == 40.0) {
nextPoint.x = redSprite.position.x + kAccelXAxis;
backx = NO;
}
else {
if (backx) {
nextPoint.x = redSprite.position.x - kAccelXAxis;
}
else
{
nextPoint.x = redSprite.position.x + kAccelXAxis;
}
}
}
if (redSprite.position.y == 40.0) {
nextPoint.y = redSprite.position.y + kAccelYAxis;
backy = YES;
}
else {
if (redSprite.position.y == result.height-40.0) {
nextPoint.y = redSprite.position.y - kAccelYAxis;
backy = NO;
}
else {
if (backy) {
nextPoint.y = redSprite.position.y + kAccelYAxis;
}
else
{
nextPoint.y = redSprite.position.y - kAccelYAxis;
}
}
}
CCAction *myAction = [CCActionSequence actions:[CCActionMoveTo actionWithDuration:0.01 position:nextPoint], [CCActionCallFunc actionWithTarget:self selector:#selector(gameStart)], [CCActionCallFunc actionWithTarget:self selector:#selector(updateCol:)],nil];
[myAction setTag:10];
[redSprite runAction:myAction];
}
Try creating a updater with an interval of 3 sec for creating your sprites. For your created sprites, use a CCRepeatForever which will generate your next positions for your sprite.
For your case, I also thought about using a custom CCSprite to store your next position to move.
You will need something like...
[self schedule:#selector(createSprite) interval:(3)]; //to schedule your sprite generator
// Your sprite generator with action
-(void)createSprite{
CCCustomRed *red = [CCCustomRed spriteWithFile:#"red.png"];
[self addChild:red];
CCCallFuncN *changePos = [CCCallFuncN actionWithTarget:self selector:#selector(setRandomPos:)];
CCMoveTo *move = [CCMoveTo actionWithDuration:1 position:red.nextPosition];
CCDelayTime *delay = [CCDelayTime actionWithDuration:1.0];
[red runAction:[CCRepeatForever actionWithAction:[CCSequence actions:move,changePos,delay,nil]]];
}
//Generate a random pos as your sprite next move
-(void)setRandomPos:(id)sender{
CCCustomRed *red = (CCCustomRed *) sender;
CGSize screenSize = [[CCDirector sharedDirector] winSize];
red.nextPosition = ccp(arc4random()%screenSize.width,arc4random()%screenSize.height);
}
Hope it helps :)

CCAnimation with low delay doesn't finish

I created a CCAnimation as seen below. I tried lowering the delay to something below .05f and the animation now fails to complete! Its only 8 frames. I don't know if I am doing something wrong. At first I thought it was a memory leak and I was losing the action, so I assigned it to a strong property to test that, and still did it. I'm not sure how the delay could cause my animation to fail to finish. I am running in the simulator at 60 frames per sec.
Using Kobold 2.0.4
Can anyone help?
else if([model currentState] == PROCESSING_FIRST_ACTION)
{
CCDirector* director = [CCDirector sharedDirector]; // process model
//Get the top left corner of the screen
int screen_height = director.screenSizeAsPoint.y;
int screen_width = director.screenSizeAsPoint.x;
id attacker = [model attacker];
id attackChoice = [attacker getRegisteredAttack];
CCAction* attack = [model.resourceManager animation: #"simple-attack-frame"];
CCSprite * attackSprite = [model.resourceManager sprite: #"simple-attack-frame-01"];
attackSprite.position = ccp(screen_width - rxa(80), screen_height - rya(80));
attackSprite.tag = 5;
self.action = attack;
CCNode * check = [self getChildByTag:5];
if(check == nil)
{
[self addChild: attackSprite];
[attackSprite runAction:attack];
}
}
resource manager:
-(id)animation: (NSString*)_resource
{
NSMutableArray *frames = [NSMutableArray array];
for(int i = 1; i <= 8; ++i)
{
[frames addObject:
[[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:
[NSString stringWithFormat:#"%#-0%d", _resource, i]]];
}
CCAnimation *animation = [CCAnimation animationWithSpriteFrames: frames delay:1/60];
CCAction * action = [CCAnimate actionWithAnimation: animation];
return action;
}
In your line
CCAnimation *animation = [CCAnimation animationWithSpriteFrames: frames delay:1/60];
you're setting the delay to 1/60, but as 1 and 60 are both integers, 1/60 is 0. Try using 1.0f/60.0f and you'll get a floating point divide.
After digging around on the web I found a solution. I'm not the one who submitted this solution but I can attest that it fixed my problems:
https://github.com/cocos2d/cocos2d-iphone/commit/60f9cc98783b9a6a5635db4f468f83e0511c74c8

Cocos2D game ABC123 cannot run on iPad

I'm new to Cocos2D and I'm now trying ABC123 (downloaded from internet, created by kwigbo)
I wonder why it works all fine by the simulator, but while i'm using my iPad to test it.... problem comes up.. I tried for 2weeks but still cannot solve it... hope anyone can teach me?? Thanks a lot....
Originally the bubble will appear AFTER player memorized the word's locations, but when using iPad to run it... the bubble appear soon after started, player cannot remember the word locations for playing the game at all...
I've tried to change the delay part from delayTime = 1.5 to 4;:
#GameLayer.m
float delayTime = 4.0;
if(dataManager.currentlevel > 10) delayTime = 2.5;
[self runAction:[Sequence actions:[DelayTime actionWithDuration:delayTime], [CallFunc actionWithTarget:self selector:#selector(showBubbles)], nil]];
It delay in simulator but didn't change in iPad....
Is there any relationship with OrbSprite.m?
#OrbSprite.m's init:
Label *l = [[Label alloc] initWithString:#"" dimensions:CGSizeMake(50, 50) alignment:UITextAlignmentCenter fontName:#"Arial Rounded MT Bold" fontSize:45];
self.label = l;
[l release];
//[self initWithFile:#"bubble1.png"];
Animation *bub = [Animation animationWithName:#"bubble" delay:1.0f images:#"bubble1.png", #"bubble2.png", nil];
self.bubble = bub;
[bub release];
[self addAnimation:bubble];
Or should I do anything on this line?
- (void) showBubble
{
isBubble = YES;
[self setDisplayFrame:#"bubble" index:1];
self.scale = .1;
[self runAction:[Sequence actions: [ScaleTo actionWithDuration:.1 scale:0.1], [ScaleTo actionWithDuration:.1 scale:1], nil]];
[self removeChild:label cleanup:YES];
}

program crashes when removing shapes in spacemanager - cocos2d

i am using spacemanager with chipmunk physics for my game.
What i am trying to do is hit a ball to a pillar and make the ball disappear. i am recreating the ball in different location so the user can hit another pillar. i have the ball shape and ball sprite as member variable.
Here is the code for creating ball, pillar shapes etc.
ball = [smgr addCircleAt:cpv(1000,10) mass:0.5 radius:35];
ball->collision_type = kBallCollisionType;
ballSprite = [cpCCSprite spriteWithShape:ball file:#"head.png"];
//[ballSprite autoFreeShape];
[self addChild:ballSprite];
ballSprite.spaceManager = smgr;
//ballSprite.ignoreRotation = NO;
cpShape *dome = [smgr addRectAt:cpv(400,500) mass:1 width:400 height:100 rotation:0];
dome->collision_type = kRectCollisionType;
cpCCSprite *dome1 = [cpCCSprite spriteWithShape:dome file:#"001.png"];
[self addChild:dome1];
dome1.spaceManager = smgr;
cpShape *pillarone = [smgr addRectAt:cpv(300,300) mass:1 width:45 height:194 rotation:0];
pillarone->collision_type = kRectCollisionType;
cpCCSprite *pillar1 = [cpCCSprite spriteWithShape:pillarone file:#"004.png"];
[self addChild:pillar1];
pillar1.spaceManager = smgr;
cpShape *pillartwo = [smgr addRectAt:cpv(500,300) mass:1 width:45 height:194 rotation:0];
pillartwo->collision_type = kRectCollisionType;
cpCCSprite *pillar2 = [cpCCSprite spriteWithShape:pillartwo file:#"004.png"];
[self addChild:pillar2];
pillar2.spaceManager = smgr;
cpShape *staticground = [smgr addRectAt:cpv(510,25) mass:1 width:0 height:0 rotation:0];
cpCCSprite *staticground1 = [cpCCSprite spriteWithShape:staticground file:#"grass1-1024.png"];
[self addChild:staticground1 z:1 tag:0];
[smgr addCollisionCallbackBetweenType:kRectCollisionType
otherType:kBallCollisionType
target:self
selector:#selector(handleCollisionWithFragmentingRect:arbiter:space:)];
AND HERE IS THE CODE FOR COLLISION HANDLING.
- (void) handleCollisionWithFragmentingRect:(CollisionMoment)moment arbiter:(cpArbiter*)arb space:(cpSpace*)space{
if (moment == COLLISION_POSTSOLVE)
{
[self removeChild:ball->data cleanup:YES];
[smgr removeAndFreeShape:ball];
ball = [smgr addCircleAt:cpv(1000,10) mass:0.5 radius:35];
ball->collision_type = kBallCollisionType;
ballSprite = [cpCCSprite spriteWithShape:ball file:#"head.png"];
[self addChild:ballSprite];
ballSprite.spaceManager = smgr;
}
}
When the first ball hits the pillar it disappears fine. but for the second and some times third ball i pick and hit the pillar it crashes with error as follows.
Chipmunk warning: Cannot remove a constraint that was not added to the space. (Removed twice maybe?)
Failed condition: cpArrayContains(space->constraints, constraint)
i am not sure where i went wrong, can anyone help please.
Thanks.
I think you need to add teh ball to be removed to a "garbage" array, and not remove it on the handleCollisionWithFragmentingRect function. For all safety measures, include the
- (void) update : (ccTime) dt
{
for (cpShape *shape in _garbage)
{
// Remove shape
[self removeChild:shape->data cleanup:YES];
[smgr removeAndFreeShape:shape];
// Add new ball
ball = [smgr addCircleAt:cpv(1000,10) mass:0.5 radius:35];
ball->collision_type = kBallCollisionType;
ballSprite = [cpCCSprite spriteWithShape:ball file:#"head.png"];
[self addChild:ballSprite];
ballSprite.spaceManager = smgr;
}
...
}
And then you would change the handle function to this:
- (void) handleCollisionWithFragmentingRect:(CollisionMoment)moment arbiter:(cpArbiter*)arb space:(cpSpace*)space
{
if (moment == COLLISION_POSTSOLVE)
{
// SHOULDNT BE A DIRECT REFERENCE TO MEMBER VARIABLE BALL.
// SHOULD BE ADDED FROM INFORMATION WITHIN THE PARAMETERS OF THIS FUNCTION.
_garbage.addObject(ball);
}
}

On CCBitmapFontAtlas effect (Display on by one)

I'm trying to make a effect using the CCBitmapFontAtlas, here is what I want:
The string say "ABCDEFG" being dispayed one by one, each one won't be displayed
until the one before is completely displayed.
And here is what I tried:
-(id) init
{
if( (self=[super init] )) {
label = [CCBitmapFontAtlas bitmapFontAtlasWithString:#"ABC" fntFile:#"bitmapFontTest.fnt"];
[self addChild:label];
CGSize s = [[CCDirector sharedDirector] winSize];
label.position = ccp(s.width/2, s.height/2);
label.anchorPoint = ccp(0.5f, 0.5f);
label.visible = NO; //hide it first
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:YES];
}
return self;
}
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CCSprite AChar = (CCSprite) [label getChildByTag:0];
CCSprite BChar = (CCSprite) [label getChildByTag:1];
CCSprite CChar = (CCSprite) [label getChildByTag:2];
id fade_in = [CCFadeIn actionWithDuration:3];
label.visible = YES;
[AChar runAction:fade_in];
[BChar runAction:fade_in];
[CChar runAction:fade_in];
return YES;
}
The effect is the "ABC" will fade in once I touched the screen, then I tried to use the
CallFuncND to call the next string to fade in while the current string is displayed.
But this seems to make things very complex.
Is there a easier way to get this effect done?
Any suggestion will be appreciate.
I feel like you are going in the right direction with this one. You could have each letter be a separate sprite and store them in an array and then run them each one by one.
The call function can be started by:
[self displayNextSprite:spriteArray nextIndex:0];
And the function is:
// Warning, This assumes you are not passing it an empty array, you may want to put in a check for that
-(void)displayNextSprite:(NSMutableArray*)spriteArray nextIndex:(NSUInteger)nextIndex
{
CCSprite *nextSprite = [spriteArray objectAtIndex:nextIndex];
id action1 = [CCFadeIn actionWithDuration:3];
// or = [CCPropertyAction actionWithDuration:3 key:#"opacity" from:0 to:255];
// The last letter
if(nextIndex == ([spriteArray count] - 1))
{
[nextSprite runAction:action1];
}
else // continue to the next letter
{
id callFunc = [CCCallFunc actionWithTarget:self selector:#selector(displayNextSprite:spriteArray nextIndex:nextIndex+1)];
id sequence = [CCSequence actionOne:action1 two:callFunc];
[nextSprite runAction:sequence];
}
}