先看效果图:(必须在真机上)
源码地址:点击打开链接
直接贴代码,所有注释和解释在代码里:
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
GameScene.m
#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