zoukankan      html  css  js  c++  java
  • Cocos2d-x入门之旅[3]动作

    Cocos通过动作(Action)让精灵动起来,把数个动作组成序列(Sequence)就能让精灵做出连续的动作,在动作中我们可以改变精灵的位置,旋转角度,缩放比例,等等

    动作(Action)

    首先我们创建一个Action对象,同样使用create,这里我们还是使用HelloWorld场景里的那张图片

    auto sprite = Sprite::create("sinnosuke.png");
    

    setPosition之后我们加上一句

    // 在2秒内:向右移动精灵50像素,向上移动精灵10像素
    auto moveBy = MoveBy::create(2, Vec2(50, 10));
    sprite->runAction(moveBy);
    

    这个精灵就会平滑地根据我们输入的参数移动

    如果把moveBy改成moveTo,那就会是另一种结果:

    // 在2秒内:把精灵移动到坐标(50,10)
    auto moveTo = MoveTo::create(2, Vec2(50, 10));
    sprite->runAction(moveTo);
    

    精灵直接移动到了(50,10)(锚点在其正中间)

    By 和 To 的区别

    • By算的是相对于节点对象的当前位置
    • To算的是绝对位置,不考虑当前节点对象在哪

    动作组合

    你还可以把多个动作加入到一个序列(Sequence)里,让精灵按执行序列

    auto moveBy = MoveBy::create(2, Vec2(50, 10));
    auto moveTo = MoveTo::create(2, Vec2(50, 10));
    auto delay = DelayTime::create(1);//设置一个一秒的延时,也加入序列中
    auto seq = Sequence::create(moveBy, delay, moveTo, nullptr);
    //做动作moveBy后,延时1秒,做动作moveTo
    sprite->runAction(seq);
    

    精灵就会按次序执行序列里的动作

    序列我们之后再详细讲解

    基本动作

    移动

    MoveToMoveBy,使精灵在指定时间内移动到指定地点

    auto sprite = Sprite::create("sinnosuke.png");
    auto delay = DelayTime::create(1);
    
    // 在2秒内:向右移动精灵50像素,向上移动精灵10像素
    auto moveBy = MoveBy::create(2, Vec2(50, 10));
    // 在2秒内:把精灵移动到坐标(50,10)
    auto moveTo = MoveTo::create(2, Vec2(50, 10));
    
    auto seq = Sequence::create(moveBy, delay, moveTo, nullptr);
    sprite->runAction(seq);
    

    效果如上图

    旋转

    RotateToRotateBy,使精灵在指定时间内旋转到指定角度

    auto sprite = Sprite::create("sinnosuke.png");
    auto delay = DelayTime::create(1);
    
    // 在2秒内:把精灵从原始位置顺时针旋转40度
    auto rotateBy = RotateBy::create(2.0f, 40.0f);
    // 在2秒内:把精灵从目前位置旋转到顺时针40度的位置
    auto rotateTo = RotateTo::create(2.0f, 40.0f);
    
    auto seq = Sequence::create(rotateBy, delay, rotateTo, nullptr);
    sprite->runAction(seq);
    

    你应该会看到这个图片转了一次就不动了,其实不是不动了

    因为在第一个动作后你已经让图片转到了顺时针40度的位置,第二个动作的目标“把精灵从目前位置旋转到顺时针40度的位置”即为目前的位置,所以看上去就是不动了

    建议你把两个动作先后顺序对调一下,运行看看,方便理解

    缩放

    ScaleBy ScaleTo 在指定时间内完成指定比例缩放

    auto sprite = Sprite::create("sinnosuke.png");
    
    // Scale uniformly by 3x over 2 seconds
    // 在2秒内:把精灵等比放大到3倍
    auto scaleBy = ScaleBy::create(2.0f, 3.0f);
    
    // Scale X by 5 and Y by 3x over 2 seconds
    // 在2秒内:把精灵的x轴放大到3倍并把y轴放大到3倍
    auto scaleBy = ScaleBy::create(2.0f, 3.0f, 3.0f);
    
    // 在2秒内:把精灵缩放到:等比放大3倍的状态
    auto scaleTo = ScaleTo::create(2.0f, 3.0f);
    
    // Scale X to 5 and Y to 3x over 2 seconds
    // 在2秒内:把精灵缩放到:x轴放大到3倍,把y轴放大到3倍的状态
    auto scaleTo = ScaleTo::create(2.0f, 3.0f, 3.0f);
    

    通过对旋转的理解(主要是To和By的理解),上述代码不难看懂,这里不多给出运行效果了,感兴趣可以自己写个Sequence测试

    淡入淡出

    FadeIn 淡入,FadeOut 淡出 (其实就是修改节点对象的透明度属性,FadeIn从完全透明到完全不透明,FadeOut 相反)

    auto sprite = Sprite::create("sinnosuke.png");
    auto delay = DelayTime::create(1);//设置一个一秒的延时,也加入序列中
    
    auto fadeIn = FadeIn::create(1.0f);
    auto fadeOut = FadeOut::create(2.0f);
    
    auto seq = Sequence::create(delay, fadeOut, delay, fadeIn, nullptr);
    sprite->runAction(seq);
    

    也很简单,代码也给出了,可以自己运行看看

    色彩混合

    使用 TintTo TintBy,将一个实现了 NodeRGB 协议的节点对象进行色彩混合

    auto sprite = Sprite::create("sinnosuke.png");
    auto delay = DelayTime::create(1);
    
    // 指定RGB值为节点着色
    auto tintTo = TintTo::create(2.0f, 120.0f, 232.0f, 254.0f);
    // 指定RGB值为增量为节点着色
    auto tintBy = TintBy::create(2.0f, 120.0f, 232.0f, 254.0f);
    
    auto seq = Sequence::create(tintTo, delay, tintBy, nullptr);
    sprite->runAction(seq);
    

    变化如下:

    此外还有帧动画变速运动

    帧动画使用 Animate 对象,通过每隔一个短暂时间进行图像替代的方式,实现一个动画效果

    变速动作可以让节点对象具有加速度,用以模仿物理运动,降低性能损耗

    序列(Sequence)

    顾名思义,序列就是多个动作按照特定顺序的一个排列(当然也能反向执行)

    其实序列就是一种封装多个动作的对象,当这个对象执行时,被封装的动作会顺序执行

    Sequence

    一个 Sequence 可以包含任何数量的动作对象,回调方法其它序列,Cocos2d-x 允许把一个方法添加进去 CallFunc 对象,然后将 CallFunc 添加到 Sequence,这样,在执行序列的时候就能触发方法调用

    auto mySprite = Node::create();
    
    auto moveTo1 = MoveTo::create(2, Vec2(50,10));
    auto moveBy1 = MoveBy::create(2, Vec2(100,10));
    auto moveTo2 = MoveTo::create(2, Vec2(150,10));
    
    auto delay = DelayTime::create(1);
    
    mySprite->runAction(
        Sequence::create(
            moveTo1, 
            delay, 
            moveBy1, 
            delay.clone(),
    		moveTo2, nullptr
        )
    );
    

    Spawn

    SpawnSequence 非常相似,但 Spawn 同时执行所有的动作

    Spawn 对象可以添加任意数量的动作,和其它 Spawn 对象,可能不同动作的执行时间不一致,在这种情况下,他们不会同时结束

    auto myNode = Node::create();
    
    auto moveTo1 = MoveTo::create(2, Vec2(50,10));
    auto moveBy1 = MoveBy::create(2, Vec2(100,10));
    auto moveTo2 = MoveTo::create(2, Vec2(150,10));
    
    myNode->runAction(Spawn::create(moveTo1, moveBy1, moveTo2, nullptr));
    

    克隆

    克隆(Clone) 的功能和字面含义一样,如果你对一个节点对象使用了 clone() 方法,你就获得了这个节点对象的拷贝

    为什么要使用 clone() 方法? 因为当 Action 对象运行时会产生一个内部状态,记录着节点属性的改变,当你想将一个创建的动作,重复使用到不同的节点对象时,如果不用 clone() 方法,就无法确定这个动作的属性到底是怎样的(因为被使用过,产生了内部状态),这会造成难以预料的结果

    我们来看示例,假如你有一个坐标位置是 (0,0)heroSprite,执行这样一个动作:

    MoveBy::create(10, Vec2(400,100));
    

    你的 heroSprite 就在 10s 的时间中,从 (0,0) 移动到了 (400,100)heroSprite 有了一个新位置 (400,100),更重要的是动作对象也有了节点位置相关的内部状态了

    现在假如你有一个坐标位置是 (200,200)emenySprite,你还使用这个相同的动作,emenySprite 就会移动到 (800,200)的坐标位置,并不是你想要的结果,因为第二次将这个动作应用的时候,它已经有内部状态了

    使用 clone() 能避免这种情况,克隆获得一个新的动作对象,新的对象没有之前的内部状态

    以下错误的用法:

    auto heroSprite = Sprite::create("herosprite.png");
    auto enemySprite = Sprite::create("enemysprite.png");
    
    auto moveBy = MoveBy::create(10, Vec2(400,100));
    
    heroSprite->runAction(moveBy);
    
    enemySprite->runAction(moveBy);
    

    使用 clone() 的正确情况:

    auto heroSprite = Sprite::create("herosprite.png");
    auto enemySprite = Sprite::create("enemysprite.png");
    
    auto moveBy = MoveBy::create(10, Vec2(400,100));
    
    heroSprite->runAction(moveBy);
    
    enemySprite->runAction(moveBy->clone());
    

    倒转

    倒转(Reverse) 的功能也和字面意思一样,调用 reverse() 可以让一系列动作按相反的方向执行,reverse() 不是只能简单的让一个 Action 对象反向执行,还能让 SequenceSpawn 倒转

    mySprite->runAction(mySpawn->reverse());
    

    应用实例

    auto mySprite = Sprite::create("mysprite.png");
    mySprite->setPosition(50, 56);
    
    auto moveBy = MoveBy::create(2.0f, Vec2(500,0));
    auto scaleBy = ScaleBy::create(2.0f, 2.0f);
    auto delay = DelayTime::create(2.0f);
    
    auto delaySequence = Sequence::create(delay, delay->clone(), delay->clone(),
    delay->clone(), nullptr);
    
    auto sequence = Sequence::create(moveBy, delay, scaleBy, delaySequence, nullptr);
    
    mySprite->runAction(sequence);
    
    mySprite->runAction(sequence->reverse());
    
  • 相关阅读:
    PHP中feof()函数的猜测
    PHP curl函数模拟爬虫(操作cookie)
    django发音
    Nginx出现“413 Request Entity Too Large”错误解决方法
    Python开发利器WingIDE破解方法
    开启Apache mod_rewrite
    LIBCD.lib(crt0.obj) : error LNK2001: unresolved external symbol _main
    python 正则学习
    php定时执行任务
    命令行CURL教程[转载]
  • 原文地址:https://www.cnblogs.com/zhxmdefj/p/11701526.html
Copyright © 2011-2022 走看看