Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma mark update
- -(void) update:(ccTime)delta
- {
- // Keep adding up the playerVelocity to the player's position
- // This requires a temporary variable because you can't modify player.position.x directly. Objective-C properties
- // work a little different than what you may be used to from other languages. The problem is that player.position
- // actually is a method call [player position] and you simply can't change a member ".x" of that method. In other words,
- // you can't change members of struct properties like CGPoint, CGRect, CGSize directly through a property getter method.
- CGPoint pos = player.position;
- pos.x += playerVelocity.x;
- // Alternatively you could re-write the above 3 lines as follows. I find the above more readable however.
- // player.position = CGPointMake(player.position.x + playerVelocity.x, player.position.y);
- // The seemingly obvious alternative won't work in Objective-C! It'll give you the following error.
- // ERROR: lvalue required as left operand of assignment
- // player.position.x += playerVelocity.x;
- // The Player should also be stopped from going outside the screen
- CGSize screenSize = [[CCDirector sharedDirector] winSize];
- float imageWidthHalved = [player texture].contentSize.width * 0.5f;
- float leftBorderLimit = imageWidthHalved;
- float rightBorderLimit = screenSize.width - imageWidthHalved;
- // the left/right border check is performed against half the player image's size so that the sides of the actual
- // sprite are blocked from going outside the screen because the player sprite's position is at the center of the image
- if (pos.x < leftBorderLimit)
- {
- pos.x = leftBorderLimit;
- // also set velocity to zero because the player is still accelerating towards the border
- playerVelocity = CGPointZero;
- }
- else if (pos.x > rightBorderLimit)
- {
- pos.x = rightBorderLimit;
- // also set velocity to zero because the player is still accelerating towards the border
- playerVelocity = CGPointZero;
- }
- // Alternatively, the above if/else if block can be rewritten using fminf and fmaxf more neatly like so:
- // pos.x = fmaxf(fminf(pos.x, rightBorderLimit), leftBorderLimit);
- player.position = pos;
- // Do the collision checks
- [self checkForCollision];
- // Update the Score (Timer) once per second. If you'd do it more often, especially every frame, this
- // will easily drag the framerate down. Updating a CCLabel's strings is slow!
- totalTime += delta;
- int currentTime = (int)totalTime;
- if (score < currentTime)
- {
- score = currentTime;
- [scoreLabel setString:[NSString stringWithFormat:@"%i", score]];
- }
- }
- #pragma mark Collision Checks
- -(void) checkForCollision
- {
- // Assumption: both player and spider images are squares.
- float playerImageSize = [player texture].contentSize.width;
- float spiderImageSize = [[spiders lastObject] texture].contentSize.width;
- // If you adjust the factors make sure you also change them in the -(void) draw method.
- float playerCollisionRadius = playerImageSize * 0.4f;
- float spiderCollisionRadius = spiderImageSize * 0.4f;
- // This collision distance will roughly equal the image shapes.
- float maxCollisionDistance = playerCollisionRadius + spiderCollisionRadius;
- // Cache [spiders count] for the duration of the loop to avoid repetitive and unnecessary calls to [spiders count].
- int numSpiders = [spiders count];
- for (int i = 0; i < numSpiders; i++)
- {
- CCSprite* spider = [spiders objectAtIndex:i];
- if ([spider numberOfRunningActions] == 0)
- {
- // This spider isn't even moving so we can skip checking it.
- continue;
- }
- // Get the distance between player and spider. Here's where it's great that the images are centered
- // on the node positions, you don't need to take into account any offsets which you would have if the
- // position would coincide with the image's lower left corner for example.
- float actualDistance = ccpDistance(player.position, spider.position);
- // Are the two objects closer than allowed?
- if (actualDistance < maxCollisionDistance)
- {
- [[SimpleAudioEngine sharedEngine] playEffect:@"alien-sfx.caf"];
- // No game over yet, just reset the game.
- [self showGameOver];
- }
- }
- }
- #pragma mark Reset Game
- // The game is played only using the accelerometer. The screen may go dark while playing because the player
- // won't touch the screen. This method allows the screensaver to be disabled during gameplay.
- -(void) setScreenSaverEnabled:(bool)enabled
- {
- UIApplication *thisApp = [UIApplication sharedApplication];
- thisApp.idleTimerDisabled = !enabled;
- }
- -(void) showGameOver
- {
- // Re-enable screensaver, to prevent battery drain in case the user puts the device aside without turning it off.
- [self setScreenSaverEnabled:YES];
- // have everything stop
- CCNode* node;
- CCARRAY_FOREACH([self children], node)
- {
- [node stopAllActions];
- }
- // I do want the spiders to keep wiggling so I simply restart this here
- CCSprite* spider;
- CCARRAY_FOREACH(spiders, spider)
- {
- [self runSpiderWiggleSequence:spider];
- }
- // disable accelerometer input for the time being
- self.isAccelerometerEnabled = NO;
- // but allow touch input now
- self.isTouchEnabled = YES;
- // stop the scheduled selectors
- [self unscheduleAllSelectors];
- // add the labels shown during game over
- CGSize screenSize = [[CCDirector sharedDirector] winSize];
- CCLabel* gameOver = [CCLabel labelWithString:@"GAME OVER!" fontName:@"Marker Felt" fontSize:60];
- gameOver.position = CGPointMake(screenSize.width / 2, screenSize.height / 3);
- [self addChild:gameOver z:100 tag:100];
- // game over label runs 3 different actions at the same time to create the combined effect
- // 1) color tinting
- CCTintTo* tint1 = [CCTintTo actionWithDuration:2 red:255 green:0 blue:0];
- CCTintTo* tint2 = [CCTintTo actionWithDuration:2 red:255 green:255 blue:0];
- CCTintTo* tint3 = [CCTintTo actionWithDuration:2 red:0 green:255 blue:0];
- CCTintTo* tint4 = [CCTintTo actionWithDuration:2 red:0 green:255 blue:255];
- CCTintTo* tint5 = [CCTintTo actionWithDuration:2 red:0 green:0 blue:255];
- CCTintTo* tint6 = [CCTintTo actionWithDuration:2 red:255 green:0 blue:255];
- CCSequence* tintSequence = [CCSequence actions:tint1, tint2, tint3, tint4, tint5, tint6, nil];
- CCRepeatForever* repeatTint = [CCRepeatForever actionWithAction:tintSequence];
- [gameOver runAction:repeatTint];
- // 2) rotation with ease
- CCRotateTo* rotate1 = [CCRotateTo actionWithDuration:2 angle:3];
- CCEaseBounceInOut* bounce1 = [CCEaseBounceInOut actionWithAction:rotate1];
- CCRotateTo* rotate2 = [CCRotateTo actionWithDuration:2 angle:-3];
- CCEaseBounceInOut* bounce2 = [CCEaseBounceInOut actionWithAction:rotate2];
- CCSequence* rotateSequence = [CCSequence actions:bounce1, bounce2, nil];
- CCRepeatForever* repeatBounce = [CCRepeatForever actionWithAction:rotateSequence];
- [gameOver runAction:repeatBounce];
- // 3) jumping
- CCJumpBy* jump = [CCJumpBy actionWithDuration:3 position:CGPointZero height:screenSize.height / 3 jumps:1];
- CCRepeatForever* repeatJump = [CCRepeatForever actionWithAction:jump];
- [gameOver runAction:repeatJump];
- // touch to continue label
- CCLabel* touch = [CCLabel labelWithString:@"tap screen to play again" fontName:@"Arial" fontSize:20];
- touch.position = CGPointMake(screenSize.width / 2, screenSize.height / 4);
- [self addChild:touch z:100 tag:101];
- // did you try turning it off and on again?
- CCBlink* blink = [CCBlink actionWithDuration:10 blinks:20];
- CCRepeatForever* repeatBlink = [CCRepeatForever actionWithAction:blink];
- [touch runAction:repeatBlink];
- }
- -(void) ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
- {
- [self resetGame];
- }
- -(void) resetGame
- {
- // prevent screensaver from darkening the screen while the game is played
- [self setScreenSaverEnabled:NO];
- // remove game over label & touch to continue label
- [self removeChildByTag:100 cleanup:YES];
- [self removeChildByTag:101 cleanup:YES];
- // re-enable accelerometer
- self.isAccelerometerEnabled = YES;
- self.isTouchEnabled = NO;
- // put all spiders back to top
- [self resetSpiders];
- // re-schedule update
- [self scheduleUpdate];
- // reset score
- score = 0;
- totalTime = 0;
- [scoreLabel setString:@"0"];
- }
- // Only draw this debugging information in, well, debug builds.
- -(void) draw
- {
- #if DEBUG
- // Iterate through all nodes of the layer.
- CCNode* node;
- CCARRAY_FOREACH([self children], node)
- {
- // Make sure the node is a CCSprite and has the right tags.
- if ([node isKindOfClass:[CCSprite class]] && (node.tag == 1 || node.tag == 2))
- {
- // The sprite's collision radius is a percentage of its image width. Use that to draw a circle
- // which represents the sprite's collision radius.
- CCSprite* sprite = (CCSprite*)node;
- float radius = [sprite texture].contentSize.width * 0.4f;
- float angle = 0;
- int numSegments = 10;
- bool drawLineToCenter = NO;
- ccDrawCircle(sprite.position, radius, angle, numSegments, drawLineToCenter);
- }
- }
- #endif
- CGSize screenSize = [[CCDirector sharedDirector] winSize];
- // always keep variables you have to calculate only once outside the loop
- float threadCutPosition = screenSize.height * 0.75f;
- // Draw a spider thread using OpenGL
- // CCARRAY_FOREACH is a bit faster than regular for loop
- CCSprite* spider;
- CCARRAY_FOREACH(spiders, spider)
- {
- // only draw thread up to a certain point
- if (spider.position.y > threadCutPosition)
- {
- // vary thread position a little so it looks a bit more dynamic
- float threadX = spider.position.x + (CCRANDOM_0_1() * 2.0f - 1.0f);
- glColor4f(0.5f, 0.5f, 0.5f, 1.0f);
- ccDrawLine(spider.position, CGPointMake(threadX, screenSize.height));
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement