• cocos2d 学习 第四章



    #import <Foundation/Foundation.h> #import "cocos2d.h"
    @interface GameScene : CCLayer
    {
    
         CCSprite* player;
    
    }
    +(id) scene;
    @end
    

    启用加速计输入,创建并定位玩家精灵

    -(id) init

    {

       if ((self = [super init]))
       {

          self.isAccelerometerEnabled = YES;                          // 支持重力加速

                player = [CCSprite spriteWithFile:@"alien.png"];            // 由图片文件生成一个CCSprite对象作为主角

                [self addChild:player z:0 tag:1];                           // 将主角添加到当前场景中

                CGSize screenSize = [[CCDirector sharedDirector] winSize];  // 通过CCDirector对象得到设备尺寸

                float imageHeight = [player texture].contentSize.height;    // 通过CCSprite对象得到主角图片的高度

                player.position = CGPointMake(screenSize.width/2, imageHeight/2);  // 将主角的位置设置为屏幕下方中心

                [self initSpiders];                       // 初始化蜘蛛对象

                [selfscheduleUpdate];                    // 是一个CCLayer对象定义的方法,它将在每桢调用update方法

        }

         return self;
    }

    注意,我没有保留玩家精灵。因为我们已将其添加为层 的子节点,所以 cocos2d 会保留它。另外由于玩家精灵永远不会从层中移除,因而现在这 样做就足够了,不需要特意对它进行保留。不保留一个内存被其他类或对象管理的对象称 为“保持弱引用”。 

    通过调用[player texture].contentSize.height 返回精灵纹理的内容尺寸。 我讲到 iOS 中纹理尺寸的大小只能是 2 的方幂。但是实际的图像尺寸可能会比纹理尺寸小。 

    -(void) accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)acceleration   

    {

            CGPoint pos = player.position;
            pos.x += acceleration.x * 10;
            player.position = pos;
    

    注意到奇怪之处了吗?上面的三行代码用一行就能写好:
    

    // ERROR: lvalue required as left operand of assignment

    player.position.x += acceleration.x * 10; 

    position 属性的类型是 CGPoint,这是一个 普通的 C 结构体。Objective-C 中的属性不能直接向结构体的域赋值。 

    注意到加速计输入哪里不正常了吗?是的,它反应迟缓,移动不畅。这是因为玩家精灵并没执行真实的加速和减速。 

    实现加速与减速的概念不在于直接改变玩家的位置值,而是使用单独的 CGPoint 变量 作为速度矢量。每次接收到加速计事件时,速度矢量就加上从加速计得到的输入。当然, 这意味着我们得把速度限制在一个任意的最大值内,否则减速时就要花点时间了。不管有没有接收到加速计输入,在每一帧都把速度加到玩家位置上。 

    为什么不使用动作来移动玩家精灵呢?无论何时你需要频繁地——如每秒数次——改 变对象的速度或方向,使用 move 动作都不是一个好的选择。动作适用于相对使用期较长 的对象,所以频繁创建新对象在分配和释放内存上增加了额外开销,这会使游戏性能大幅 下降。

    更糟糕的是,如果不为动作留出一点时间,动作是不会执行的。这就是在每帧添加新 动作来替换前一个却没有任何效果的原因。 

    -(void) accelerometer:(UIAccelerometer *) acceleromete didAccelerate:(UIAcceleration *)acceleration

    {
      float deceleration = 0.4f;            // 减速值

          float sensitivity = 6.0f;               // 明感度

          float maxVeloctiy = 100;            // 最大速度

        

        playerVelocity.x = playerVelocity.x * deceleration + acceleration.x *sensitivity;

        // 新的玩家速度=原有速度*减速值+加速计*明感度值

        CCLOG(@"playVelocity.x = %f",playerVelocity.x);

        if(playerVelocity.x > maxVeloctiy)

        {

            playerVelocity.x = maxVeloctiy;

        }

        else if(playerVelocity.x < -maxVeloctiy)

        {

            playerVelocity.x = maxVeloctiy;

        }

    
    

    现在 playerVelocity 能够改变了,但如何把速度加到玩家精灵的位置值上呢?可以在 GameScene init 方法中指定如下 update 方法:

    (void) update:(ccTime)delta

    method to be called every frame [self scheduleUpdate];

    同样需要添加“(void) update:(ccTime)delta”方法 

    - (void)update:(ccTime)delta

    {

        CGPoint pos = player.position;          // 得到主角当前位置pos

        pos.x += playerVelocity.x;              // posX值加上速度playerVelocity的值

        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;   // 速度重置为0

        }

        else if(pos.x >rightBorderLimit)    // 如果新位置大于右边界

        {

            pos.x = rightBorderLimit;       // 新位置等于右边界

            playerVelocity = CGPointZero;   // 速度重置为0

        }

        player.position = pos;              // 如果新位置没有超出范围,则将移动主角到新位置

    }

    添加障碍物

      CCArray *spiders;               // 蜘蛛

        float spiderMoveDuration;       // 

        int numSpidersMoved;            // 已经移动过的蜘蛛数量

     

    #pragma mark 初始化所有蜘蛛对象

    - (void)initSpiders

    {

        CGSize screenSize = [[CCDirectorsharedDirector] winSize];

        CCSprite *tempSpider = [CCSpritespriteWithFile:@"spider.png"]; // 由图片文件生产CCSprite蜘蛛对象

        float imageWidth = [tempSpider texture].contentSize.width;      // 得到蜘蛛对象图片宽度

        int numSpiders = screenSize.width/imageWidth;                   // 由设备宽度/图片宽带得到可以容纳蜘蛛的数量

        spiders = [[CCArray alloc] initWithCapacity:numSpiders];        // 生成相应的数组

        for (int i = 0; i<numSpiders; i++)

        {

            CCSprite *spider = [CCSpritespriteWithFile:@"spider.png"];     // 循环生成每个蜘蛛的CCSprite

            [self addChild:spider z:0 tag:2];                               // 将蜘蛛放到场景中

            [spiders addObject:spider];                                     // 将蜘蛛对象放到数组中

        }

        [self resetSpiders];                                                // 重置所有蜘蛛的位置

    }

     

    #pragma mark 重置所有蜘蛛对象的位置

    - (void)resetSpiders

    {

        CGSize screenSize = [[CCDirectorsharedDirector] winSize];

        int numSpiders = [spiders count];                                   // 得到现有蜘蛛数组中的个数

        if(numSpiders>0)                                                    

        {

            CCSprite *tempSplider = [spiders lastObject];                   // 取得最后一个蜘蛛对象

            CGSize size = [tempSplider texture].contentSize;                // 得到蜘蛛对象的尺寸

            for (int i = 0; i<numSpiders; i++)                              

            {

                CCSprite *spider = [spiders objectAtIndex:i];               // 循环每个蜘蛛对象

                spider.position = CGPointMake(size.width * i + size.width * 0.5f

                                          , screenSize.height+size.height); // 将蜘蛛下移一个图片高度

                [spider stopAllActions];                                    // 停止蜘蛛对象的所有动作

            }

        }

        [self unschedule:@selector(spidersUpdate:)];                        // 停止所有循环动作

        [self schedule:@selector(spidersUpdate:) interval:0.7f]; // 重现启动所有循环动作,每隔0.7秒循环蜘蛛下落动作

        numSpidersMoved = 0;                                                // 重置移动过的蜘蛛数量为0

        spiderMoveDuration = 4.0f;                                          // ??????

    }

     

    #pragma mark 每隔0.7秒,随机挑选一个蜘蛛,检查它是否有空,如果是则更新它的位置

    - (void)spidersUpdate:(ccTime)delta

    {

        for (int i = 0; i<10; i++)

        {

            // CCRANDOM_0_1() == ((random() / (float)0x7fffffff ))

            float rf = CCRANDOM_0_1();      // 生成01之间的某个随机数

            int randomSpiderIndex = rf*[spiders count];

            CCLOG(@"random = %f,spiderCount = %d,randomSpiderIndex = %d",rf,[spiderscount],randomSpiderIndex);

            CCSprite *spider = [spiders objectAtIndex:randomSpiderIndex]; // 根据随机数选取某只蜘蛛

            if([spider numberOfRunningActions] == 0)        // 判断这只蜘蛛是否在执行动作

            {

                [self runSpiderMoveSequence:spider];        // 如果这只蜘蛛没有动作,则让它执行动作

                break;                                      // 退出循环

            }

        }

    }

     

    #pragma mark 通过动作序列控制某个蜘蛛的运动

    - (void)runSpiderMoveSequence:(CCSprite *)spider

    {

        numSpidersMoved ++;             // 下落蜘蛛数加1

        if(numSpidersMoved %8 == 0 && spiderMoveDuration > 2.0f)

        // 每落下 8 个蜘蛛,spiderMove - Duration 就降低,从而增加所有蜘蛛的速度。

        {

            spiderMoveDuration -= 0.1f;

        }

        CGPoint belowScreenPosition = CGPointMake(spider.position.x

                                                  , -[spider texture].contentSize.height); // 下落一个蜘蛛位置

        CCMoveTo *move = [CCMoveToactionWithDuration:spiderMoveDuration

                                              position:belowScreenPosition]; // 下落动作

        CCCallFuncN *call = [CCCallFuncNactionWithTarget:self

                                                 selector:@selector(spiderDidDrop:)];

        CCSequence *sequence = [CCSequence actions:move,call,nil];  // 动作序列

        [spider runAction:sequence];    // 执行动作序列

    }

     

    - (void)spiderDidDrop:(id)sender

    {

        NSAssert([sender isKindOfClass:[CCSpriteclass]],@"sender is not a CCSprite");

        CCSprite *spider = (CCSprite *)sender;

        CGPoint pos = spider.position;

        CGSize screenSize = [[CCDirectorsharedDirector] winSize];

        pos.y = screenSize.height + [spider texture].contentSize.height;

        spider.position = pos;

    }

    #pragma mark 碰撞测试

    -(void) checkForCollision

    {

        float playerImageSize = [player texture].contentSize.width;                 // 主角宽度

        float spiderImageSize = [[spiders lastObject] texture].contentSize.width;   // 蜘蛛宽度

        float playerCollisionRadius = playerImageSize * 0.4f;       // 主角半径

        float spiderCollisionRadius = spiderImageSize * 0.4f;       // 蜘蛛半径

        

        float maxCollisionDistance = playerCollisionRadius + spiderCollisionRadius;

        // 主角与蜘蛛之间的最大的安全距离

        

        int numSpiders = [spiders count];

        for (int i = 0; i < numSpiders; i++)

        {

            CCSprite* spider = [spidersobjectAtIndex:i];

            if ([spider numberOfRunningActions] == 0// 如果蜘蛛没有发生动作

            {

                continue;

            }

            

            float actualDistance = ccpDistance(player.position, spider.position); // 主角与蜘蛛之间的距离

            if (actualDistance < maxCollisionDistance)  // 如果主角与蜘蛛之间的距离小于安全距离,说明他们碰撞了

            {

                [self resetSpiders];

                totalTime = 0;

                score = 0;

                [scoreLabelsetString:@"0"];

                break;

            }

        }

    }

     

    CCLabelBMFont 简介 

    CCLabelBMFont 的特色就是以占用更多内存为代价加快标签的更新,这与其他任何 CCSprite 类相似。 

  • 相关阅读:
    7个最好的免费杀毒软件下载
    VMware虚拟机扩容
    tomcat的JK和JK2
    面向对象——接口
    JPA入门样例(採用JPA的hibernate实现版本号)
    JAVA数组的定义及用法
    Styles and Themes
    OpenSSL再曝CCS注入漏洞-心伤未愈又成筛子
    纯文本抽出程序库DMC TEXT FILTER
    数据结构课程设计之通讯录管理系统
  • 原文地址:https://www.cnblogs.com/sell/p/2852767.html
Copyright © 2020-2023  润新知