zoukankan      html  css  js  c++  java
  • 【转载】使用铁哥SmartFlash快速开发方案:66行代码搞定抽奖程序!

      最近埋头耕耘,在老外文章的基础上弄出了一套Flash快速开发的方案,且在项目中得到了验证。大体思路在以前的博客中透露过1,2,如:《不用Flex,进行轻量级的Flash RIA开发以降低发布文件的尺寸》和《几行代码搞定Flash应用的多语言实时切换问题》,今天,借吴秦的例子《大家快来玩转盘抽奖游戏(走在网页游戏开发的路上(七))》来进行全面展示,看看怎么用66行代码搞定抽奖程序!

    一、项目验证

        先看项目成绩,下面是一个风速控件(由于是为客户开发的,就不提供swf了,只提供截图):

    image

        其中有多项配置值可通过js设置,见下:

                var config3 =       
                {        
                    300,                // 控件宽        
                    height:300,                // 控件高        
                    showAnimation:true,        // 是否显示动画        
                    animateSeconds:1.5,        // 动画速度,单位为秒        
                    title:"风速(m/s)",        // 标题        
                    titleFontSize:14,        // 标题字体大小        
                    value:132.9,            // 控件显示值,单位:角度        
                    valueFontSize:12,        // 控件显示值的字体大小        
                    titleMiddleOffset:-35,    // 标题的纵坐标离圆心的距离,负代表在上        
                    valueMiddleOffset:20,    // 内容框的纵坐标离圆心的距离,负代表在上        
                    innerRadius:90,            // 內圆半径        
                    innerThickness:8,        // 內圆厚度        
                    minScaleValue:0,        // 最小刻度值        
                    maxScaleValue:140,        // 最大刻度值        
                    gapAngles:38,            // 空缺扇形的角度        
                    scaleGrids:14,            // 刻度的格数        
                    // 刻度盘的染色配置        
                    masklist:"{min:0,max:25,color:0x66b266; min:80,max:140,color:0xfc6464}"        
                };

                swfobject.embedSWF('SectorMeter.swf', 'demo3', "300", "300", "9.0.0", {}, config3);

        还可以动态改变控件值(有动画效果):

    thisMovie("demo3").setValue(xxx);

        这控件看起来蛮复杂的,实际上抛开公共代码,具体的编码量总计为254行!swf文件大小为25k(比用flash开发的会略大)。充分证明了只用Flex的思想和工具类的Flash开发的可行性和有效性。需要说明的是,项目类型需要设定成 MX only。

    二、3个基础类

        先介绍3个基础类:BaseComponent、BaseContainer和Application。BaseComponent.as 和 BaseContainer.as 绝大部分是沿用了 minimalcomps 的Component.as 和 Container.as代码,我只是加了个removeAllChildren方法:

    public function removeAllChildren():void       
    {        
        while( this.numChildren > 0)        
        {        
            this.removeChildAt(0);        
        }        
    }

        接着是 Application.as 类,也是使用了国外文章的方案(很抱歉,原文地址忘记了):

    package       
    {        
        import flash.display.DisplayObject;        
        import flash.display.Sprite;        
        import flash.display.StageAlign;        
        import flash.display.StageScaleMode;        
        import flash.events.Event;        
        [DefaultProperty( "children" )]        
        [Bindable]        
        public class Application extends Sprite        
        {        
            protected var _Number = 0;        
            protected var _height:Number = 0;        
            public function Application()        
            {        
                super();        
                x = 0;        
                y = 0;        
                if(stage != null)        
                {        
                    stage.align = StageAlign.TOP_LEFT;        
                    stage.scaleMode = StageScaleMode.NO_SCALE;        
                }        
                addEventListener(Event.ENTER_FRAME, onInvalidate);        
            }        
            private var _children:Vector.<DisplayObject>;        
            private var childrenChanged:Boolean = false;        
            public function get children():Vector.<DisplayObject>        
            {        
                return _children;        
            }        
            public function set children( value:Vector.<DisplayObject> ):void        
            {        
                if ( _children != value )        
                {        
                    _children = value;        
                    childrenChanged = true;        
                    invalidate();        
                }        
            }        
            protected function invalidate():void        
            {        
                addEventListener(Event.ENTER_FRAME, onInvalidate);        
            }        
            protected function onInvalidate(event:Event) : void        
            {        
                if ( childrenChanged )        
                {        
                    while ( numChildren > 0 )        
                    {        
                        removeChildAt( 0 );        
                    }        
                    for each ( var child:DisplayObject in children )        
                    {        
                        addChild( child );        
                    }        
                    childrenChanged = false;        
                }        
                removeEventListener(Event.ENTER_FRAME, onInvalidate);        
            }        
            override public function set width(w:Number):void        
            {        
                _width = w;        
                invalidate();        
                dispatchEvent(new Event(Event.RESIZE));        
            }

            override public function get width():Number       
            {        
                return _width;        
            }        
            override public function set height(h:Number):void        
            {        
                _height = h;        
                invalidate();        
                dispatchEvent(new Event(Event.RESIZE));        
            }

            override public function get height():Number       
            {        
                return _height;        
            }        
            override public function set x(value:Number):void        
            {        
                super.x = Math.round(value);        
            }        
            override public function set y(value:Number):void        
            {        
                super.y = Math.round(value);        
            }        
        }        
    }

        这样一来,就可以在MXML中进行布局了。

    三、第一个程序:雅美蝶!

        下面,基于上面的三个类,写出第一个程序:Hello World。当然,为了与时俱进,这里不能叫Hello World,叫雅美蝶!

        由于在Flash Builder开发环境中,即使引用了包含fl的库文件,也不会提示其中的控件。为了方便以及改变原控件的一些不合理行为,我们可以继承fl控件,如用Label继承TextField类:

    package       
    {        
        import flash.text.TextField;        
        import flash.text.TextFormat;

        public class Label extends TextField       
        {        
            public override function set defaultTextFormat(format:TextFormat):void        
            {        
                if(this.defaultTextFormat != format)        
                {        
                    super.defaultTextFormat = format;        
                    this.text = this.text;        
                }        
            }        
        }        
    }

        因为 TextField 需要设定 defaultTextFormat 在先,设定 text 在后,不然 text 是不会改变的,在MXML中十分难用。这里重写defaultTextFormat 的 setter方法。

        TextFormat类在MXML下也十分难用,这里我们也继承下它:

    package       
    {        
        import flash.text.TextFormat;

        public class TextFormatter extends TextFormat       
        {        
            public function TextFormatter()        
            {        
                super();        
                this.font = "宋体";        
            }        
            public function setBold(val:Boolean = true):TextFormatter        
            {        
                this.bold = true;        
                return this;        
            }        
            public function setAlign(val:String = "left"):TextFormatter        
            {        
                this.align = val;        
                return this;        
            }        
            public function setSize(val:int = 10):TextFormatter        
            {        
                this.size = val;        
                return this;        
            }        
        }        
    }

        这样一改,就可以很方便的利用IDE的智能提示了。

        下面,写出第一个程序:雅美蝶!

    <?xml version="1.0" encoding="utf-8"?>       
    <local:Application xmlns:fx="
    http://ns.adobe.com/mxml/2009"
                       xmlns:local="*" width="500" height="100"        
                       xmlns:d="flash.display.*" 
                       >        
        <local:Label x="30" y="30" text="雅美蝶!"        
                     defaultTextFormat="{new TextFormatter().setSize(20)}"        
                     width="100" />        
    </local:Application>

        看看运行结果:

    image

        程序大小:6033Byte!

        下面我们让它动起来。虽然可以自己写动画代码,但为了省事,还是直接调用大名鼎鼎的Tweening,这里使用TweenLite:

    <?xml version="1.0" encoding="utf-8"?>      
    <local:Application xmlns:fx="
    http://ns.adobe.com/mxml/2009"
                       xmlns:local="*" width="500" height="100"      
                       click="tween()"       
                       >       
        <fx:Script>       
            <![CDATA[       
                import com.greensock.TweenLite;       
                import com.greensock.easing.*;       
                [Bindable]       
                public var labelFontSize:Number = 20;       
                private function tween():void       
                {       
                    labelFontSize = 20;       
                    alpha = 1;       
                    TweenLite.to(this,3,{labelFontSize:0, alpha:0});       
                }       
            ]]>       
        </fx:Script>       
        <local:Label id="label" x="{30}" y="30" text="雅美蝶!"       
                     defaultTextFormat="{new TextFormatter().setSize(labelFontSize)}"       
                     width="100" />        
    </local:Application>

        由于使用了数据绑定和tweening,程序尺寸增到了27KB。下面是Flash程序,可用鼠标点击查看动画

    四、一个很重要的组件:BackGround

        一旦能用图片作为背景,就可以实现出种种的皮肤效果,下面,引入一个非常重要的组件BackGround,支持嵌入图片,且具有九宫格。BackGround对带九宫格支持的 ScaleBitmap 类进行了封装:

    package       
    {        
        import flash.display.Bitmap;        
        import flash.display.BitmapData;        
        import flash.display.DisplayObject;        
        import flash.display.Graphics;        
        import flash.display.Sprite;        
        import flash.events.Event;        
        import flash.geom.Matrix;        
        import flash.geom.Rectangle;

        public class BackGround extends BaseComponent       
        {        
            [Bindable]        
            public var source:*;        
            [Bindable]        
            public var sourceScale9Grid:Rectangle;        
            public function BackGround():void        
            {        
                super();        
            }        
            public override function draw():void        
            {        
                super.draw();        
                if(source)        
                {        
                    if(source is BitmapData)        
                    {        
                        drawBitmapData(source);        
                    }        
                    else if(source is Class)        
                    {        
                        var bmp:Bitmap = new source() as Bitmap;        
                        if(bmp != null)        
                        {        
                            drawBitmapData(bmp.bitmapData);        
                        }        
                    }        
                }        
            }        
            private var _bgBitmap:DisplayObject = null;        
            private function drawBitmapData(bmpData:BitmapData):void        
            {        
                if(_bgBitmap != null)        
                {        
                    this.removeChild(_bgBitmap);        
                    _bgBitmap = null;        
                }        
                if(bmpData == null) return;        
                var sb:ScaleBitmap = new ScaleBitmap(bmpData,"auto",true);        
                sb.scale9Grid = this.sourceScale9Grid;        
                sb.setSize(this.width,this.height);        
                _bgBitmap = sb;        
                this.addChild(sb);        
            }        
        }        
    }

    五、实现抽奖程序

        现在万事俱备,让我们在上面介绍的基础上实现抽奖程序。直接使用吴秦的例子《大家快来玩转盘抽奖游戏(走在网页游戏开发的路上(七))》中的图片资源,把这些资源提取出来,分别命名为arrow.png、bg.jpg和top.png,放在src/assets目录下。

    image     下面进行布局:

    <?xml version="1.0" encoding="utf-8"?>       
    <local:Application xmlns:fx="
    http://ns.adobe.com/mxml/2009"
                       xmlns:local="*" width="500" height="500"        
                       >        
        <local:BackGround x="{width*0.5-0.5-0.5*428}" y="{height*0.5-0.5-0.5*427}"        
                          width="428" height="427" source="@Embed(source='assets/bg.jpg')"        
                          />        
        <local:BackGround x="{width*0.5-0.5-0.5*103}" y="{height*0.5-0.5-0.5*103}"        
                          width="103" height="103" source="@Embed(source='assets/top.png')"        
                          />        
    </local:Application>

        效果图:

    image

        下面添加Arrow类:

    package       
    {        
        import flash.display.Bitmap;        
        import flash.display.Graphics;

        public class Arrow extends BaseComponent       
        {        
            [Embed(source='assets/arrow.png')]        
            public var arrowClass:Class;        
            public var offset:Number = 60; // 箭头资源的末端离圆心的偏移量        
            private var _angle:Number = 0;        
            public function get angle():Number        
            {        
                return _angle;        
            }        
            public function set angle(value:Number):void        
            {        
                _angle = value;        
                this.rotation = value;        
            }        
            public override function draw():void        
            {        
                this.removeAllChildren();        
                var g:Graphics = this.graphics;        
                g.clear();        
                var bmp:Bitmap = new arrowClass() as Bitmap;        
                bmp.x = -bmp.width/2;        
                bmp.y = -bmp.height/2 - offset;        
                this.addChild(bmp);        
            }        
        }        
    }

        上类offset是箭头资源的末端离圆心的偏移量。而由于rotation 的取值范围为-180~180,不能直接用在动画中,因此,添加angle字段对它进行封装。

        下面将Arrow类添加到布局中:

    <?xml version="1.0" encoding="utf-8"?>       
    <local:Application xmlns:fx="
    http://ns.adobe.com/mxml/2009"
                       xmlns:local="*" width="500" height="500"        
                       >        
        <local:BackGround x="{width*0.5-0.5-0.5*428}" y="{height*0.5-0.5-0.5*427}"        
                          width="428" height="427" source="@Embed(source='assets/bg.jpg')"        
                          />        
        <local:Arrow x="{width*0.5-0.5}" y="{height*0.5-0.5}" >        
        </local:Arrow>        
        <local:BackGround x="{width*0.5-0.5-0.5*103}" y="{height*0.5-0.5-0.5*103}"        
                          width="103" height="103" source="@Embed(source='assets/top.png')"        
                          />        
    </local:Application>

        效果图:

    image

        像模像样了吧!

        万事俱备,下面添加动画,为了方便,这里用固定值,实际应用中,应该是去服务器取值:

    <?xml version="1.0" encoding="utf-8"?>      
    <local:Application xmlns:fx="
    http://ns.adobe.com/mxml/2009"
                       xmlns:local="*" width="500" height="500"      
                       >       
        <fx:Script>       
            <![CDATA[       
                import com.greensock.TweenLite;       
                import com.greensock.easing.*;       
                private function roll(val:int):void       
                {       
                    val = val%8;       
                    arrow.angle = arrow.rotation;  // 把  angle 恢复到 -180-180 之间       
                    var newAngle:Number = val * 360 / 8 + 360 * 5;  // 多转几圈       
                    TweenLite.to(arrow, 10, { angle:newAngle, ease:Expo.easeOut }); // 使用 Expo.easeOut 让转动先快后慢       
                }       
            ]]>       
        </fx:Script>       
        <local:BackGround x="{width*0.5-0.5-0.5*428}" y="{height*0.5-0.5-0.5*427}"        
                          width="428" height="427" source="@Embed(source='assets/bg.jpg')"        
                          />       
        <local:Arrow id="arrow" x="{width*0.5-0.5}" y="{height*0.5-0.5}" >       
        </local:Arrow>       
        <local:BackGround x="{width*0.5-0.5-0.5*103}" y="{height*0.5-0.5-0.5*103}"        
                          width="103" height="103" source="@Embed(source='assets/top.png')"        
                          click="roll(4)"        
                          buttonMode="true" useHandCursor="true"        
                          />       
    </local:Application>

        下面看动画,点击中间的“抽奖”按钮即可进行抽奖:

        程序大小:58KB。比吴秦的例子(68KB)中还要小10K。而如果不用数据绑定(仔细观看上面代码,这个例子中数据绑定无用),代码的尺寸还可以小上几K。 而编码量呢?抛除基础类,代码量只有 29 + 37 = 66 行(算进空格,{,}等)!

        66行代码!!!代码就不打包下载了,如果感兴趣,自己动手做一遍会比直接拿Demo编译收获更大。

  • 相关阅读:
    4.2编写第一个servlet(500错误解决)超级开心
    springmvc文件上传下载
    找出字符串中不重复字符的最长子串的长度
    微信小程序接入,https服务器搭建和调试
    js常用写法
    通过条件删除标签
    xml的修改遍历,以及建立
    shelve模块
    dump与load
    locate,find,df,mount,du命令
  • 原文地址:https://www.cnblogs.com/fx2008/p/2324366.html
Copyright © 2011-2022 走看看