Countdown timer in cocos2d? - iphone

I'm trying to create a countdown timer in cocos2d, but I can not help and would like to resolve this problem, my code is below this, perhaps the logic is wrong but I can not fix.
-(id) init
{
// always call "super" init
// Apple recommends to re-assign "self" with the "super" return value
if( (self=[super init] )) {
CCSprite *background = [CCSprite spriteWithFile:#"backgame.png"];
CGSize size = [[CCDirector sharedDirector] winSize];
[background setPosition:ccp(size.width/2, size.height/2)];
[self addChild: background];
[self schedule:#selector(countDown:)];
}
return self;
}
-(void)countDown:(ccTime)delta
{
CCLabel *text = [CCLabel labelWithString:#" "
fontName:#"BallsoOnTheRampage" fontSize:46];
text.position = ccp(160,455);
text.color = ccYELLOW;
[self addChild:text];
int countTime = 20;
while (countTime != 0) {
countTime -= 1;
[text setString:[NSString stringWithFormat:#"%i", countTime]];
}
}

Your int countTime = 20; is declaring itself every time to be 20. Also, your while loop will decrement the countTimer as fast as the system can update the CCLabel. If you're trying to do a real timer, you want it to decrement ONLY when countDown: is called. Not during a while-loop.
Try this:
#interface MyScene : CCLayer
{
CCLabel *_text;
}
#property (nonatomic, retain) int countTime;
#end
#implementation MyScene
#synthesize countTime = _countTime;
-(id) init {
if( (self=[super init] )) {
CCSprite *background = [CCSprite spriteWithFile:#"backgame.png"];
CGSize size = [[CCDirector sharedDirector] winSize];
[background setPosition:ccp(size.width/2, size.height/2)];
[self addChild: background];
_countTime = 20;
_text = [CCLabel labelWithString:[NSString stringWithFormat:#"%i", self.countTime]
fontName:#"BallsoOnTheRampage" fontSize:46];
text.position = ccp(160,455);
text.color = ccYELLOW;
[self addChild:_text];
[self schedule:#selector(countDown:) interval:0.5f];// 0.5second intervals
}
return self;
}
-(void)countDown:(ccTime)delta {
self.countTime--;
[_text setString:[NSString stringWithFormat:#"%i", self.countTime]];
if (self.countTime <= 0) {
[self unschedule:#selector(countDown:)];
}
}
#end

Your count allways becomes 20 in your countDown.
You should also move this to your init:
CCLabel *text = [CCLabel labelWithString:#" "
fontName:#"BallsoOnTheRampage" fontSize:46];
text.position = ccp(160,455);
text.color = ccYELLOW;
[self addChild:text];
Then you should use:
[self schedule:#selector(countDown:) interval:1.0f];
Then instead of using CCLabel you should use CCLabelBMFont. It's much faster :)

Related

Displaying score overlapping

I used cocos2d game tutorial from http://www.raywenderlich.com/25736/how-to-make-a-simple-iphone-game-with-cocos2d-2-x-tutorial After i add the score to scorelabel, the score increases but the previous score isn't getting removed and the new score gets added above the earlier score's label
code:
CGSize winSize = [[CCDirector sharedDirector] winSize];
CCLabelTTF * label1 = [CCLabelTTF labelWithString:#"_monsterdestroyed" fontName:#"Arial" fontSize:32];
score=score + 2;
[label1 setString:[NSString stringWithFormat:#"%d",score]];
label1.color = ccc3(0,0,0);
label1.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:label1];
I am guessing that you are doing all this in an update method, adding a label1 label at every update. You probably want an iVar in your .h file for the score label1 , initialize it in your init, as follows:
in .h
CCLabelTTF *label1;
in .m
-(id) init {
if (self = [super init]) {
// your existing code, add the following
CGSize winSize = [[CCDirector sharedDirector] winSize];
label1 = [CCLabelTTF labelWithString:#"0" fontName:#"Arial" fontSize:32];
label1.color = ccc3(0,0,0);
label1.position = ccp(winSize.width/2, winSize.height/2);
[self addChild:label1];
}
}
// where you update the score
score = score + 2;
[label1 setSting:[NSString stringWithFormat:"%i", score];

How to display the score in the game over layer in cocos2d

I've a problem when I try to show the final score in the Game Over Layer in a game in cocos2d. There's an algorithm that modify the value of my variable increment, that contains the points of the user and then the game shows them.
increment = increment + 50;
[pointLabel setString: [NSString stringWithFormat: #"Points: %i", increment]];
and then a function controls if the user has or not lives in his play
-(void)gameOver:(int)value punteggio:(id)punti{
if (value == 1) {
//WIN
}else if(value == 2){
if (life > 1) { // 1
life = life - 1;
for (CCSprite *spr in spriteLifeArray) {
if (life == spr.tag) {
[self removeChild:spr cleanup:YES];
}}}
else {
// LOSE
[...]
[[CCDirector sharedDirector] replaceScene:[GameOver node]];
}
}}
Then the GameOverLayer is called. This is the .h file
#interface GameOver : CCNode {
CGSize size;
CCLabelTTF *label1;
CCLabelTTF *label2;
CCLabelTTF *labelpnt;
CCLabelTTF *labelscore;
}
-(void)restart;
Here the .m file
#implementation GameOver
+(id) scene {
// 'scene' is an autorelease object.
CCScene *scene = [CCScene node];
// 'layer' is an autorelease object.
GameOver *layer = [GameOver node];
// add layer as a child to scene
[scene addChild: layer];
// return the scene
return scene;
}
-(id) init{
if( (self=[super init] )) {
size = [[CCDirector sharedDirector] winSize];
label1 = [CCLabelTTF labelWithString:#"Game Over" fontName:#"Marker Felt" fontSize:40];
label1.position = ccp(size.width/2 , size.height/2+20+50 );
labelpnt = [CCLabelTTF labelWithString:#"Punteggio" fontName:#"Marker Felt" fontSize:20];
labelpnt.position = ccp(size.width/2 , size.height/2+50-100 );
labelscore = [CCLabelTTF labelWithString:#"100" fontName:#"Marker Felt" fontSize:20];
[labelscore setString: [NSString stringWithFormat: #" 0 "]];
[labelscore setColor:ccc3(255, 1, 1)];
labelscore.position = ccp(size.width / 2, size.height/2+50-130);
label2 = [CCLabelTTF labelWithString:#"Ricomincia" fontName:#"Marker Felt" fontSize:25];
CCMenuItemLabel *back = [CCMenuItemLabel itemWithLabel:label2 target:self selector:#selector(restart)];
CCMenu *menu= [CCMenu menuWithItems:back, nil];
menu.position = ccp(size.width/2 , size.height/2-50+50);
[self addChild: label1];
[self addChild: labelpnt];
[self addChild: labelscore];
[self addChild: menu];
}
return self;
}
-(void) restart {
[[CCDirector sharedDirector] replaceScene:[HelloWorldLayer node]];
}
How can I show the final value of my int increment in the game over layer? How can I pass it throught the classes?
Use UserDefault. Here is code
//Save score in game screen
int highScore = 234;
[[NSUserDefaults standardUserDefaults] setInteger:12 forKey:#"HighScore"];
[[NSUserDefaults standardUserDefaults] synchronize];
//get score in game over
int highScore = [[NSUserDefaults standardUserDefaults] integerForKey:#"HighScore"];
NSString *score = [NSString stringWithFormat: #"%d", highScore];
CCLabelTTF *scoreLabel = [CCLabelTTF labelWithString:score fontName:#"Marker Felt" fontSize:40];
Hey in that Case You should take a separate layer for displaying the Score lives or whatever you want to display simultaneously.
In HUD Layer i.e Heads-Up Display class You should write some basic code to display a CCLabelBMFont to the screen that says "Your Score", “You Win” or “You Lose” and a button underneath that says “Restart”.
When the restart button is tapped, it creates a new instance of the ActionLayer switches to it.
Write a Score method scoreUpdate, this method will have the logic for the score calculation like whenever a bullet hit to monster and update it to the CCLabelBMFont label.
And then All you need to do just call that method.
Here is the one of the best tutorial for such requirement.
See

Debug label y value in cocos2d is off

I have a cocos2d game with a CCLayer called GameplayLayer placed inside a scene. Here is the layer's init code:
- (id)initWithScene1BackgroundLayer:(Scene1BackgroundLayer *)scene5UILayer {
if ((self = [super init])) {
uiLayer = scene5UILayer;
startTime = CACurrentMediaTime();
[self scheduleUpdate];
self.isAccelerometerEnabled = YES;
//chipmunk
[self createSpace];
[self createGround];
mouse = cpMouseNew(space);
self.isTouchEnabled = YES;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile:#"escapesceneatlas.plist"];
sceneSpriteBatchNode = [CCSpriteBatchNode
batchNodeWithFile:#"escapesceneatlas.png"];
hopper = [[[CPHopper alloc] initWithLocation:ccp(200,200) space:space groundBody:groundBody] autorelease];
} else {
[[CCSpriteFrameCache sharedSpriteFrameCache]
addSpriteFramesWithFile:#"escapesceneatlas.plist"];
sceneSpriteBatchNode = [CCSpriteBatchNode
batchNodeWithFile:#"escapesceneatlas.png"];
//Viking became hopper and starts at bottom
hopper = [[[CPHopper alloc] initWithLocation:ccp(100,100) space:space groundBody:groundBody] autorelease];
//An enemy robot called JJ1 also starts at bottom
genericBody = [[[CPGenericBody alloc] initWithLocation:ccp(210,200) space:space groundBody:groundBody] autorelease];
//add the batchnode to layer
[self addChild:sceneSpriteBatchNode z:0];
}
[self addLabel];
[sceneSpriteBatchNode addChild:hopper z:2];
[sceneSpriteBatchNode addChild:genericBody z:2];
}
return self;
}
The addLabel method calls the debugLabel of the hopper class like this:
-(void)addLabel{
//set debuglabel
CCLabelBMFont *debugLabel=[CCLabelBMFont labelWithString:#"NoneNone" fntFile:#"SpaceVikingFont.fnt"];
[self addChild:debugLabel];
[hopper setMyDebugLabel:debugLabel];
}
Then the debugLabel code in the hopper class is:
-(void)setDebugLabelTextAndPosition {
CGPoint newPosition = [self position];
NSString *labelString = [NSString stringWithFormat:#"X: %.2f \n Y:%d \n", newPosition.x, newPosition.y];
[myDebugLabel setString: [labelString stringByAppendingString:#" tracking..."]];
float yOffset = screenSize.height * 0.195f;
newPosition = ccp(newPosition.x,newPosition.y+yOffset);
[myDebugLabel setPosition:newPosition];
}
For some reason when I run it the X value is fine, its value seems reasonable, it starts out at 100 but the y value is approx 1,567,385 and then if i move the hopper it goes to 35,633,753 and keeps changing to huge random numbers. It seems very unsteady.
Why could this be?
There is a simple typo in your debug label code. You are formatting your floating point number as an integer which just gives garbage results. Because the stringWithFormat function will not implicitly convert the float to int but just take the bit representation of the float and interpret it as an integer number.
A more detailed explanation is given here.
So this
NSString *labelString = [NSString stringWithFormat:#"X: %.2f \n Y:%d \n", newPosition.x, newPosition.y];
should be
NSString *labelString = [NSString stringWithFormat:#"X: %.2f \n Y:%.2f \n", newPosition.x, newPosition.y];
.

Change Sprite with Buttons - Cocos2d

I have 2 buttons (left and right) and a sprite sheet that contains all 55 images. I was wondering, what is the best way to go through each sprite using the buttons?
E.G.
Press the left button and the first sprite is added. Press the right button, the first sprite is removed and the second sprite to added. So on and so forth until it reaches the last image.
This is the Sprite Sheet
#import "cocos2d.h"
#interface GameScene : CCLayer {
CCSpriteBatchNode *pspriteSheet
}
+(CCScene *) scene;
#property (nonatomic, retain) CCSprite *p;
#end
----------------------------------------------------
#import "GameScene.h"
#implementation GameScene
#synthesize p = _p;
+(CCScene *) scene
{
CCScene *scene = [CCScene node];
GameScene *layer = [GameScene node];
[scene addChild: layer];
return scene;
}
-(id) init
{
if ((self = [super init]))
{
[[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:
#"PAnim.plist"];
pspriteSheet = [CCSpriteBatchNode batchNodeWithFile:#"PAnim.pvr.ccz"];
[self addChild:pspriteSheet z:0];
}
return self;
}
- (void) dealloc
{
CCLOG(#"%#: %#", NSStringFromSelector(_cmd), self);
_p = nil;
[CCSpriteFrameCache purgeSharedSpriteFrameCache];
[CCTextureCache purgeSharedTextureCache];
[super dealloc];
}
Should I just keep adding them and removing them?
E.G.
-(void)buttons:(CGPoint)touchLocation
{
if (CGRectContainsPoint(leftB.boundingBox, touchLocation) && tapP == YES && paused == NO) {
if (count == 1)
{
_p = [CCSprite spriteWithSpriteFrameName:#"p1.png"];
[pspriteSheet addChild:_p];
count = 2;
_p.position = ccp(240, 215);
}
if (CGRectContainsPoint(rightB.boundingBox, touchLocation) && tapP == YES && paused == NO) {
if (count == 2)
{
[pspriteSheet removeChild:_p cleanup:YES];
_p = [CCSprite spriteWithSpriteFrameName:#"p2.png"];
_p.position = ccp(240, 215);
[pspriteSheet addChild:_p];
count = 3;
}
}
Here is where the "buttons" method is called
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchLocation = [self convertTouchToNodeSpace:touch];
[self buttons:touchLocation];
return TRUE;
}
Since it is using spriteframe, you can use setDisplay frame:
CCSpriteFrame* frame = [[CCSpriteFrameCache sharedSpriteFrameCache]spriteFrameByName:#"spr1.png"];
[mySprite setDisplayFrame:frame];
This would save up memory instead of always adding and removing..

Cocos2d Chipmunk: Touch Shapes?

Today i got a cocos2d question!
I got a few shapes and the space-manager set up in my .m file by using nodes:
- (CCNode*) createBlockAt:(cpVect)pt
width:(int)w
height:(int)h
mass:(int)mass
{
cpShape *shape = [smgr addRectAt:pt mass:mass width:w height:h rotation:0];
cpShapeNode *node = [cpShapeNode nodeWithShape:shape];
node.color = ccc3(56+rand()%200, 56+rand()%200, 56+rand()%200);
[self addChild:node];
return node;
}
- (CCNode*) createCircleAt:(cpVect)pt
mass:(int)mass
radius:(int)radius
{
cpShape *shape = [smgr addCircleAt:pt mass:mass radius:radius];
cpShapeNode *node1 = [cpShapeNode nodeWithShape:shape];
CCSprite *sprt = [CCSprite spriteWithFile:#"fire.png"];
node1.color = ccc3(56+rand()%200, 56+rand()%200, 56+rand()%200);
[self addChild:node1];
return node1;
}
then i actually make the shapes, set up a background, alloc and start the space-manager in my init method:
- (id) init
{
[super init];
CCSprite *background = [CCSprite spriteWithFile:#"BGP.png"];
background.position = ccp(240,160);
[self addChild:background];
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:0 swallowsTouches:NO];
//allocate our space manager
smgr = [[SpaceManagerCocos2d alloc] init];
smgr.constantDt = 1/55.0;
[smgr addWindowContainmentWithFriction:1.0 elasticity:1.0 inset:cpvzero];
[self createBlockAt:cpv(160,50) width:50 height:100 mass:100];
[self createBlockAt:cpv(320,50) width:50 height:100 mass:100];
[self createBlockAt:cpv(240,110) width:210 height:20 mass:100];
[self createCircleAt:cpv(240,140) mass:25 radius:20];
[smgr start];
return self;
}
Now, i want a shape to be removed if it's touched. What is the best way to do that???
I hope that somebody out there can help me :)
Edit:
Plz somebody, start a bounty! Or i never get this answered :(
-DD
How about like this?
- (BOOL)ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint point = [self convertTouchToNodeSpace:touch];
cpShape *shape = [smgr getShapeAt:point];
if (shape) {
[self removeChild:shape->data cleanup:YES];
[smgr removeAndFreeShape:shape];
}
return YES;
}