From d19677f9f73d8fe7436982bdf8d40f69d69d1b43 Mon Sep 17 00:00:00 2001 From: Starla Insigna Date: Fri, 12 Aug 2011 09:51:50 -0400 Subject: Added tutorial mode GameLayer was also renamed to ClassicGameMode and its pause functionality and score/lives counters were moved out to GameMode. FallingObjectDelegate was created to allow for custom code to be run when items were caught/missed, something that is used extensively by tutorial mode. Important: Cart Collect's bundle identifier was changed in this revision from com.fourisland.Cart-Collect to com.apatheticink.Cart-Collect, so ensure that before attempting to compile/run this build, you clear your build directory and remove the old version of Cart Collect from your device. Closes #193 --- Classes/TutorialMode.m | 349 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 349 insertions(+) create mode 100644 Classes/TutorialMode.m (limited to 'Classes/TutorialMode.m') diff --git a/Classes/TutorialMode.m b/Classes/TutorialMode.m new file mode 100644 index 0000000..37e8bd0 --- /dev/null +++ b/Classes/TutorialMode.m @@ -0,0 +1,349 @@ +// +// 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 "Cherry.h" +#import "Bottle.h" +#import "OneUp.h" +#import "Rock.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 + +@implementation TutorialMode + +@synthesize currentTutorial; + +- (id)init +{ + self = [super init]; + + if (nil != self) + { + CCSprite* backgroundImage = [CCSprite spriteWithFile:@"SeaBeach.png"]; + backgroundImage.position = ccp(240, 160); + [self addChild:backgroundImage z:-1]; + + CCMenuItemImage* menuItem1 = [CCMenuItemImage itemFromNormalImage:@"skiptutorial.png" selectedImage:@"skiptutorial2.png" target:self selector:@selector(skipTutorial)]; + CCMenu* theMenu = [CCMenu menuWithItems:menuItem1, nil]; + theMenu.position = ccp(480-16-16-62, 320-8-16); + [self addChild:theMenu]; + + showedDeathBubble = NO; + randomItemsDropped = 0; + } + + return self; +} + +- (void)onEnterTransitionDidFinish +{ + [super onEnterTransitionDidFinish]; + + [self scheduleDelayedAction:^{ + TutorialBubble* bubble = [[TutorialBubble alloc] initWithText:@"Welcome to Cart Collect. 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.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.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; + [object release]; + } 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) + { + TutorialBubble* bubble = [[TutorialBubble alloc] initWithText:@"As you play, Cart Collect 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]; + } +} + +- (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; + [object release]; + } 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; + + [object release]; + } delay:1.0f]; + } else if ([currentTutorial.name isEqual:@"missed-first"]) + { + [self scheduleDelayedAction:^{ + FallingObject* object = [self dropRandomItem]; + object.sprite.tag = 2002; + [object release]; + } delay:1.0f]; + } else if (([currentTutorial.name isEqual:@"caught-second"]) || ([currentTutorial.name isEqual:@"missed-second"])) + { + [self scheduleDelayedAction:^{ + FallingObject* object = [self dropSpecificItem:[[OneUp alloc] init]]; + object.sprite.tag = 2003; + [object release]; + } delay:2.0f]; + } else if ([currentTutorial.name isEqual:@"intense"]) + { + [self schedule:@selector(randomlyAddObject:) interval:1.0f]; + } else if ([currentTutorial.name isEqual:@"end"]) + { + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + [defaults setBool:YES forKey:@"hasDoneTutorial"]; + + [[CCDirector sharedDirector] replaceScene:[CCTransitionFade transitionWithDuration:3.0f scene:[ClassicGameMode 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:(FallingObject*)object +{ + 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; +} + +- (FallingObject*)dropRandomItem +{ + FallingObject* object; + int randomval = arc4random()%100; + + if (randomval < 65) + { + object = [[Cherry alloc] init]; + } else { + object = [[Bottle alloc] init]; + } + + return [self dropSpecificItem:object]; +} + +- (void)setLives:(int)m_lives +{ + [super setLives:m_lives]; + + 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)randomlyAddObject:(ccTime)dt +{ + FallingObject* object; + + if (randomItemsDropped < 5) + { + int randomval = arc4random()%100; + + if (randomval < 65) + { + object = [[Cherry alloc] init]; + } else if (randomval < 98) + { + object = [[Bottle alloc] init]; + } else { + object = [[OneUp alloc] init]; + } + } else if (randomItemsDropped == 5) + { + object = [[Rock alloc] init]; + object.sprite.tag = 2009; + + [self unschedule:@selector(randomlyAddObject:)]; + } else if (randomItemsDropped < 15) { + int randomval = arc4random()%100; + + if (randomval < 40) + { + object = [[Cherry alloc] init]; + } else if (randomval < 70) + { + object = [[Rock alloc] init]; + } else if (randomval < 98) + { + object = [[Bottle alloc] init]; + } else { + object = [[OneUp alloc] init]; + } + } 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 Cart Collect!" name:@"end"]; + self.currentTutorial = bubble; + [bubble release]; + } delay:2.0f]; + + [self unschedule:@selector(randomlyAddObject:)]; + + return; + } else { + NSLog(@"randomItemsDropped in TutorialMode is greater than 15--this should never happen."); + + return; + } + + [self dropSpecificItem:object]; + [object release]; + + randomItemsDropped++; +} + +- (void)skipTutorial +{ + [self unscheduleAllSelectors]; + self.currentTutorial = nil; + + NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; + [defaults setBool:YES forKey:@"hasDoneTutorial"]; + + [[CCDirector sharedDirector] replaceScene:[CCTransitionFlipY transitionWithDuration:1.0f scene:[ClassicGameMode scene]]]; +} + +@end -- cgit 1.4.1