cocos2d视频教程进阶篇--第3天--猴子跳跳游戏_跳一跳游戏cocos2dx_xingxiliang的博客-程序员秘密

技术标签: 游戏开发  

今天我们学习一个Cocosd2d-iphone游戏。中间介绍了texturepacker 和physics editor的使用(需要MAC操作系统),我们一起做一个实战级别的游戏。


其中还介绍了 图片资源文件加密, 碰撞检测,动画效果等知识,比较有趣。


感觉代码太枯燥的,敬请期待视频上传

高清avi视频和项目源代码已经提供下载:

百度网盘:http://pan.baidu.com/s/1ELk78 里面的进阶篇。

//
//  Floor.h
//  MonkeyJump
//
//  Created by Mac on 14-3-10.
//  Copyright (c) 2014年 codeandweb.de. All rights reserved.
//

#import "GB2Sprite.h"

@interface Floor : GB2Sprite // 既有cocos2d CCSprite 又包含 b2Body

+(Floor*)floorSprite;

@end


//
//  Floor.m
//  MonkeyJump
//
//  Created by Mac on 14-3-10.
//  Copyright (c) 2014年 codeandweb.de. All rights reserved.
//

#import "Floor.h"

@implementation Floor

+(Floor*)floorSprite{
    // GB2Sprite
    return [[[self alloc] initWithStaticBody:@"grassfront" spriteFrameName:@"floor/grassfront.png"] autorelease];
}
@end



//
//  GameLayer.h
//  MonkeyJump
//
//  Created by Andreas Löw on 10.11.11.
//  Copyright codeandweb.de 2011. All rights reserved.
//

// When you import this file, you import all the cocos2d classes
#import "cocos2d.h"

@class Object;
@class Monkey;
@class HeadUpDisplay;

// GameLayer
@interface GameLayer : CCLayer
{
    float       _timeLeftBeforeNextObject;
    Object*     _nextObject;
    
    Monkey*     _monkey;
    CCSpriteBatchNode* _objectLayer ;

    CCSprite *__backGrass;
    float _heapHeight;   //堆积物体的最高高度
}


@property (assign,nonatomic) float highestObjectY;
@property(nonatomic) float heapHeight;  // 不需要写synthesis

// returns a CCScene that contains the GameLayer as the only child
+(CCScene *) scene;

@end




//
//  GameLayer.mm
//  MonkeyJump
//
//  Created by Andreas Löw on 10.11.11.
//  Copyright codeandweb.de 2011. All rights reserved.
//

// Import the interfaces
#import "GameLayer.h"
#import "GB2DebugDrawLayer.h"
#import "GB2Sprite.h"
#import "Floor.h"

#import "Object.h"
#import "Monkey.h"
#import "HeadUpDisplay.h"
#import "SimpleAudioEngine.h"

#import "ZipUtils.h"
#import "cocos2d/Support/ZipUtils.h"


// HelloWorldLayer implementation
@implementation GameLayer {
    CCSprite *__background;
    Floor *_floorObj;
    HeadUpDisplay *_hud;
    int _tickAfterMonkeyDead;
    float _timeGap;
    CCLayerColor *_indicator;
}


+(CCScene *) scene
{
	// 'scene' is an autorelease object.
	CCScene *scene = [CCScene node];

	// 'layer' is an autorelease object.
	GameLayer *layer = [GameLayer node];

	// add layer as a child to scene
	[scene addChild: layer];

	// return the scene
	return scene;
}

// on "init" you need to initialize your instance
-(id) init
{

    caw_setkey_part(0, 0xb789a2ef);
    caw_setkey_part(1, 0xa185b1df);
    caw_setkey_part(2, 0x5e648b88);
    caw_setkey_part(3, 0x9cf4f44e);


     CGSize screenSize = [[CCDirector sharedDirector] winSize];

    float temp;
    if (screenSize.width > screenSize.height){
        temp = screenSize.width;
        screenSize.width = screenSize.height;
        screenSize.height = temp;
    }

	if( (self=[super init]))
    {
        // 加载我们的spritesheet            pvr.czz
        [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"tp_objects.plist"];

        [[CCSpriteFrameCache sharedSpriteFrameCache] addSpriteFramesWithFile:@"tp.plist"];

        // 加载box2d 物体属性
        [[GB2ShapeCache sharedShapeCache] addShapesWithFile:@"pe_monkey.plist"];

        // 最底层
        __background = [CCSprite spriteWithSpriteFrameName:@"jungle.png"];
        __background.anchorPoint = ccp(0,0);
        __background.position = ccp(0,0);
        [self addChild:__background z:0];

        // 背景的草
        __backGrass = [CCSprite spriteWithSpriteFrameName:@"floor/grassbehind.png"];
        __backGrass.anchorPoint = ccp(0, 0);
        __backGrass.position = ccp(0, 0);
        [self addChild:__backGrass z:2];

        // 所有展示的 box2d世界中的物体
        _objectLayer = [CCSpriteBatchNode batchNodeWithFile:@"tp_objects.pvr.ccz"];

        [self addChild:_objectLayer z:10];


        _floorObj = [Floor floorSprite];
        CCSprite* floor = (CCSprite *) [_floorObj ccNode];
        [_objectLayer addChild:floor];

        [self scheduleUpdate];

        _timeLeftBeforeNextObject = 2;
        _nextObject = nil;

        GB2Node* leftWall = [[[GB2Node alloc] initWithStaticBody:nil node:nil] autorelease];
        [leftWall addEdgeFrom:b2Vec2FromCC(0, 0) to:b2Vec2FromCC(0, 10000)];


        GB2Node*rightWall = [[[GB2Node alloc] initWithStaticBody:nil node:nil] autorelease];
        [rightWall addEdgeFrom:b2Vec2FromCC(screenSize.height, 0) to:b2Vec2FromCC(screenSize.height, 10000)];

        // i really not like
        //调试box2d
//        CCNode* debugLayer = [[[GB2DebugDrawLayer alloc] init] autorelease];
//        [self addChild:debugLayer z:40];
        
        _monkey = [[[Monkey alloc] initWithParentlayer:self] autorelease];
        
        [_monkey setPhysicsPosition:b2Vec2FromCC(240, (120 + 32) / 2)];
        [_objectLayer addChild:[_monkey ccNode] z:40];


        _hud = [[HeadUpDisplay alloc] init];
        [self addChild:_hud z:20];

        [self setIsTouchEnabled:YES];


        _heapHeight = floor.position.y + floor.contentSize.height;

        _indicator = [[[CCLayerColor alloc] initWithColor:ccc4(255, 0, 0, 128) width:70 height:20] autorelease];
        [self addChild:_indicator z:30];
        _indicator.visible = NO;


        [[SimpleAudioEngine sharedEngine] playBackgroundMusic:@"tafi-maradi-loop.caf" loop:YES];
    }
    
	return self;
}

// 接受用户事件  触发猴子的运动
-(void)ccTouchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    UITouch* touch = (UITouch*) [touches anyObject];
    
    CGPoint uiPos = [touch locationInView:[touch view]];
    
    CGPoint pos = [[CCDirector sharedDirector] convertToGL:uiPos];
    
    float mX = [_monkey ccNode].position.x;
    
    if (pos.x < mX){
        _monkey.isMovingLeft = YES;
    }
    else {
        _monkey.isMovingLeft = NO;
    }


    // 触屏的上半部分  触摸 让猴子起跳
    if (pos.y > 160.0){
        [_monkey jump];
    }
}




-(void)update:(float) dt{
    //CCLOG(@"update method");
    _timeGap = 3.0f;

    [_hud notifiedHealth:_monkey.health];
    [_hud notifieadScore:_monkey.score];

    if (_monkey.health < 0){
        _tickAfterMonkeyDead++;

        if (_tickAfterMonkeyDead > 90){
            [[GB2Engine sharedInstance] deleteAllObjects]; // box2d 清空
            [[CCDirector sharedDirector] replaceScene:[GameLayer scene]];    // cocos2d 图形

            return;
        }
    }


    CGSize screenSize = [[CCDirector sharedDirector] winSize];

    _timeLeftBeforeNextObject -= dt;

    float monkeyY = [_monkey ccNode].position.y;

    if (_timeLeftBeforeNextObject > 0.5 * _timeGap && nil != _nextObject){
        _indicator.position = ccp([_nextObject ccNode].position.x, 300);
        _indicator.visible = YES;

    }       else{
        _indicator.visible = NO;
    }

    if (_timeLeftBeforeNextObject <= 0){
        _nextObject = [Object randomObject];

        int offsetX = rand() % 400 + 40;
        int offsetY = 400 + _heapHeight;

        [_nextObject setPhysicsPosition:b2Vec2FromCC(offsetX, offsetY)];

        [_objectLayer addChild:[_nextObject ccNode]];

        _timeGap *= 0.8;
        
        _timeLeftBeforeNextObject = _timeGap;
        if (_timeLeftBeforeNextObject < 0.5){
            _timeLeftBeforeNextObject  = 0.5;
        }
        //CCLOG(@"time gap is %f", _timeLeftBeforeNextObject);

    }

    // 调整摄像头位置
    [self adjustViewPoint:screenSize monkeyY:monkeyY];


    // 堆积物体的顶部      遍历box2d世界中的所有东西
    [[GB2Engine sharedInstance] iterateObjectsWithBlock:^(GB2Node *node) {
           // 是Object吗

            if ([node isKindOfClass:([Object class])]){
                Object *obj = (Object *)node;

                if (b2_staticBody != [obj getBodyType]      //已经变成静态的 不再考虑
                    &&  _nextObject != obj
                    && obj.numContacts > 1 //和多个物体又接触 才算在堆上
                    && [obj linearVelocity].LengthSquared() < 0.4
                        ){       // 只有obj是落在堆上的物体 才去更新_heapHeight

                    float objY = [obj ccNode].position.y + [obj ccNode].contentSize.height;

                    if (_heapHeight < objY){
                        _heapHeight = objY;

                        if (_heapHeight > 120){
                            ;
                        }

                        //CCLOG(@"heap height is %f", _heapHeight);
                    }

                    // 如果物体在堆的下层,离顶部很远 使它变成静态物体  box2d性能提高
                    if (objY < _heapHeight - 320){
                        [obj setBodyType:b2_staticBody];

                        static int numObjectsFromDynamicToStatic = 0;
                        numObjectsFromDynamicToStatic ++;
//                        CCLOG(@"%x(%d) become from dynamic to static , totally %d objects changed",
//                        obj, obj.numContacts, numObjectsFromDynamicToStatic);

                    }
                }

            }
    }];


}

- (void)adjustViewPoint:(CGSize)screenSize monkeyY:(float)monkeyY {
    float centerY = monkeyY - screenSize.width / 2;

    if (centerY < 0){
        centerY = 0;
    }


    _objectLayer.position = ccp(0, -centerY);

    __backGrass.position = ccp(0, -0.8 * centerY);

    __background.position = ccp(0, -0.6 * centerY);
}


@end





//
// Created by Mac on 14-3-16.
// Copyright (c) 2014 codeandweb.de. All rights reserved.
//

#import <Foundation/Foundation.h>
#import <cocos2d.h>
#import "CCSpriteBatchNode.h"

@interface HeadUpDisplay : CCSpriteBatchNode {
    float _displayHealth;
}

@property(nonatomic) float displayHealth;

-(id)init;

- (void)notifieadScore:(float)theScore;

-(void)notifiedHealth:(float) monkeyHealth;
@end



//
// Created by Mac on 14-3-16.
// Copyright (c) 2014 codeandweb.de. All rights reserved.
//

#import "HeadUpDisplay.h"
#import "CCSprite.h"
#import "CCAction.h"
#import "CCActionInterval.h"
#import "CCActionInstant.h"
#import "CCSpriteFrame.h"
#import "CCSpriteFrameCache.h"

#define MAX_DISPLAY_TOKE_NUM 10

@implementation HeadUpDisplay {

    CCSprite *_displayToken [MAX_DISPLAY_TOKE_NUM];

    CCSprite* _scoreDisplay[5];

@private
    float _scoreOnBoard;
    CCSpriteFrame *_digits [10];
}

- (id)init {
    [super initWithFile:@"tp_objects.pvr.ccz" capacity:50];

    if (self){
        for (int i = 0; i < MAX_DISPLAY_TOKE_NUM; i ++){
            _displayToken[i] = [CCSprite spriteWithSpriteFrameName:@"hud/banana.png"];
            _displayToken[i].position = ccp(20 + i * 15, 280);
            [self addChild:_displayToken[i]];
            _displayToken[i].visible = YES;

        }

        for (int i = 0; i < 5; i ++){
            _scoreDisplay[i] = [CCSprite spriteWithSpriteFrameName:@"numbers/0.png"];
            _scoreDisplay[i].position = ccp(380 + i * 15, 280);
            _scoreDisplay[i].scale = 0.7f;
            [self addChild:_scoreDisplay[i]];
            _scoreDisplay[i].visible = NO;
        }

        for (int i = 0; i < 10; i ++){
            NSString* name = [NSString stringWithFormat:@"numbers/%d.png", i];
            _digits[i] = [[CCSpriteFrameCache sharedSpriteFrameCache] spriteFrameByName:name];
        }
    }

    _displayHealth = 100.0; // 100 ---- MAX_DISPLAY_TOKE_NUM
    _scoreOnBoard = 0;

    return self;
}


-(void) notifieadScore:(float)theScore{
    if (_scoreOnBoard < theScore){
        _scoreOnBoard += 1;

        if (_scoreOnBoard > theScore){
            _scoreOnBoard = theScore;
        }
    }

    int scoreInt = (int)_scoreOnBoard;

    char buf[5 + 1] = {0};

    snprintf(buf, 6, "%5d", scoreInt);

    for (int i = 0; i < 5; i ++){
        if (' ' == buf[i]){
            _scoreDisplay[i].visible = NO;
            continue;
        }

        int index = buf[i] - '0';

        [_scoreDisplay[i] setDisplayFrame:_digits[index]];
        _scoreDisplay[i].visible = YES;
    }


}

- (void)notifiedHealth:(float)monkeyHealth {

    if (monkeyHealth > _displayHealth){
        _displayHealth += 13.0f;
        if (_displayHealth > monkeyHealth){
            _displayHealth = monkeyHealth;
        }
    }  else{
          _displayHealth -= 13.0f;

        if (_displayHealth < monkeyHealth){
            _displayHealth = monkeyHealth;
        }
    }


    int displayNum = (int)((_displayHealth / 100) * MAX_DISPLAY_TOKE_NUM);

    int i;

    for (i =0; i < displayNum; i ++){
        //_displayToken[i].visible = YES;
        CCSprite *token =    _displayToken[i];
        if (NO == token.visible){

            token.visible = YES;

            token.opacity = 0.0f;
            token.scale = 0.3;

            // 多个动作 合并
            CCSpawn *action  = [CCSpawn actions:
                    [CCScaleTo actionWithDuration:0.3 scale:1.0f],
                    [CCFadeIn actionWithDuration:0.3f],
                    nil]  ;

            [token runAction:action];

        }
    }

    for (; i < MAX_DISPLAY_TOKE_NUM; i ++){

        CCSprite *token =    _displayToken[i];
        if (YES == token.visible && [token numberOfRunningActions] <= 0){

            CCSpawn *disappear = [CCSpawn actions:
                    [CCScaleTo actionWithDuration:0.3 scale:0.3],
                    [CCFadeOut actionWithDuration:0.3],
                    nil]; // visiable == YES;

            CCHide* hide = [CCHide action];

            CCSequence *all = [CCSequence actions:disappear, hide, nil];


            [token runAction:all];

        }
    }
}

@end



//
//  Monkey.h
//  MonkeyJump
//
//  Created by Mac on 14-3-11.
//  Copyright (c) 2014年 codeandweb.de. All rights reserved.
//

#import "GB2Sprite.h"

@class GameLayer;
@class GB2Contact;

@interface Monkey : GB2Sprite
{
    bool _isMovingLeft;
    
    int _numContactWithFloor;
    
    int _numContactWithHead;
    int _numContactWithLeft;
    int _numContactWithRight;
    
    ccTime  _timePassed;
    int _animatePhase;


    int _trappedCount; // 记录猴子被困住的时间  -- 跳到堆积物体的顶部以上




    float _health;
}

@property (assign, nonatomic) bool isMovingLeft;
@property (assign, nonatomic) int numbContactWithFloor;

@property(nonatomic) float health;


@property(nonatomic) float score;

-(id)initWithParentlayer:(GameLayer*) theParentLayer;
-(void)jump;

- (void)beginContactWithFloor:(GB2Contact *)contact;

- (void)endContactWithFloor:(GB2Contact *)contact;


- (void)beginContactWithObject:(GB2Contact *)contact;

- (void)endContactWithObject:(GB2Contact *)contact;
@end



//
//  Monkey.m
//  MonkeyJump
//
//  Created by Mac on 14-3-11.
//  Copyright (c) 2014年 codeandweb.de. All rights reserved.
//    xcode -> appcode

#import "Monkey.h"
#import "SimpleAudioEngine.h"
#import "GMath.h"
#import "GB2Contact.h"

#import "GameLayer.h"
#import "Object.h"

@implementation Monkey {
    GameLayer *__parentLayer;
}

@synthesize isMovingLeft = _isMovingLeft;
@synthesize numbContactWithFloor = _numbContactWithFloor;

-(id)initWithParentlayer:(GameLayer*) theParentLayer{
    __parentLayer = theParentLayer;

    [super initWithDynamicBody:@"monkey" spriteFrameName:@"monkey/idle/2.png"];
    
    if (self){
        [self setFixedRotation:YES];
        [self setBullet:YES];
        
        self.isMovingLeft = NO;
        _numContactWithFloor = 0;
        
        
        _numContactWithHead = 0;
        _numContactWithLeft = 0;
        _numContactWithRight = 0;
        
        _timePassed = 0.3;
        
        _animatePhase = 1;

        _health = 100;


        
    }
    
    return self;
}

// 自己实现动画效果  周期性的改变自己展示的图形
-(void)updateCCFromPhysics{
    [super updateCCFromPhysics]; //使物体 先服从box2d中原有的物理规律


    if (_health < 0) {
        return;
    }

    
    float impulse = self.mass * 0.5;
    float velocityX = [self linearVelocity].x;
    
    float velocityY = [self linearVelocity].y;
    
    //CCLOG(@"v y is %f", velocityY);
    
    if (velocityY > 8){
        //body->SetLinearDamping(0.6);
        self.linearVelocity = b2Vec2(velocityX, 0.6 * velocityY);
    }
    
    //使猴子水平移动
    if (_isMovingLeft && velocityX > -1.0){
        [self applyLinearImpulse:b2Vec2(-impulse, 0) point:self.worldCenter];
    } else if (!_isMovingLeft && velocityX < 1.0){
        [self applyLinearImpulse:b2Vec2(impulse, 0) point:self.worldCenter];
    }

    // 设置猴子 在屏幕显示什么图片 实现动画效果
    [self setMonkeyDisplayFrame];

    // 计算猴子已经被困多长时间
    if (_numContactWithHead > 0){
        _trappedCount ++;

        if (_trappedCount > 60){
            [self setPhysicsPosition:b2Vec2FromCC(ccNode.position.x,
            __parentLayer.heapHeight)];
        }
    }
    else{
        _trappedCount = 0;
    }


    float curRelevateScore = 1.0 *   [self ccNode].position.y - 75;

    if (self.score < curRelevateScore){
        self.score = curRelevateScore;
    }



}


// 设置猴子应该显示那一张图片 实现动画效果
- (void)setMonkeyDisplayFrame {

    _timePassed -= 1.0f / 60.0f;

    if (_timePassed <= 0){
        _animatePhase++;

        if (_animatePhase >= 3){
            _animatePhase = 1;
        }


        _timePassed = 0.3;
    }

    NSString* frameName;
    NSString* dir;
    float monkeyVelocityLengthSquare = [self linearVelocity].LengthSquared();

    dir = _isMovingLeft ? @"left":@"right";

    //CCLOG(@"v square is %f", monkeyVelocityLengthSquare);

    if ( monkeyVelocityLengthSquare < 0.3){
        if (_numContactWithHead > 0){
            frameName = @"arms_up";
        }
        else{
            frameName = @"idle/2";
        }
    }
    else {
        if (_numContactWithFloor < 0){

            frameName = [NSString stringWithFormat:@"jump/%@", dir];
        }
        else{
            if (_numContactWithLeft > 0 && _isMovingLeft){
                frameName = [NSString stringWithFormat:@"push/%@_%d", dir, _animatePhase];
            }
            else if (_numContactWithRight > 0 && !_isMovingLeft){
                frameName = [NSString stringWithFormat:@"push/%@_%d", dir, _animatePhase];
            }
            else{
                frameName = [NSString stringWithFormat:@"walk/%@_%d", dir, _animatePhase];
            }
        }
    }

    NSString* completeFrameName = [NSString stringWithFormat:@"monkey/%@.png", frameName];

    [self setDisplayFrameNamed:completeFrameName];
}

-(void)jump{

    if (_health < 0)
    {
        return;
    }

    if (_numContactWithFloor <=0){
        return; //离地 的时候不需要再施加冲量了
    }
    
    float factor = 1.0f;
    if (_numContactWithHead > 0){
        factor = 3.0f;
    }
    
    [self applyLinearImpulse:b2Vec2(0, self.mass * 6.0 * factor) point:self.worldCenter];
    
    float _pan = ([self ccNode].position.x - 240.0) / 240.0;
    
    [[SimpleAudioEngine sharedEngine] playEffect:@"jump.caf" pitch:gFloatRand(0.8, 1.2) pan:_pan gain:1.0];
}

-(void)beginContactWithFloor:(GB2Contact*) contact{
    _numContactWithFloor ++;
}

-(void)endContactWithFloor:(GB2Contact*) contact{
    _numContactWithFloor --;
}

-(void)beginContactWithObject:(GB2Contact*) contact{

    GB2Node* otherNode = [contact otherObject] ;
    if ([otherNode isKindOfClass:[Object  class]]){   // 如果是香蕉则补充生命值
        Object *other = (Object *)otherNode;
        if ([other.objName isEqualToString:@"banana"]){
            _health += 60;
            if (_health > 100){
                _health = 100;
            }
            [other disappear];

            [[SimpleAudioEngine sharedEngine] playEffect:@"gulp.caf"];

            //return;

        } else if ([other.objName isEqualToString:@"bananabunch"]){
            _health += 90;
            if (_health > 100){
                _health = 100;
            }
            [other disappear];


            [[SimpleAudioEngine sharedEngine] playEffect:@"gulp.caf"];


            //return;
        }
    }



    void* str = contact.ownFixture->GetUserData();
    
    NSString* fixId = (NSString*)str;
    
    if ([fixId isEqualToString:@"head"]){
        _numContactWithHead ++;


        GB2Node* otherNode = [contact otherObject]    ;
        if ([otherNode isKindOfClass:[Object  class]]){
            b2Vec2 otherV = [otherNode linearVelocity];

            float otherVY = otherV.y;

            // 造成伤害
            [self hurtHealth:otherNode otherVY:otherVY];

        }


    } else if([fixId isEqualToString:@"push_left"]){
        _numContactWithLeft ++;
    } else if ([fixId isEqualToString:@"push_right"]){
        _numContactWithRight ++;
    } else{
        _numContactWithFloor ++;
    }
}

- (void)hurtHealth:(GB2Node *)otherNode otherVY:(float)otherVY {
    if (otherVY < -0.3) // 另外一个物体是向下运动的  0
            {
                _health += 0.5* otherVY * otherNode.mass;


                [[SimpleAudioEngine sharedEngine] playEffect:@"hurt.caf" pitch:1.0 pan:1.0 gain:2.0];

                CCLOG(@"health is %f", _health);

                if (_health < 0){
                    [self setFixedRotation:NO];

                    [self setCollisionMaskBits:0x0001]; // 是猴子只和 地面发生碰撞

                    [self setDisplayFrameNamed:@"monkey/dead.png"];
                }

            }
}

-(void)endContactWithObject:(GB2Contact*) contact{
    void* str = contact.ownFixture->GetUserData();
    
    NSString* fixId = (NSString*)str;
    
    if ([fixId isEqualToString:@"head"]){
        _numContactWithHead --;
    } else if([fixId isEqualToString:@"push_left"]){
        _numContactWithLeft --;
    } else if ([fixId isEqualToString:@"push_right"]){
        _numContactWithRight --;
    } else{
        _numContactWithFloor --;
    }
}



@end



//
//  Object.h
//  MonkeyJump
//
//  Created by Mac on 14-3-10.
//  Copyright (c) 2014年 codeandweb.de. All rights reserved.
//

#import "GB2Sprite.h"

@interface Object : GB2Sprite
{
    NSString* _objName;

    GB2Node* _contactOtherObjNames[50]; //和那些物体又接触

    int _numContacts;
}

@property (assign, nonatomic) int numContacts;
@property (retain, nonatomic) NSString *objName;

-(id)initWithObjName:(NSString*) theObjName;
+(id)randomObject;

-(id)disappear;

@end



//
//  Object.m
//  MonkeyJump
//
//  Created by Mac on 14-3-10.
//  Copyright (c) 2014年 codeandweb.de. All rights reserved.
//

#import "Object.h"
#import "GMath.h"
#import "GB2Contact.h"
#import "SimpleAudioEngine.h"

@implementation Object {
    bool _hasBeginDisappearAction;
}

@synthesize objName = _objName;
@synthesize numContacts = _numContacts;

-(id)initWithObjName:(NSString*) theObjName
{
    NSString* pngName = [NSString stringWithFormat:@"objects/%@.png", theObjName];
    // GB2Sprite
    [super initWithDynamicBody:theObjName spriteFrameName:pngName];
    
    if (self){
        _objName = theObjName;

        _numContacts = 0;

        _hasBeginDisappearAction = NO;
    }
    
    return self;
}
+(id)randomObject{
    int type = rand() % 7;
    
    NSString* myObjName = @"backpack.png";
    
    switch (type) {
        case 0:
            myObjName = @"backpack";
            break;
        case 1:
            myObjName = @"statue";
            break;
        case 2:
            myObjName = @"banana";
            break;
        case 3:
            myObjName = @"bananabunch";
            break;
        case 4:
            myObjName = @"hat";
            break;
        case 5:
            myObjName = @"pineapple";
            break;
        case 6:
            myObjName = @"canteen";
            break;
            
        default:
            break;
    }
    
    return [[[Object alloc] initWithObjName:myObjName] autorelease];
}

- (id)disappear {

    // 消失动画
    if (NO == _hasBeginDisappearAction)
    {
        CCSpawn *outAction = [CCSpawn actions:
                [CCScaleTo actionWithDuration:0.2 scale:0.0],
                [CCFadeOut actionWithDuration:0.2],
                nil];


        CCCallFunc *deleteAction = [CCCallFunc actionWithTarget:self selector:@selector(deleteNow)];

        [self runAction:[CCSequence actions:outAction, deleteAction, nil ]];

        _hasBeginDisappearAction = YES;
    }

    return nil;
}


-(void)beginContactWithObject:(GB2Contact*)contact{

    GB2Node *other_ = (contact.otherObject);
    _contactOtherObjNames[_numContacts] = other_;

    _numContacts ++;

    if (_numContacts >= 50){
        ;
    }


    b2Vec2 v = [self linearVelocity];
    
    if (v.LengthSquared() < 3){
        return;
    }


    // 播放声音
    NSString* cafName = [NSString stringWithFormat:@"%@.caf",_objName];
    
    float pan = ([self ccNode].position.x - 240.0) / 240.0;
    
    //
    [[SimpleAudioEngine sharedEngine] playEffect:cafName pitch:gFloatRand(0.8, 1.2) pan:(pan) gain:1.0];





}

-(void)endContactWithObject:(GB2Contact*) contact{
    _numContacts --;

    if (_numContacts < 0){
        ;
    }
}

-(void)beginContactWithFloor:(GB2Contact*) contact{
    [self beginContactWithObject:contact];

    //_numContacts ++;
}

-(void)endContactWithFloor:(GB2Contact*) contact{
    
    _numContacts --;

    if (_numContacts < 0){
        ;
    }
}


-(void) dealloc{
    [_objName release];
    [super dealloc];
}
@end


版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/xingxiliang/article/details/21331459

智能推荐

练习2-9 整数四则运算_chj65的博客-程序员秘密

练习2-9 整数四则运算浙大版《C语言程序设计(第3版)》题目本题要求编写程序,计算2个正整数的和、差、积、商并输出。题目保证输入和输出全部在整型范围内。输入格式:输入在一行中给出2个正整数A和B。输出格式:在4行中按照格式“A 运算符 B = 结果”顺序输出和、差、积、商。输入样例:输出样例:##include&lt;stdio.h&gt; int main (void)...

联想r720安装固态_联想拯救者r720笔记本NVME接口M.2固态硬盘怎么安装win7系统_weixin_39787089的博客-程序员秘密

[文章导读]联想拯救者r720是一款游戏笔记本,专为游戏设计的键盘备受年轻网友喜爱,这款电脑采用了英特尔 酷睿i5 7代系列,能够满足游戏用户们使用需求,新推出的联想笔记本电脑都预装了win10系统,win10系统在稳定性和用户体验面还存在问题,因此很多用户都想把win10系统改成win7系统,因此很多用户都想把win10系统改成win7系统,但是由于新机型采用UEFI模式,要修改BIOS才能改装...

然后制作次世代建模?资深大咖给你技巧详解_weixin_44386638的博客-程序员秘密

蒸汽朋克女猎手制备对于概念艺术,您必须清楚地了解您的主要动机是什么。例如,我想模仿一个女猎人(她是DC Comics的超级英雄),我也想给她一个蒸汽朋克的样子。所以我在不同的网站上搜索了很多艺术品,当我得到一些想法时,我开始将它们放入参考表中,包括鞋子,身体,面部,面具,头发,长手套,绑腿等等。尽量简化你的参考表; 它会帮助你不要在中途迷茫。如果你找不到合适的参考资料,你可以在Photoshop中粗略地绘制它。缩短和最小化您的参考集合设计 - 执行在这一点上,我开始阻挡所有...

【Keras】训练时显存out of memory的解决办法——fit_generator函数_动力橙CHT的博客-程序员秘密

问题描述:建立好model之后,用model.fit()函数进行训练,发现超出显存容量(一共有12G) 问题分析:fit()函数训练时,将全部训练集载入显存之后,才开始分批训练。显然很容易就超出了12G 解决办法:用fit_generator函数进行训练fit_generator函数将训练集分批载入显存,但需要自定义其第一个参数——generator函数,从而分批将训练集送入显存def data

重定向标准错误输出_bin文件报错 重定向标准错误到标准输出_cheungjustin的博客-程序员秘密

<br />8.2.3  重定向标准错误输出<br /><br />第5章介绍了标准输出的概念,并解释了如何重定向命令的标准输出。除了标准输出之外,命令还可以将输出发送到标准错误输出。命令将错误消息发送到标准错误输出,这样就可以避免与发送到标准输出的信息混淆在一起。<br />与处理标准输出一样,默认情况下,shell将命令的标准错误输出发送到屏幕上。除非重定向标准输出和标准错误输出中的某一个,否则不能区分命令的输出到底是标准输出还是标准错误输出。本节讲述Bourne Again Shell使用的语法。如果

JavaEE程序员必读图书大推荐1_龙海881123的博客-程序员秘密

第一部分: Java语言篇1 《Java编程规范》  适合对象:初级,中级  介绍:作者James Gosling(Java之父),所以这本书我觉得你怎么也得读一下。对基础讲解的很不错。2 《Java核心技术:卷Ⅰ基础知识》  适合对象:初级,中级  介绍

随便推点

shell脚本的基础知识_搞什么滚去学习的博客-程序员秘密

一、Shell脚本概述1.1Shell基本概念将要执行的命令按顺序保存到一个文本文件给该文件可执行权限可结合各种Shell控制语句以完成更复杂的操作1.2 Shell脚本应用场景重复性操作交互性任务批量事务处理服务运行状态监控定时任务执行1.3 Shell作用——翻译官shell是一个特殊的应用程序,它介于操作系统内核和用户之间,充当了一个“命令解释器”的角色,负责接收用户输入的操作指令并进行解释,将需要执行的操作传递给内核执行,并输出执行结果。二、shell编程规范2.1 用

linux traceroute追踪路由路径_zhaomax的博客-程序员秘密

TraceRoute的工作原理  1.TraceRoute的工作原理:      traceroute 有使用两种:使用ICMP的和使用UDP的。Microsoft      使用ICMP,所以win95上发出的traceRT应使用的是ICMP,但我没有用 sniffer查过;其它包括unix和cisco router都使用UDP.      ICMP traceroute:     ...

bzoj 1449: [JSOI2009]球队收益 (费用流)_球队的支出是和他们的胜场有关系的_clover_hxy的博客-程序员秘密

题目描述传送门题目大意:在一个篮球联赛里,有n支球队,球队的支出是和他们的胜负场次有关系的,具体来说,第i支球队的赛季总支出是Ci∗x2+Di∗y2,Di<=CiCi*x^2+Di*y^2,Di<=Ci。其中x,y分别表示这只球队本赛季的胜负场次。现在赛季进行到了一半,每只球队分别取得了win[i]场胜利和lost[i]场失利。而接下来还有m场比赛要进行。问联盟球队的最小总支出是多少。题解对于每支队

win10操作系统 64位 原版 百度网盘下载_win10系统下载百度网盘_weixin_38168838的博客-程序员秘密

iso镜像文件4.57G,这里压缩成两个两个包便于上传网盘;使用时候,直接下载两个压缩包解压成镜像文件便可安装;链接:https://pan.baidu.com/s/1JNgxuBzdzFpp-pHHdf-DWQ提取码:9g3e扫码下载:转载于:https://www.cnblogs.com/xioawu-blog/p/11224533.html...

如何在DigitalOcean Kubernetes上使用Spinnaker设置CD流水线_cukw6666的博客-程序员秘密

The author selected the Free and Open Source Fund to receive a donation as part of the Write for DOnations program. 作者选择了免费开放源基金来接受捐款,这是Write for DOnations计划的一部分。 介绍 (Introduction)Spinnaker is an...

程序员笑话十二_又将程序换酒钱_盼盼编程的博客-程序员秘密

《桃花庵--程序员版》写字楼里写字间,写字间中程序员;程序人员写程序,又将程序换酒钱;酒醒只在屏前坐,酒醉还来屏下眠;酒醉酒醒日复日,屏前屏下年复年;但愿老死电脑间,不愿鞠躬老板前;奔驰宝马贵者趣,公交自行程序员;别人笑我太疯癫,我笑自己命太贱;但见满街漂亮妹,哪个归得程序员...

推荐文章

热门文章

相关标签