Simple Game - adding a countdown after scoring - iphone

I am creating a simple tennis game in Objective-C. Currently, when the player or the computer scores, it gives a message "tap to begin" and that releases the ball (it's a bit awkward to have your thumb on the racquet and another thumb to tap it to begin).
How do I add a timer into my game so that I don't have to tap after every score?
(This code is the resetting method when there is a new game and when there is a score)
{
self.gameState = kGameStatePaused;
ball.center = self.view.center;
if(newGame)
{
if(computerScoreValue > playerScoreValue)
{
tapToBegin.textAlignment = UITextAlignmentCenter;
tapToBegin.text = #"Computer Wins!";
AudioServicesPlaySystemSound(booFileID);
}
else
{
tapToBegin.textAlignment = UITextAlignmentCenter;
tapToBegin.text = #"You Win!";
AudioServicesPlaySystemSound(clappingFileID);
}
computerScoreValue = 0;
playerScoreValue = 0;
}
else
{
tapToBegin.textAlignment = UITextAlignmentCenter;
tapToBegin.text = #"Tap to Begin";
}
playerScore.text = [NSString stringWithFormat:#"%d",playerScoreValue];
computerScore.text = [NSString stringWithFormat:#"%d",computerScoreValue];
}

NSTimer should work. If you're curious take a look at CADisplayLink too.

Related

Animating sequence of images in cocos2d

i have this code to show animation of a image
-(void) blink:(ccTime) delta {
animateblink ++; //adds 1 every frame
if (animateblink <= 6 ) { //if we included frames to show for breaking and the current frame is less than the max number of frames to play
if (animateblink < 6) {
[sprite setTexture:[[CCSprite spriteWithFile:[NSString stringWithFormat:#"%#_blinkk00%i.png", baseImageName,animateblink]] texture]];
[self unschedule:_cmd];
[self schedule:#selector(openEyes:) interval:0.1f];
[self schedule:#selector(moveSprite:) interval:0.1f];
}
}
}
i have 6 images of animating like
dragonimage_blinkk001,dragonimage_blinkk002,dragonimage_blinkk003,dragonimage_blinkk004,dragonimage_blinkk005,dragonimage_blinkk006 like that
i put two methods,
1: for animation time
2: for movement of the image
the code is
-(void) openEyes:(ccTime) delta {
[sprite setTexture:[[CCSprite spriteWithFile:[NSString stringWithFormat:#"%#.png", baseImageName]] texture]];
[self unschedule:_cmd];
int blinkInterval = (arc4random() % 6) + 1; // range 3 to 8
[self schedule:#selector(blink:) interval:blinkInterval];
}
-(void)moveSprite:(ccTime)delta
{
movementCounter ++;
if (movementCounter == 1000) {
[self unschedule:_cmd];
}
else
{
spriteimagename.position = ccp(spriteimagename.position.x+10,spriteimagename.position.y);
}
}
but on the first method the animation time is not correct,there is a lot of delay of animation,i just want to show animation of the images randomly and fast,its a dragon flying animation.
my sec on method is not at all working,i didn't get any movement of that image.
i hope you understand my issue.how to solve the above two method issues.
Thanks in advance.
Quick solution is to add frameIndex member in cocos2d CCSpriteFrame class. i don't know is that allowed to change. But it works fine.
#interface CCSpriteFrame : NSObject <NSCopying>
{
int frameIndex;
....
}
//Here in code initialize frames with unique index
CCAnimation* animation;
NSMutableArray *animFrames2 = [NSMutableArray array];
for( int i=1;i<=15;i++)
{
CCSpriteFrame *frame = [cache spriteFrameByName:[NSString stringWithFormat:#"ActerSmash_%d.png",i]];
frame.frameIndex = (int)i;
[animFrames2 addObject:frame];
}
animation = [CCAnimation animationWithFrames:animFrames2];
CCAnimate *action = [CCAnimate actionWithDuration:ACTER_SMASH_SPEED animation:animation restoreOriginalFrame:YES];
action.tag = kTagAnimationSmashAnim ;
mActer.AnimSmash = action;
//Checking frame Index
CCAnimate *anim = mActer.AnimSmash ;
for(CCSpriteFrame *frame in anim.animation.frames)
{
if([mActer isFrameDisplayed:frame] ) )
{
if(frame.frameIndex == 5 )
{
//Do something..
}
}
}

How to update an object's image in NSMutableArray?

I am trying to set the image of the face down card to the image that the value of the card is. The method in KCCard, image:, returns the image of the card.
- (UIImage *)image:(BOOL)yesOrNo
{
if (!yesOrNo) {
return [UIImage imageNamed:#"back-blue-150-3.png"];
} else {
return [UIImage imageNamed:[NSString stringWithFormat:#"%#-%#-150", [self suitAsString], [self valueAsString]]];
}
}
The code I am using in the deal method is as follows.
int lastDealerX = 437;
//int lastDealerY = 49;
int lastDealerTag = 0;
for (KCCard *aCard in dealerHand) {
if (lastDealerTag == 0) {
KCCardView *cardView = [[KCCardView alloc] initWithFrame:CGRectMake(lastDealerX, 49, 150, 215)];
cardView.backgroundColor = [UIColor blackColor];
cardView.image = [aCard image:NO];
cardView.tag = lastDealerTag;
[self.view addSubview:cardView];
lastDealerTag = lastDealerTag + 1;
lastDealerX = lastDealerX + 42;
} else {
KCCardView *cardView = [[KCCardView alloc] initWithFrame:CGRectMake(lastDealerX, 49, 150, 215)];
cardView.backgroundColor = [UIColor blackColor];
cardView.image = [aCard image:YES];
cardView.tag = lastDealerTag;
[self.view addSubview:cardView];
lastDealerTag = lastDealerTag + 1;
lastDealerX = lastDealerX + 42;
}
}
The KCCardView with tag 0 shows the card face down and the other card is face up. The problem is that when I want the face down card to show, it won't. Here is the show code.
- (IBAction)showCard:(id)sender {
for (UIView *view in self.view.subviews) {
for (KCCard *aCard in dealerHand) {
KCCardView *cardView = (KCCardView *)view;
if (cardView.tag == 0) {
cardView.image = [[dealerHand objectAtIndex:0] image:YES];
}
}
}
}
KCCard is an NSObject, KCCardView is a UIImageView, and dealerHand is an NSMutableArray.
Here is a video showing the build and run: http://aleckazarian.com/misc/Blackjack.mov
Here is the XCode project: http://aleckazarian.com/misc/Blackjack.zip
If you look at the connection in the nib you'll notice that it is connected to
showCard
this is a completely different method to
showCard:
In your class you implement - (IBAction)showCard:(id)sender; therefore you need to break the connection in Interface builder and reconnect it.
Update
The second time I ran your program I got
-[UIRoundedRectButton setImage:]: unrecognized selector sent to instance 0x68612e0
This looks like it's because you are iterating over the view's subviews and checking if 0 == tag. 0 is the default value for tag so essentially mostly every view will respond true unless you have explicitly set the tags to something else. The problem code it
for (UIView *view in self.view.subviews) {
for (KCCard *aCard in dealerHand) {
KCCardView *cardView = (KCCardView *)view;
if (cardView.tag == 0) { // <------- This is the bad check
cardView.image = [((KCCard *)[dealerHand objectAtIndex:0]) image:YES];
}
}
}
To fix this either do one of these (they are in order of my preference - I wouldn't go near 3 or 4 in this case):
Keep a reference to the cardView's in an array
Give the cardView's a non zero tag when they are created
Use respondsToSelector:
Test for the class `[cardView isKindOf:[UIButton class]];
The compiler does not know, what kind of object [dealerHand objectAtIndex:0] is, thus it cannot respond to image:. Try this:
cardView.image = [((KCCard *)[dealerHand objectAtIndex:0]) image:YES];

SneakyJoystick - Movement by certain points/tiles

I have SneakyJoystick up and running but I want to move my sprite tile by tile in a certain frequency ... I am pretty new to iphone programming and cocos2d so I don't exactly know how the whole SneakyJoystick thingy works.
I got the code from a book and again: I just want my Sprite to move like in the game Pokèmon tile by tile...
-(void)initJoystickAndButtons {
CGSize screenSize = [CCDirector sharedDirector].winSize;
CGRect joystickBaseDimensions =
CGRectMake(0, 0, 128.0f, 128.0f);
CGRect jumpButtonDimensions =
CGRectMake(0, 0, 64.0f, 64.0f);
CGRect attackButtonDimensions =
CGRectMake(0, 0, 64.0f, 64.0f);
CGPoint joystickBasePosition;
CGPoint jumpButtonPosition;
CGPoint attackButtonPosition;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
// The device is an iPad running iPhone 3.2 or later.
CCLOG(#"Positioning Joystick and Buttons for iPad");
joystickBasePosition = ccp(screenSize.width*0.0625f,screenSize.height*0.052f);
jumpButtonPosition = ccp(screenSize.width*0.946f,screenSize.height*0.052f);
attackButtonPosition = ccp(screenSize.width*0.947f,screenSize.height*0.169f);
} else {
// The device is an iPhone or iPod touch.
CCLOG(#"Positioning Joystick and Buttons for iPhone");
joystickBasePosition = ccp(screenSize.width*0.07f,
screenSize.height*0.11f);
jumpButtonPosition = ccp(screenSize.width*0.93f,
screenSize.height*0.11f);
attackButtonPosition = ccp(screenSize.width*0.93f,
screenSize.height*0.35f);
}
SneakyJoystickSkinnedBase *joystickBase = [[[SneakyJoystickSkinnedBase alloc] init] autorelease];
joystickBase.position = joystickBasePosition;
joystickBase.backgroundSprite =[CCSprite spriteWithFile:#"dpadDown.png"];
joystickBase.thumbSprite =[CCSprite spriteWithFile:#"joystickDown.png"];
joystickBase.joystick = [[SneakyJoystick alloc]initWithRect:joystickBaseDimensions];
leftJoystick = [joystickBase.joystick retain];
leftJoystick.isDPad = YES;
[self addChild:joystickBase];
SneakyButtonSkinnedBase *jumpButtonBase =[[[SneakyButtonSkinnedBase alloc] init] autorelease];
jumpButtonBase.position = jumpButtonPosition;
jumpButtonBase.defaultSprite =[CCSprite spriteWithFile:#"jumpUp.png"];
jumpButtonBase.activatedSprite =[CCSprite spriteWithFile:#"jumpDown.png"];
jumpButtonBase.pressSprite = [CCSprite spriteWithFile:#"jumpDown.png"];
jumpButtonBase.button = [[SneakyButton alloc]initWithRect:jumpButtonDimensions];
jumpButton = [jumpButtonBase.button retain];
jumpButton.isToggleable = NO;
[self addChild:jumpButtonBase];
SneakyButtonSkinnedBase *attackButtonBase =[[[SneakyButtonSkinnedBase alloc] init] autorelease];
attackButtonBase.position = attackButtonPosition;
attackButtonBase.defaultSprite = [CCSprite spriteWithFile:#"handUp.png"];
attackButtonBase.activatedSprite = [CCSprite spriteWithFile:#"handDown.png"];
attackButtonBase.pressSprite = [CCSprite spriteWithFile:#"handDown.png"];
attackButtonBase.button = [[SneakyButton alloc]initWithRect:attackButtonDimensions];
attackButton = [attackButtonBase.button retain];
attackButton.isToggleable = NO;
[self addChild:attackButtonBase];
> }
> -(void)applyJoystick:(SneakyJoystick *)aJoystick toNode:(CCNode *)tempNode forTimeDelta:(float)deltaTime{
> CGPoint scaledVelocity = ccpMult(aJoystick.velocity, 44.0f); // 1
> CGPoint newPosition = ccp(tempNode.position.x + scaledVelocity.x * deltaTime,tempNode.position.y + scaledVelocity.y * deltaTime);
> [tempNode setPosition:newPosition];
> if (jumpButton.active == YES) {
> CCLOG(#"Jump button is pressed.");
> if (attackButton.active == YES) {
> CCLOG(#"Attack button is pressed.");
> } }
> }
>
> # pragma mark -
> # pragma mark Update Method
> -(void) update:(ccTime)deltaTime {
> [self applyJoystick:leftJoystick toNode:dude
> forTimeDelta:deltaTime];
> }
I did something similar for my game. There are many steps and cannot go much into detail.
First you need to know when is the joystick being used.
Second you need to interpet the direction of the joystick. For a game like Pokemon, you only need to check for up/down/right/left directions. It is possible to access the degrees of the joystick. Simply interpret the degrees like "if degrees are between -45 to 45, it means the joystick is mainly facing right" etc.
Third you will have to unlink the joystick from your player object. That tutorial, somewhere, makes you link both of them so that the joystick will automatically move the player. You have to undo that.
Fourth make up a schedule somewhere in your scene. The schedule will interpret the joystick direction (if it is being used), and will run a CCMoveBy action on the player. If the joystick directs to the right and the map's tile size is 32, then the CCMoveBy movement parameter would be (32,0). Remember to not run a nother action if the player is already running one.
There are many details and so much to polish. You better try to ask each thing individually instead of everything in one shot.

How to Highlight word of UILabel in iphone

I am loading Lyrics of song on UILabel With Timer. Now I want to highlight Each word of that label with different color. How can I do this ?
I am showing lyrics like this
- (void)setCurrentAudioProgress:(NSTimeInterval)time duration:(NSTimeInterval)duration
{
float progress = time/duration;
long currentPlaybackTime = audioPlayer.currentTime;
long remainingTime = (duration-time);
int remainingHours = (remainingTime /3600);
int remainingMinutes = ((remainingTime /60 -remainingHours*60));
int remainingSeconds = (remainingTime %60);
int currentHours = (currentPlaybackTime / 3600);
int currentMinutes = ((currentPlaybackTime / 60) - currentHours*60);
int currentSeconds = (currentPlaybackTime % 60);
currentTimeLabel.text = [NSString stringWithFormat:#"%i:%02d:%02d", currentHours, currentMinutes, currentSeconds];
remainingTimeLabel.text = [NSString stringWithFormat:#"%i.%02d.%02d", remainingHours , remainingMinutes, remainingSeconds];
[progressView setProgress:progress];
for (int i = 0; i<[lyricsArray count]; i++) {
NSString *lyricsTime = [[lyricsArray objectAtIndex:i]valueForKey:#"startTime" ] ;
if ([currentTimeLabel.text isEqualToString:lyricsTime]) {
songLyricsLabel.text = [NSString stringWithFormat:#"%#",[[lyricsArray objectAtIndex:i]valueForKey:#"songLyrics" ]];
}
}
}
You have to use the trick some thing like this one label doesn't support the highlighting
iPhone "slide to unlock" animation
You can use following whenever you want to highlight the label text then just add the following lines for respective label
label.highlighted = YES;
label.highlightedTextColor = [UIColor blueColor];
for different color you can add an array with color names and select randomly....

Cocos2d game termination problem when a moving sprite goes inside the bounding box of a animating still sprite(a ball get into a hole)

Let me explain it in depth, when ever if(CGRectContainsPoint([hole1 boundingBox], ball1.position)) condition goes true, i do lots of stuffs, like unscheduled, a selector, destroying a ball body calling an animation (please refer Code below)etc. This work properly most of the time. But sometimes when ball is really near to hole(just touching the hole but but not enough to make the above condition true), or is been throws towards the hole really fast speed, then application got terminated. I have checked, by commenting many actions which are been performed in this section, but got nothing helpful, application keep terminating when some efforts are been done to make it terminate.
if(CGRectContainsPoint([hole1 boundingBox], ball1.position))
{
ballBody->SetLinearVelocity(b2Vec2(0.0f,0.0f));
ballBody->SetAngularVelocity(0.0f);
[self unschedule:#selector(tick:)];
self.isTouchEnabled = NO;
[self removeChild:ball1 cleanup:YES];
world->DestroyBody(ballBody);
// create the sprite sheet
CCSpriteSheet *spriteSheet;
GolfBallsAppDelegate *appDelegate = (GolfBallsAppDelegate *)[[UIApplication sharedApplication] delegate];
if([appDelegate.ballValue isEqualToString:#"cricketball"])
{
spriteSheet = [CCSpriteSheet spriteSheetWithFile:#"cricket_ball_strip.png"];
}
else if([appDelegate.ballValue isEqualToString:#"ironball"])
{
spriteSheet = [CCSpriteSheet spriteSheetWithFile:#"iron_ball_strip.png"];
}
else if([appDelegate.ballValue isEqualToString:#"golfball"])
{
spriteSheet = [CCSpriteSheet spriteSheetWithFile:#"golf_ball_strip.png"];
}
else if([appDelegate.ballValue isEqualToString:#"soccerball"])
{
spriteSheet = [CCSpriteSheet spriteSheetWithFile:#"soccer_ball_strip.png"];
}
else if([appDelegate.ballValue isEqualToString:#"basketball"])
{
spriteSheet = [CCSpriteSheet spriteSheetWithFile:#"basket_ball_strip.png"];
}
spriteSheet.position = ccp(hole1.position.x,60);
[self addChild:spriteSheet];
float frameWidth = 96;
float frameHeight = 84;
CCSprite *sprite = [CCSprite spriteWithTexture:spriteSheet.texture rect:CGRectMake(0, 0, frameWidth, frameHeight)];
[spriteSheet addChild:sprite];
//if(animation)
{
// create the animation
CCAnimation *spriteAnimation = [CCAnimation animationWithName:#"potting" delay:0.1f];
int frameCount = 0;
for (int x = 0; x < 6; x++)
{
// create an animation frame
CCSpriteFrame *frame = [CCSpriteFrame frameWithTexture:spriteSheet.texture rect:CGRectMake(x*frameWidth,0*frameHeight,frameWidth,frameHeight) offset:ccp(0,0)];
[spriteAnimation addFrame:frame];
frameCount++;
// stop looping after we've added 14 frames
if (frameCount == 6)
{
//[self removeChild:spriteSheet cleanup:YES];
break;
}
}
// create the action
CCAnimate *spriteAction = [CCAnimate actionWithAnimation:spriteAnimation];
//CCRepeatForever *repeat = [CCRepeatForever actionWithAction:spriteAction];
// run the action
[sprite runAction:spriteAction];
//[sprite runAction:repeat];
}
[self schedule:#selector(loading) interval:0.5];
[self schedule:#selector(holeFinish) interval:1];
//[self removeChild:spriteSheet cleanup:YES];
}
Any suggestion will be highly appreciated.
EDIT: What i found is, problem with folling lines [self removeChild:ball1 cleanup:YES];
world->DestroyBody(ballBody);
(MAY be). but as it not occurs always, (as I mentioned), thus it's being ridiculous.
I think your problem will be that you are trying to delete a body when the b2World is 'locked', (When the world is busy working out collisions).
Try flagging the object as ready for deletion, and deleting it at the start of your next loop:
Replace:
[self removeChild:ball1 cleanup:YES];
world->DestroyBody(ballBody);
with
ball1.isDead = YES;
And at the start of your next game loop:
for (Ball b in balls)
{
if (b.isDead)
world->DestroyBody(b.ballBody);
}