先看效果图:(必须在真机上)
源码地址:点击打开链接
直接贴代码,所有注释和解释在代码里:
GameScene.h
#import <Foundation/Foundation.h> #import "cocos2d.h" @interface GameScene : CCLayer{ CCSprite *player; //玩家精灵 CGPoint playerVelocity; //速率 CCArray *shits; //所有便便集合 float shitMoveDuration; //便便之间距离 int numShitsMoved; //便便活动数量 CCLabelTTF *scoreLabel; //得分标签 double totalTime; //总时间 int score; //成绩 CCLabelBMFont *gameLabel; CCLabelTTF *taplabel; } +(id) scene; @end
#import "GameScene.h" #import "SimpleAudioEngine.h" @implementation GameScene +(id)scene { CCScene *scene = [CCScene node]; CCLayer *layer = [GameScene node]; [scene addChild:layer]; return scene; } -(id)init { if ((self = [super init])) { //创建背景音乐 [[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"background.mp3" loop:YES]; CCLOG(@"%@,%@",NSStringFromSelector(_cmd),self); //设置加速器,并添加accelerometer方法 [self setAccelerometerEnabled:YES]; //触摸事件,调用ccTouchesEnded:(NSSet *)touches事件 [self setTouchEnabled:YES]; //初始化精灵 player = [CCSprite spriteWithFile:@"Icon.png"]; //添加精灵 [self addChild:player z:0 tag:1]; //屏幕大小 CGSize screenSize = [[CCDirector sharedDirector] winSize]; //精灵高度 float imageHeight = [player texture].contentSize.height; //精度位置,position是精灵的中间坐标在哪里 player.position = CGPointMake(screenSize.width/2, imageHeight/2); //成绩标签 //scoreLabel = [CCLabelTTF labelWithString:@"0" fontName:@"Arial" fontSize:48]; scoreLabel = [CCLabelBMFont labelWithString:@"0" fntFile:@"font01.fnt"];//位置显示 //标签位置,屏幕中间顶部 scoreLabel.position = CGPointMake(screenSize.width / 2, screenSize.height); //对于标签上对齐 scoreLabel.anchorPoint = CGPointMake(0.5f, 1.0f); //添加成绩标签 [self addChild:scoreLabel z:-1]; //更新精灵的位置,每一帧都会调用方法update [self scheduleUpdate]; //初始化所有便便 [self initShits]; } return self; } //加速器方法 -(void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration { // CGPoint pos = player.position; // pos.x += acceleration.x * 10; // player.position = pos; //减速值 float deceleration = 0.4f; //加速值灵敏度 float sensitivity = 6.0f; //最大速度 float maxVelocity = 100; //改变坐标位置 playerVelocity.x = playerVelocity.x * deceleration + acceleration.x * sensitivity; //越界判断 if (playerVelocity.x > maxVelocity) { playerVelocity.x = maxVelocity; }else if(playerVelocity.x < -maxVelocity) { playerVelocity.x = -maxVelocity; } } //每一帧更新玩家精灵位置 -(void)update:(ccTime)delta { //精灵当前位置 CGPoint pos = player.position; //加上速率 pos.x += playerVelocity.x; CGSize screenSize = [[CCDirector sharedDirector] winSize]; //精灵宽度的一半,为了判断越界使用 float imageWidthHalved = [player texture].contentSize.width * 0.5f; //左越界值 float leftBorderLimit = imageWidthHalved; //右越界值 float rightBorderLimit = screenSize.width - imageWidthHalved; //左右越界处理 if (pos.x < leftBorderLimit) { pos.x = leftBorderLimit; playerVelocity = CGPointZero; }else if(pos.x > rightBorderLimit){ pos.x = rightBorderLimit; playerVelocity = CGPointZero; } //改变精灵位置 player.position = pos; //时间做为玩家的成绩 totalTime += delta; int currentTime = (int)totalTime; if (score < currentTime) { score = currentTime; [scoreLabel setString:[NSString stringWithFormat:@"%i",score]]; } //检测碰撞 [self checkForCollision]; } //初始化便便 -(void)initShits { CGSize screenSize = [[CCDirector sharedDirector] winSize]; CCSprite *tempShit = [CCSprite spriteWithFile:@"shit.png"]; //便便的宽度 float imageWidth = [tempShit texture].contentSize.width; //一屏能显示总共多少个便便 int numShits = screenSize.width/imageWidth; shits = [[CCArray alloc] initWithCapacity:numShits]; for (int i = 0; i < numShits; i++) { CCSprite *shit = [CCSprite spriteWithFile:@"shit.png"]; [self addChild:shit z:0 tag:2]; [shits addObject:shit]; } //重新设置所有便便的位置 [self resetShits]; } //重新设置所有便便的位置 -(void)resetShits { CGSize screentSize = [[CCDirector sharedDirector] winSize]; CCSprite *tempShit = [shits lastObject]; CGSize size = [tempShit texture].contentSize; int numShits = [shits count]; for (int i = 0; i< numShits; i++) { CCSprite *shit = [shits objectAtIndex:i]; shit.position = CGPointMake(size.width * i + size.width * 0.5f,screentSize.height + size.height); //停止所有动作 [shit stopAllActions]; } //更新停止 [self unschedule:@selector(shitsUpdate:)]; //每隔0.7秒运行一次shitsUpdate [self schedule:@selector(shitsUpdate:) interval:0.7f]; numShitsMoved = 0; shitMoveDuration = 4.0f; } //隔0.7秒下落的便便 -(void)shitsUpdate:(ccTime)delta { //为什么循环10次,因为,我不知道随机生成的索引值 对应的便便是不是活动的,所以要确认最终随机选 出的蜘蛛当前是空闲的,当然这个数字是做任意随机的,如果没有随机选出一个空闲的蜘蛛,就会 跳过这次更新,然后等待下一次。 for (int i = 0; i < 10; i++) { int randomShiteIndex = CCRANDOM_0_1() * [shits count]; CCSprite *shit = [shits objectAtIndex:randomShiteIndex]; //某个便便是不是在活动 if ([shit numberOfRunningActions] == 0) { //如果空闲,就使它运动 [self runShitMoveSequence:shit]; break; } } } //通过动作控制便便的运动 -(void)runShitMoveSequence:(CCSprite*)shit { numShitsMoved++; //每落下八个就加速,加速是让便便之间的距离减少 if (numShitsMoved % 8 == 0 && shitMoveDuration > 2.0f) { shitMoveDuration -= 0.1f; } //下降到的位置 CGPoint belowScreenPosition = CGPointMake(shit.position.x, -[shit texture].contentSize.height); //动作 CCMoveTo *move = [CCMoveTo actionWithDuration:shitMoveDuration position:belowScreenPosition]; CCCallFuncN *callDidDrop = [CCCallFuncN actionWithTarget:self selector:@selector(shitDidDrop:)]; //动作循环 CCSequence *sequence = [CCSequence actions:move, callDidDrop, nil]; [shit runAction:sequence]; } //重设便便位置 -(void)shitDidDrop:(id)sender { //保证sender参数属于正确的类 NSAssert([sender isKindOfClass:[CCSprite class]], @"sender is not a CCSprite!"); CCSprite *shit = (CCSprite*)sender; CGPoint pos = shit.position; CGSize screenSize = [[CCDirector sharedDirector] winSize]; pos.y = screenSize.height + [shit texture].contentSize.height; //改变便便位置 shit.position = pos; } //碰撞检测 -(void) checkForCollision { //用精灵和便便的半径来判断是否碰撞 float playerImageSize = [player texture].contentSize.width; float shitimageSize = [[shits lastObject] texture].contentSize.width; float playCollisionRadius = playerImageSize * 0.4f; float shitCollisionRadius = shitimageSize * 0.4f; //最大碰撞距离 float maxCollisionDistance = playCollisionRadius + shitCollisionRadius; int numShits = [shits count]; for (int i=0; i < numShits; i++) { CCSprite *shit = [shits objectAtIndex:i]; if ([shit numberOfRunningActions] == 0) { continue; } //ccpDistance方法判断是否碰撞 float actualDistance = ccpDistance(player.position, shit.position); if (actualDistance < maxCollisionDistance) { //Game over!! [[SimpleAudioEngine sharedEngine] playEffect:@"007.mp3"]; //[self resetShits]; [self gameOver]; break; } } } -(void)gameOver { //屏幕大小 CGSize screentSize = [[CCDirector sharedDirector] winSize]; CCSprite *tempShit = [shits lastObject]; CGSize size = [tempShit texture].contentSize; int numShits = [shits count]; for (int i = 0; i< numShits; i++) { CCSprite *shit = [shits objectAtIndex:i]; shit.position = CGPointMake(size.width * i + size.width * 0.5f,screentSize.height + size.height); //停止所有动作 [shit stopAllActions]; } //更新停止 //[self unschedule:@selector(shitsUpdate:)]; [self unscheduleAllSelectors]; gameLabel = [CCLabelBMFont labelWithString:@"GAME OVER!" fntFile:@"font01.fnt"]; gameLabel.position = CGPointMake(screentSize.width / 2, screentSize.height / 2); [self addChild:gameLabel]; taplabel = [CCLabelTTF labelWithString:@"tap screen to play again" fontName:@"Arial" fontSize:20]; taplabel.position = CGPointMake(screentSize.width / 2, screentSize.height / 2 - [gameLabel texture].contentSize.height / 2); [self addChild:taplabel]; } //点击事件 -(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { if (gameLabel != nil) { [self removeChild:gameLabel]; [self removeChild:taplabel]; taplabel = nil; gameLabel = nil; totalTime = 0.0f;[self scheduleUpdate];[self resetShits]; }}- (void)dealloc{CCLOG(@"%@,%@",NSStringFromSelector(_cmd),self); shits = nil;[super dealloc];}@end