使用铁哥SmartFlash快速开发方案:66行代码搞定抽奖程序!

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

一、项目验证

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

使用铁哥SmartFlash快速开发方案:66行代码搞定抽奖程序!

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

            var config3 = 
            { 
                width: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 _width: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>

    看看运行结果:

使用铁哥SmartFlash快速开发方案:66行代码搞定抽奖程序!

    程序大小: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目录下。

使用铁哥SmartFlash快速开发方案:66行代码搞定抽奖程序!     下面进行布局:

<?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>

    效果图:

使用铁哥SmartFlash快速开发方案:66行代码搞定抽奖程序!

 

 

    下面添加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>

    效果图:

使用铁哥SmartFlash快速开发方案:66行代码搞定抽奖程序! 

    像模像样了吧!

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

<?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编译收获更大。

本文转自xiaotie博客园博客,原文链接http://www.cnblogs.com/xiaotie/archive/2011/06/15/2081386.html如需转载请自行联系原作者


xiaotie 集异璧实验室(GEBLAB)

上一篇:Fiddler手机抓包安装与配置


下一篇:关于myEclipse2016部署项目后jsp文件编码集变成ansi问题解决