1

大多数社交游戏(如 CastleVille (c) Zynga 或 Magic Land (c) Wooga)都有硬币、星星等奖励给玩家一些简单的动作,比如砍树。

doobers 似乎执行了几个补间:

  1. 首先,他们扑通一声跳了出来。它们的尺寸也会反弹。
  2. 之后,他们以贝塞尔曲线飞到得分栏。

我为我的问题准备了一个非常简单的测试用例和屏幕截图。测试用例在 Flex 中,因为这是我最近一直在使用的,但我的问题更笼统(ActionScript,Tween)。我正在使用com.greensock.TweenMax库。

我的问题:我已经弄清楚如何做第二个贝塞尔部分。但我不知道,第一个弹跳部分怎么做?

在此处输入图像描述

MyApp.mxml(不一定是 Flex,可以是 Flash):

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" 
               applicationComplete="init()">

    <fx:Script>
        <![CDATA[
            import mx.collections.ArrayList;
            import spark.core.SpriteVisualElement;
            import com.greensock.TweenMax;
            import com.greensock.easing.Cubic;

            private function init():void {
                var g:Graphics = myComp.graphics;
                g.clear();
                g.beginFill(0xCCCCCC);
                g.drawRect(0, 0, myComp.width, myComp.height);
                g.endFill();                
            }           

            private function handleClick(event:MouseEvent):void {
                var star:SpriteVisualElement = new Star();
                star.x = event.localX;
                star.y = event.localY;
                myComp.addChild(star);

                TweenMax.to(star, 1, {
                    delay: 2,
                    ease:  Cubic.easeOut,
                    bezier: [
                        {x: myComp.width - star.width, y: Math.max(event.localY, myComp.height/2)}, 
                        {x: myComp.width - star.width, y: 0}
                    ]
                });
            }

        ]]>
    </fx:Script>    

    <mx:UIComponent id="myComp" width="100%" height="100%" click="handleClick(event)" />

</s:Application>

星.fxg:

<?xml version='1.0' encoding='UTF-8'?>
<!-- fxg/star.fxg -->
<fxg:Graphic xmlns:fxg="http://ns.adobe.com/fxg/2008" version="2">    
    <fxg:Path x="9.399" y="10.049" data="M 82.016 78.257 L 51.895 69.533 L 27.617 89.351 L 26.621 58.058 L 0.231 41.132 L 29.749 30.52 L 37.714 0.241 L 56.944 24.978 L 88.261 23.181 L 70.631 49.083 Z">
        <fxg:fill>
            <fxg:SolidColor color="#FFFFFF"/>
        </fxg:fill>
        <fxg:stroke>
            <fxg:SolidColorStroke 
                caps="none" 
                color="#4769C4" 
                joints="miter" 
                miterLimit="4" 
                weight="20"/>
        </fxg:stroke>
    </fxg:Path>
</fxg:Graphic>

另外我想知道,如何在最后添加“宝丽来相机闪光灯”效果?

更新:

在 LondonDrugs_MediaServices 的帮助下(谢谢!)doobers 现在挤压和跳跃(代码如下),但我仍然有 3 个未解决的问题:

  1. 如何在鼠标悬停事件上运行 flyTween?
  2. 如何在最后添加“宝丽来闪电战”补间?
  3. 不知道如何在最后删除鼠标悬停处理程序 - 因为它是一个匿名闭包

我还在GreenSock 论坛上发布了我的问题。

谢谢你的任何提示

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" 
               applicationComplete="init()">

    <fx:Script>
        <![CDATA[
            import com.greensock.TweenMax;
            import com.greensock.easing.Bounce;
            import com.greensock.easing.Cubic;
            import spark.core.SpriteVisualElement;

            private function init():void {
                var g:Graphics = myComp.graphics;
                g.clear();
                g.beginFill(0xCCCCCC);
                g.drawRect(0, 0, myComp.width, myComp.height);
                g.endFill();                
            }           

            private function handleClick(event:MouseEvent):void {
                var star:SpriteVisualElement = new Star();
                star.x = event.localX;
                star.y = event.localY;
                myComp.addChild(star);

                TweenMax.to(star, 2, {
                    bezier: [
                        {x:star.x + 10, y:star.y - 20, scaleX: 1,   scaleY: 1}, 
                        {x:star.x + 20, y:star.y + 20, scaleX: 1.2, scaleY: .8}, 
                        {x:star.x + 20, y:star.y + 30, scaleX: 1,   scaleY: 1}], 
                    orientToBezier: false, 
                    ease: Bounce.easeOut
                });

                var flyTween:TweenMax = TweenMax.to(star, 1, {
                    delay: 10,
                    ease:  Cubic.easeOut,
                    bezier: [
                        {x: myComp.width - star.width, y: Math.max(event.localY, myComp.height/2)}, 
                        {x: myComp.width - star.width, y: 0}
                    ],
                    onComplete: function():void {
                        myComp.removeChild(star);
                        // XXX how to remove the mouse over handler here?
                    }
                });

                star.addEventListener(MouseEvent.MOUSE_OVER, function(event:MouseEvent):void {
                    // XXX how to force flyTween to execute right now, without the delay?
                    flyTween.complete();
                });
            }
        ]]>
    </fx:Script>    

    <mx:UIComponent id="myComp" width="100%" height="100%" click="handleClick(event)" />

</s:Application>

UPDATE2:谢谢LondonDrugs_MediaServices,这里再次更新了截图+代码。

和 doobers 一起玩已经很有趣了,但是仍然有 2 个小问题:

  1. 我真的必须杀死(延迟的)补间蝇吗?我不能在鼠标悬停时以某种方式修改它的延迟(将其设置为 0)吗?
  2. 最后有那种“相机闪光”效果会很好。我只是不记得它是如何完成的——一些标准的 Flash MX 效果......

在此处输入图像描述

MyApp.mxml:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" 
               applicationComplete="init()">

    <fx:Script>
        <![CDATA[
            import com.greensock.TweenMax;
            import com.greensock.easing.Bounce;
            import com.greensock.easing.Cubic;
            import flash.filters.GlowFilter;
            import spark.core.SpriteVisualElement;

            private function init():void {
                var g:Graphics = myComp.graphics;
                g.clear();
                g.beginFill(0xCCCCCC);
                g.drawRect(0, 0, myComp.width, myComp.height);
                g.endFill();                
            }           

            private function goFlyTween(star:DisplayObject, delay:Number = 0):void {
                TweenMax.to(star, 1, {
                    delay: delay,
                    ease:  Cubic.easeOut,
                    bezier: [
                        {x: myComp.width - star.width, 
                         y: Math.max(star.y, myComp.height/2)}, 
                        {x: myComp.width - star.width, y: 0}
                    ],
                    onComplete: function():void {
                        if(star.parent)
                            star.parent.removeChild(star);
                    }
                });
            }

            private function handleClick(event:MouseEvent):void {
                var star:SpriteVisualElement = new Star();
                star.filters = [
                    new GlowFilter(0xffffff, 1, 4, 4, 10, 2), 
                    new GlowFilter(0x0, 1, 1.5, 1.5, 10, 2)
                ];
                star.x = event.localX;
                star.y = event.localY;
                myComp.addChild(star);

                TweenMax.to(star, 2, {
                    bezier: [
                        {x:star.x + 10, y:star.y - 20, scaleX: 1,   scaleY: 1}, 
                        {x:star.x + 20, y:star.y + 20, scaleX: 1.2, scaleY: .8}, 
                        {x:star.x + 20, y:star.y + 30, scaleX: 1,   scaleY: 1}], 
                    orientToBezier: false, 
                    ease: Bounce.easeOut,
                    onComplete: goFlyTween,
                    onCompleteParams: [star, 3]
                });

                star.addEventListener(MouseEvent.MOUSE_OVER, function(event:MouseEvent):void {
                    // instead of killing + recreating, can't we just reset the delay?
                    TweenMax.killTweensOf(star);
                    goFlyTween(star);
                }, false, 0, true);
            }
        ]]>
    </fx:Script>    

    <mx:UIComponent id="myComp" width="100%" height="100%" click="handleClick(event)" />

</s:Application>
4

1 回答 1

1

您可以按照与第二部分相同的基本方式进行操作。只需使用 Bounce 缓动函数,并为补间添加一些 scaleX 修改:(当然,您需要为您的场景相应地设置 x/y 值)

TweenMax.to(star, 3, {bezier:[{x:star.x + 20, y:star.y - 10, scaleX: 1}, {x:star.x + 40, y:star.y + 20, scaleX: 2}, {x:star.x + 40, y:star.y + 30, scaleX: 1}], orientToBezier:false, ease:Bounce.easeOut});

编辑

对于您编辑中的其他问题:

我建议为你的 flyTween 制作一个单独的函数,这不是必需的,但在我看来让生活更清洁。mouseOver 处理程序上的弱侦听器将使其成为非问题,请参阅下面代码中的更新。我不知道你所说的“宝丽来闪电战”是什么意思,所以你需要进一步解释。

      private function goFlyTween(star:DisplayObject, delay:Number = 0):void {
           TweenMax.to(star, 1, {
               delay: delay,
               ease:  Cubic.easeOut,
               bezier: [
                   {x: myComp.width - star.width, y: Math.max(event.localY, myComp.height/2)}, 
                   {x: myComp.width - star.width, y: 0}
               ],
               onComplete: function():void {
                    if(star.parent){
                        star.parent.removeChild(star);
               }
           });
       }



       private function handleClick(event:MouseEvent):void {
            var star:SpriteVisualElement = new Star();
            star.x = event.localX;
            star.y = event.localY;
            myComp.addChild(star);

            TweenMax.to(star, 2, {
                bezier: [
                    {x:star.x + 10, y:star.y - 20, scaleX: 1,   scaleY: 1}, 
                    {x:star.x + 20, y:star.y + 20, scaleX: 1.2, scaleY: .8}, 
                    {x:star.x + 20, y:star.y + 30, scaleX: 1,   scaleY: 1}], 
                orientToBezier: false, 
                ease: Bounce.easeOut,
                onComplete: goFlyTween,
                onCompleteParams: [star, 3]
            });

            star.addEventListener(MouseEvent.MOUSE_OVER,function(event:MouseEvent):void {
                TweenMax.killTweensOf(star);
                goFlyTween(star);
            },false,0,true); //use a weak listener (last parameter true on addEventListener), then you don't have to worry about removing the listener.  OR just don't use an anonymous function for this...
        }

对于反弹补间,添加 onComplete 参数:

于 2012-08-17T23:40:47.410 回答