// // TutorialMode.m // Cart Collect // // Created by Starla Insigna on 8/10/11. // Copyright 2011 Four Island. All rights reserved. // #import "TutorialMode.h" #import "FallingObject.h" #import "GameModeSelectionLayer.h" #import "SimpleAudioEngine.h" #import "ClassicGameMode.h" // Item tags: // 2000 - first dropped item // 2001 - item that is dropped after you catch first dropped item to demonstrate what happens when you miss // 2002 - items that are dropped after you miss first dropped item to demonstrate what happens when you catch // 2003 - 1-Up // 2009 - rock // 2010 - random item dropped after death from first rock typedef enum { kCherryObject = 0, kEnergyDrinkObject, kOneUpObject, kRockObject } FallingObjects; @implementation TutorialMode @synthesize currentTutorial; static GameModeInfo* info; + (GameModeInfo*)info { if (info == nil) { info = [[GameModeInfo alloc] initWithName:@"Tutorial" location:@"Florence" numOfStars:0 imageFilename:[[NSBundle mainBundle] pathForResource:@"florence" ofType:@"png"] unlocked:YES unlockCondition:nil gameClass:[TutorialMode class] globalHighscoreKey:nil starsToUnlock:0]; } return info; } - (id)init { self = [super init]; if (nil != self) { CCSprite* backgroundImage = [CCSprite spriteWithFile:@"SeaBeach.png"]; backgroundImage.position = ccp(240, 160); [self addChild:backgroundImage z:-1]; showedDeathBubble = NO; randomItemsDropped = 0; [objectFactory createRecipeWithIdentifier:kCherryObject spriteFilename:@"cherry.png" weight:5]; [objectFactory createRecipeWithIdentifier:kEnergyDrinkObject spriteFilename:@"bottle.png" weight:6]; [objectFactory createRecipeWithIdentifier:kOneUpObject spriteFilename:@"oneup.png" weight:10]; [objectFactory createRecipeWithIdentifier:kRockObject spriteFilename:@"rock.png" weight:7]; } return self; } - (void)onEnterTransitionDidFinish { [super onEnterTransitionDidFinish]; [self scheduleDelayedAction:^{ TutorialBubble* bubble = [[TutorialBubble alloc] initWithText:@"Welcome to Cartographic. This is a tutorial designed to help you get started playing the game. Below this bubble is a cart. Tilt your device to move it." name:@"cart" spriteReference:cart.sprite]; self.currentTutorial = bubble; [bubble release]; } delay:2.0f]; } - (void)tick:(ccTime)dt { [super tick:dt]; FallingObject* object = [objects anyObject]; if ((object.sprite.tag == 2000) && (object.sprite.position.y == 360-object.weight*14)) { TutorialBubble* bubble = [[TutorialBubble alloc] initWithText:@"This is an item. Try to catch it with your cart." name:@"item" spriteReference:object.sprite]; self.currentTutorial = bubble; [bubble release]; } else if ((object.sprite.tag == 2003) && (object.sprite.position.y == 360-object.weight*8)) { TutorialBubble* bubble = [[TutorialBubble alloc] initWithText:@"This is a 1-Up. Catch it to gain an extra life. There's no penalty for not catching it, though." name:@"oneup" spriteReference:object.sprite]; self.currentTutorial = bubble; [bubble release]; } else if ((object.sprite.tag == 2009) && (object.sprite.position.y == 360-object.weight*14)) { TutorialBubble* bubble = [[TutorialBubble alloc] initWithText:@"This is a rock. It would be better for your health if you did not catch this item." name:@"rock" spriteReference:object.sprite]; self.currentTutorial = bubble; [bubble release]; } } - (void)didCatchItem:(FallingObject *)item { if (item.objectType == kCherryObject) { [[SimpleAudioEngine sharedEngine] playEffect:[[NSBundle mainBundle] pathForResource:@"Item1" ofType:@"wav"]]; self.score += 10; } else if (item.objectType == kEnergyDrinkObject) { [[SimpleAudioEngine sharedEngine] playEffect:[[NSBundle mainBundle] pathForResource:@"Item1" ofType:@"wav"]]; self.score += 25; } else if (item.objectType == kOneUpObject) { [[SimpleAudioEngine sharedEngine] playEffect:[[NSBundle mainBundle] pathForResource:@"1up" ofType:@"wav"]]; self.lives++; } else if (item.objectType == kRockObject) { [[SimpleAudioEngine sharedEngine] playEffect:[[NSBundle mainBundle] pathForResource:@"Damage1" ofType:@"wav"]]; self.lives--; } if (item.sprite.tag == 2000) { TutorialBubble* bubble = [[TutorialBubble alloc] initWithText:@"Congratulations! If you look at your score, you'll see it increased. Catching items is good. Now, let's see what happens when you don't catch an item." name:@"caught-first"]; self.currentTutorial = bubble; [bubble release]; } else if (item.sprite.tag == 2002) { TutorialBubble* bubble = [[TutorialBubble alloc] initWithText:@"There you go! If you look at your score, you'll see it increased. Catching items is good." name:@"caught-second"]; self.currentTutorial = bubble; [bubble release]; } } - (void)didMissItem:(FallingObject *)item { if ((item.objectType == kCherryObject) || (item.objectType == kEnergyDrinkObject)) { [[SimpleAudioEngine sharedEngine] playEffect:[[NSBundle mainBundle] pathForResource:@"Damage1" ofType:@"wav"]]; self.lives--; } if (item.sprite.tag == 2000) { TutorialBubble* bubble = [[TutorialBubble alloc] initWithText:@"Whoops, you missed it! Look at your lives counter--you lost one! If you lose all of your lives, you lose the game. Try catching the item again." name:@"missed-first"]; self.currentTutorial = bubble; [bubble release]; } else if (item.sprite.tag == 2001) { [cart setImmobile:NO]; TutorialBubble* bubble = [[TutorialBubble alloc] initWithText:@"You lost a life! You only have three lives, so try not to miss any items! However..." name:@"missed-second"]; self.currentTutorial = bubble; [bubble release]; } else if (item.sprite.tag == 2002) { [self scheduleDelayedAction:^{ FallingObject* object = [self dropRandomItem]; object.sprite.tag = 2002; } delay:1.0f]; } } - (void)didDestroyItem:(FallingObject *)item { if (item.sprite.tag == 2003) { [self schedule:@selector(randomlyAddObject:) interval:2.5f]; } else if (item.sprite.tag == 2009) { if ((lives < 1) && (!showedDeathBubble)) { showedDeathBubble = YES; TutorialBubble* bubble = [[TutorialBubble alloc] initWithText:@"You lost all your lives! Normally, you'd be taken to a game over screen where you could submit your score to the highscore list, but we're a bit more forgiving in tutorial mode." name:@"gameover-rock"]; self.currentTutorial = bubble; [bubble release]; } else { TutorialBubble* bubble = [[TutorialBubble alloc] initWithText:@"As you play, Cartographic gets progressively more intense. Watch what happens when rocks are added to the mix and the speed is turned up." name:@"intense"]; self.currentTutorial = bubble; [bubble release]; } } else if (item.sprite.tag == 2010) { TutorialBubble* bubble = [[TutorialBubble alloc] initWithText:@"As you play, Cartographic gets progressively more intense. Watch what happens when rocks are added to the mix and the speed is turned up." name:@"intense"]; self.currentTutorial = bubble; [bubble release]; } if ((lives < 1) && (!showedDeathBubble)) { showedDeathBubble = YES; TutorialBubble* bubble = [[TutorialBubble alloc] initWithText:@"You lost all your lives! Normally, you'd be taken to a game over screen where you could submit your score to the highscore list, but we're a bit more forgiving in tutorial mode." name:@"gameover"]; self.currentTutorial = bubble; [bubble release]; } } - (void)setCurrentTutorial:(TutorialBubble *)m_currentTutorial { @synchronized(self) { if (currentTutorial != m_currentTutorial) { [currentTutorial removeFromSuperview]; [currentTutorial release]; currentTutorial = [m_currentTutorial retain]; } } if (currentTutorial != nil) { [currentTutorial setTarget:self action:@selector(endTutorial)]; [[[CCDirector sharedDirector] openGLView] addSubview:currentTutorial]; [self pauseSchedulerAndActions]; } } - (void)endTutorial { [self resumeSchedulerAndActions]; if ([currentTutorial.name isEqual:@"cart"]) { [self scheduleDelayedAction:^{ FallingObject* object = [self dropRandomItem]; object.sprite.tag = 2000; } delay:3.0f]; } else if ([currentTutorial.name isEqual:@"caught-first"]) { [cart setImmobile:YES]; [self scheduleDelayedAction:^{ FallingObject* object = [self dropRandomItem]; if (cart.sprite.position.x > 240) { object.sprite.position = ccp(20, 360); } else { object.sprite.position = ccp(460, 360); } object.sprite.tag = 2001; } delay:1.0f]; } else if ([currentTutorial.name isEqual:@"missed-first"]) { [self scheduleDelayedAction:^{ FallingObject* object = [self dropRandomItem]; object.sprite.tag = 2002; } delay:1.0f]; } else if (([currentTutorial.name isEqual:@"caught-second"]) || ([currentTutorial.name isEqual:@"missed-second"])) { [self scheduleDelayedAction:^{ FallingObject* object = [self dropSpecificItem:kOneUpObject]; object.sprite.tag = 2003; } delay:2.0f]; } else if ([currentTutorial.name isEqual:@"gameover-rock"]) { [self scheduleDelayedAction:^{ FallingObject* object = [self dropRandomItem]; object.sprite.tag = 2010; } delay:1.0f]; } else if ([currentTutorial.name isEqual:@"intense"]) { [self schedule:@selector(randomlyAddObject:) interval:1.0f]; } else if ([currentTutorial.name isEqual:@"end"]) { [[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:3.0f scene:[GameModeSelectionLayer scene] withColor:ccc3(0,0,0)]]; } self.currentTutorial = nil; } - (void)pause { if (self.currentTutorial != nil) { [self.currentTutorial removeFromSuperview]; } [super pause]; } - (void)unpause { [super unpause]; if (self.currentTutorial != nil) { [self pauseSchedulerAndActions]; [[[CCDirector sharedDirector] openGLView] addSubview:self.currentTutorial]; } } - (FallingObject*)dropSpecificItem:(int)objectType { FallingObject* object = [[objectFactory buildFallingObjectWithRecipeIdentifier:objectType] retain]; int objectX = arc4random()%448+16; object.sprite.position = ccp(objectX, 360); object.sprite.scale = 1; [self addChild:object.sprite]; object.delegate = self; [objects addObject:object]; return [object autorelease]; } - (FallingObject*)dropRandomItem { int randomval = arc4random()%100; int recipeIdentifier; if (randomval < 65) { recipeIdentifier = kCherryObject; } else { recipeIdentifier = kEnergyDrinkObject; } return [self dropSpecificItem:recipeIdentifier]; } - (void)randomlyAddObject:(ccTime)dt { int recipeIdentifier; if (randomItemsDropped < 5) { int randomval = arc4random()%100; if (randomval < 65) { recipeIdentifier = kCherryObject; } else if (randomval < 98) { recipeIdentifier = kEnergyDrinkObject; } else { recipeIdentifier = kOneUpObject; } } else if (randomItemsDropped == 5) { recipeIdentifier = kRockObject; [self unschedule:@selector(randomlyAddObject:)]; } else if (randomItemsDropped < 15) { int randomval = arc4random()%100; if (randomval < 40) { recipeIdentifier = kCherryObject; } else if (randomval < 70) { recipeIdentifier = kRockObject; } else if (randomval < 98) { recipeIdentifier = kEnergyDrinkObject; } else { recipeIdentifier = kOneUpObject; } } else if (randomItemsDropped == 15) { [self scheduleDelayedAction:^{ TutorialBubble* bubble = [[TutorialBubble alloc] initWithText:@"That's pretty much it! You've completed the tutorial, so now it's time to play an actual game of Cartographic!" name:@"end"]; self.currentTutorial = bubble; [bubble release]; } delay:2.0f]; [self unschedule:@selector(randomlyAddObject:)]; [[ClassicGameMode info] unlock]; return; } else { NSLog(@"randomItemsDropped in TutorialMode is greater than 15--this should never happen."); return; } FallingObject* object = [self dropSpecificItem:recipeIdentifier]; if (randomItemsDropped == 5) { object.sprite.tag = 2009; } randomItemsDropped++; } @end