// // JumpGameMode.m // Cart Collect // // Created by Starla Insigna on 8/17/11. // Copyright 2011 Four Island. All rights reserved. // #import "JumpGameMode.h" #import "SimpleAudioEngine.h" #import "FallingObject.h" #import "Cherry.h" #import "Bottle.h" #import "OneUp.h" #import "Rock.h" #import "GameOverScene.h" #import "PointMultiplier.h" #define kMinimumGestureLength 25 @interface LedgeFactory : NSObject { UIImage* leftSprite; UIImage* midSprite; UIImage* rightSprite; UIImage* singleSprite; } - (id)init; - (UIImage*)createLedgeWithWidth:(int)width height:(int)height; @end @implementation FallingObject (Flags) - (BOOL)fellDuringWave { return flags[0]; } - (void)setFellDuringWave:(BOOL)value { flags[0] = value; } @end @implementation JumpGameMode - (id)init { self = [super init]; if (nil != self) { CCSprite* backgroundImage = [CCSprite spriteWithFile:@"SeaBeach.png"]; backgroundImage.position = ccp(240, 160); [self addChild:backgroundImage z:-1]; water = [CCSprite spriteWithFile:@"water.png"]; water.position = ccp(240, -60); [self addChild:water]; cart.sprite.position = ccp(120, 22+64); //86 cart.falling = YES; cart.delegate = self; self.isTouchEnabled = YES; waterTick = 0; wave = NO; factory = [[LedgeFactory alloc] init]; ledges = [[NSMutableSet alloc] init]; CCTexture2D* texture = [[CCTexture2D alloc] initWithImage:[factory createLedgeWithWidth:6 height:2]]; CCSprite* ledge = [CCSprite spriteWithTexture:texture]; ledge.position = ccp(80, 32); [self addChild:ledge]; [ledges addObject:ledge]; [texture release]; CCSprite* firstLedge = ledge; texture = [[CCTexture2D alloc] initWithImage:[factory createLedgeWithWidth:10 height:2]]; ledge = [CCSprite spriteWithTexture:texture]; ledge.position = ccp(80 + firstLedge.boundingBox.size.width/2 + ledge.boundingBox.size.width/2+64, 32); [self addChild:ledge]; [ledges addObject:ledge]; [texture release]; ledgeScrollSpeed = 0; ledgeAccelerationRate = 20.0f; addSpeed = 2.5f; } return self; } - (void)onEnterTransitionDidFinish { [super onEnterTransitionDidFinish]; [self schedule:@selector(accelerateGame) interval:ledgeAccelerationRate]; [self schedule:@selector(randomlyAddObject:) interval:addSpeed]; [self schedule:@selector(incrementScore) interval:1.0f]; [self scheduleDelayedAction:^{ wave = YES; } delay:60.0f]; } - (void)tick:(ccTime)dt { NSMutableSet* discardedSet = [NSMutableSet set]; int rightmost = 0; int rightwidth = 0; for (CCSprite* sprite in ledges) { sprite.position = ccp(sprite.position.x - ledgeScrollSpeed, sprite.position.y); if ((sprite.position.x + sprite.boundingBox.size.width/2) < 0) { [discardedSet addObject:sprite]; [self removeChild:sprite cleanup:YES]; } if (sprite.position.x > rightmost) { rightmost = sprite.position.x; rightwidth = sprite.boundingBox.size.width/2; } } [ledges minusSet:discardedSet]; NSMutableSet* discardedObjects = [NSMutableSet set]; for (FallingObject* object in objects) { if (object.sprite.position.y < (64+object.sprite.boundingBox.size.height/2)) { for (CCSprite* ledge in ledges) { CGSize first = [object.sprite boundingBox].size; CGSize second = [ledge boundingBox].size; if (object.sprite.position.x > (ledge.position.x - second.width/2 - first.width/2)) { if (object.sprite.position.x < (ledge.position.x + second.width/2 + first.width/2)) { if (object.sprite.position.y > (ledge.position.y - second.height/2 - first.height/2)) { if (object.sprite.position.y < (ledge.position.y + second.height/2 + first.height/2)) { [discardedObjects addObject:object]; } } } } } } if (object.fellDuringWave) { object.sprite.position = ccp(object.sprite.position.x, MAX(object.sprite.position.y, water.position.y+80+11)); } else { object.sprite.position = ccp(object.sprite.position.x-ledgeScrollSpeed, object.sprite.position.y); } } [objects minusSet:discardedObjects]; if (rightmost <= 480) { int ledgeWidth = arc4random() % 9 + 1; int ledgeDistance = arc4random() % (ledgeScrollSpeed*ledgeScrollSpeed+1)*3/2; CCTexture2D* texture = [[CCTexture2D alloc] initWithImage:[factory createLedgeWithWidth:ledgeWidth height:2]]; CCSprite* ledge = [CCSprite spriteWithTexture:texture]; ledge.position = ccp(rightmost + rightwidth + ledge.boundingBox.size.width/2+64+ledgeDistance, 32); [self addChild:ledge]; [ledges addObject:ledge]; [texture release]; } if ([self cartIsObstructed:cart]) { cart.sprite.position = ccp(cart.sprite.position.x-ledgeScrollSpeed, cart.sprite.position.y); } [super tick:dt]; if ((cart.sprite.position.y < 86) && (cart.boundedByScreen)) { cart.boundedByScreen = NO; } else if ((cart.sprite.position.y >= 86) && (!cart.boundedByScreen)) { cart.boundedByScreen = YES; } if (cart.sprite.position.y == (0-cart.sprite.boundingBox.size.height/2)) { [self setLives:self.lives-1]; cart.boundedByScreen = YES; [[SimpleAudioEngine sharedEngine] playEffect:[[NSBundle mainBundle] pathForResource:@"Damage1" ofType:@"wav"]]; if (cart.sprite.position.x < cart.sprite.boundingBox.size.width/2) { cart.sprite.position = ccp(cart.sprite.boundingBox.size.width, 320 + cart.sprite.boundingBox.size.height/2); } else { cart.sprite.position = ccp(cart.sprite.position.x, 320 + cart.sprite.boundingBox.size.height/2); } } if (lives <= 0) { [self unscheduleAllSelectors]; [[CCDirector sharedDirector] replaceScene:[CCTransitionSlideInT transitionWithDuration:1.5f scene:[GameOverScene sceneWithScore:score gameMode:@"Jump"]]]; } if (wave) { waterTick++; water.position = ccp(240, 140 * sin(waterTick / (36 * M_PI)) - 60); if (waterTick == 180) { wave = NO; [self scheduleDelayedAction:^{ wave = YES; } delay:10.0f]; } else if (waterTick == 360) { wave = NO; waterTick = 0; [self scheduleDelayedAction:^{ wave = YES; } delay:60.0f]; } } if (jump) { jumpTick++; cart.sprite.position = ccp(cart.sprite.position.x, MAX(100 * sin(jumpTick / (2 * M_PI)) + 86, water.position.y+80+11)); if (jumpTick == 20) { jump = NO; jumpTick = 0; cart.falling = YES; } } } - (void)ccTouchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { if ((!isPaused) && (!isGesturing)) { UITouch* touch = [touches anyObject]; gestureStartPoint = [touch locationInView:nil]; isGesturing = YES; } } - (void)ccTouchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { if (isGesturing) { UITouch* touch = [touches anyObject]; CGPoint gestureCurrentPosition = [touch locationInView:nil]; CGFloat angle = atan2f(gestureCurrentPosition.y - gestureStartPoint.y, gestureCurrentPosition.x - gestureStartPoint.x); CGFloat distance = sqrt(powf((gestureCurrentPosition.x - gestureStartPoint.x),2) + powf((gestureCurrentPosition.y - gestureStartPoint.y),2)); if ((distance >= kMinimumGestureLength) && (angle >= expectedAngle - M_PI_4) && (angle <= expectedAngle + M_PI_4) && ((cart.sprite.position.y >= 80) && (cart.sprite.position.y <= 90))) { jump = YES; cart.falling = NO; } } } - (void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { isGesturing = NO; } - (int)cartShouldFall:(Cart *)m_cart { int bottom = 0-m_cart.sprite.boundingBox.size.height/2; for (CCSprite* sprite in ledges) { CGSize first = [m_cart.sprite boundingBox].size; CGSize second = [sprite boundingBox].size; if (m_cart.sprite.position.x > (sprite.position.x - second.width/2 - first.width/2)) { if (m_cart.sprite.position.x < (sprite.position.x + second.width/2 + first.width/2)) { bottom = sprite.position.y + second.height/2 + first.height/2; break; } } } if (waterTick > 0) { bottom = MAX(water.position.y+80+11, bottom); } return bottom; } - (BOOL)cartIsObstructed:(Cart *)m_cart { for (CCSprite* sprite in ledges) { CGSize first = [m_cart.sprite boundingBox].size; CGSize second = [sprite boundingBox].size; if (m_cart.sprite.position.x > (sprite.position.x - second.width/2 - first.width/2)) { if (m_cart.sprite.position.x < (sprite.position.x + second.width/2 + first.width/2)) { if (m_cart.sprite.position.y > (sprite.position.y - second.height/2 - first.height/2)) { if (m_cart.sprite.position.y < (sprite.position.y + second.height/2 + first.height/2)) { return YES; } } } } } return NO; } - (void)accelerateGame { [self unschedule:@selector(accelerateGame)]; [self unschedule:@selector(randomlyAddObject:)]; ledgeScrollSpeed += 2; ledgeAccelerationRate *= 2; addSpeed *= 0.8f; [self schedule:@selector(randomlyAddObject:) interval:addSpeed]; [self schedule:@selector(accelerateGame) interval:ledgeAccelerationRate]; } - (void)randomlyAddObject:(ccTime)dt { FallingObject* object; int randomval = arc4random()%100; int pmChance = (5-pointMultiplier)*5 + 30; if (randomval < 30) { object = [[OneUp alloc] init]; } else if (randomval < pmChance) { object = [[PointMultiplier alloc] init]; } else { object = [[Rock alloc] init]; } int objectX; CGSize first = [cart.sprite boundingBox].size; CGSize second = [object.sprite boundingBox].size; for (;;) { objectX = arc4random()%448+16; if (waterTick == 0) { break; } if (cart.sprite.position.x > (objectX - second.width/2 - first.width/2)) { if (cart.sprite.position.x < (objectX + second.width/2 + first.width/2)) { continue; } } break; } object.sprite.position = ccp(objectX, 360); object.sprite.scale = 1; object.fellDuringWave = waterTick > 0; [self addChild:object.sprite]; [objects addObject:object]; [object release]; if (score >= 240) { if (arc4random() % 100 > 80) { object = [[Rock alloc] init]; for (;;) { objectX = arc4random()%448+16; if (waterTick == 0) { break; } if (cart.sprite.position.x > (objectX - second.width/2 - first.width/2)) { if (cart.sprite.position.x < (objectX + second.width/2 + first.width/2)) { continue; } } break; } object.sprite.position = ccp(objectX, 360); object.sprite.scale = 1; object.fellDuringWave = waterTick > 0; [self addChild:object.sprite]; [objects addObject:object]; [object release]; } } if (score >= 480) { if (arc4random() % 100 > 80) { object = [[Rock alloc] init]; for (;;) { objectX = arc4random()%448+16; if (waterTick == 0) { break; } if (cart.sprite.position.x > (objectX - second.width/2 - first.width/2)) { if (cart.sprite.position.x < (objectX + second.width/2 + first.width/2)) { continue; } } break; } object.sprite.position = ccp(objectX, 360); object.sprite.scale = 1; object.fellDuringWave = waterTick > 0; [self addChild:object.sprite]; [objects addObject:object]; [object release]; } } } - (void)incrementScore { [self setScore:self.score+pointMultiplier]; } - (void)setLives:(int)m_lives { int oldLives = lives; [super setLives:m_lives]; if (oldLives > lives) { [self setPointMultiplier:1]; } } - (void)setPitch:(double)m_pitch { [super setPitch:m_pitch]; expectedAngle = pitch*M_PI_2; } @end @implementation LedgeFactory - (id)init { self = [super init]; CGImageRef framestuff = [[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ledge" ofType:@"png"]] CGImage]; CGImageRef leftRef = CGImageCreateWithImageInRect(framestuff, CGRectMake(0, 0, 32, 32)); CGImageRef midRef = CGImageCreateWithImageInRect(framestuff, CGRectMake(32, 0, 32, 32)); CGImageRef rightRef = CGImageCreateWithImageInRect(framestuff, CGRectMake(64, 0, 32, 32)); CGImageRef singleRef = CGImageCreateWithImageInRect(framestuff, CGRectMake(96, 0, 32, 32)); leftSprite = [[UIImage alloc] initWithCGImage:leftRef]; midSprite = [[UIImage alloc] initWithCGImage:midRef]; rightSprite = [[UIImage alloc] initWithCGImage:rightRef]; singleSprite = [[UIImage alloc] initWithCGImage:singleRef]; CGImageRelease(leftRef); CGImageRelease(midRef); CGImageRelease(rightRef); CGImageRelease(singleRef); return self; } - (UIImage*)createLedgeWithWidth:(int)width height:(int)height { NSAssert(width > 0, @"Ledge width must be greater than 0"); NSAssert(height > 0, @"Ledge height must be greater than 0"); UIGraphicsBeginImageContext(CGSizeMake(width*32, height*32)); for (int y=0; y