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

简介:

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

一、项目验证

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

image

    其中有多项配置值可通过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>

    看看运行结果:

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

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


xiaotie 集异璧实验室(GEBLAB)

相关文章
|
6月前
|
JavaScript 数据可视化 PHP
想要快速开发一个系统?选 BuildAdmin 就对了!
Part1介绍 基于 Vue3.3 + ThinkPHP8 + TypeScript + Vite + Pinia + Element Plus 等流行技术栈的后台管理系统,自适应多端、可视化 CRUD 代码生成、自带 WEB 终端、同时提供 Web、WebNuxt、Server 端、内置全局数据回收站和字段级数据修改保护、自动注册路由、无限子级权限管理等,无需授权即可免费商用,希望能帮助大家实现快速开发。
94 0
|
6月前
|
小程序 JavaScript Java
基于微信小程序的点餐系统小程序的设计与实现(源码+lw+部署文档+讲解等)
基于微信小程序的点餐系统小程序的设计与实现(源码+lw+部署文档+讲解等)
|
6月前
|
Go
区域代理分红商城系统开发指南教程/步骤功能/方案逻辑/源码项目
The development of regional proxy dividend distribution mall system involves multiple aspects such as proxy dividend function and electronic mall system development. The following is an overview of the steps for developing a regional agent dividend distribution mall system
|
6月前
|
小程序 JavaScript 前端开发
【经验分享】如何实现在支付宝小程序内的图片裁剪功能
【经验分享】如何实现在支付宝小程序内的图片裁剪功能
145 1
|
6月前
|
安全 区块链
区块链游戏系统开发步骤需求丨功能逻辑丨规则玩法丨指南教程丨源码详细
Developing blockchain game systems has been a highly anticipated field in recent years. By combining blockchain technology and game mechanics, players can enjoy a brand new gaming experience and higher game credibility.
|
小程序 API
10行代码实现微信小程序支付功能,使用小程序云开发实现小程序支付功能(含源码)
10行代码实现微信小程序支付功能,使用小程序云开发实现小程序支付功能(含源码)
391 0
|
6月前
|
前端开发 测试技术 UED
前端知识(十四)——浅谈用户体验测试的主要功能
前端知识(十四)——浅谈用户体验测试的主要功能
127 0
|
存储 前端开发 安全
什么是盲盒游戏系统开发规则丨指南教程丨功能逻辑丨需求项目丨源码方案
确定盲盒游戏的目标受众、玩法要素和游戏规则。 - 确定游戏系统的核心功能,如盲盒的获取、开启、物品收集、交易等。 - 确定技术平台和开发语言,如移动端应用的开发是选择原生开发(如iOS的Swift或Android的Java/Kotlin)还是跨平台开发(如React Native或Flutter)。
|
前端开发
前端代码简洁之路,后台系统之详情页设计
前端业务开发中,为了脱离舒适区,也为了解放重复功能开发的劳动力,会将一些功能进行改造,本期改造千篇一律的详情页。
3991 26
前端代码简洁之路,后台系统之详情页设计
|
JavaScript 前端开发
【从零到一手撕脚手架 | 第四节】加速开发效率 使用plop生成开发模板 使用mock进行数据模拟
基础的脚手架已经搭建完毕,如果我们想快速生成几个基础的组件模板我们可以使用Plop或者使用文件写入实现。比如我们不想等后端同学的接口,可以直接使用mock模拟数据生成。
283 0
【从零到一手撕脚手架 | 第四节】加速开发效率 使用plop生成开发模板 使用mock进行数据模拟
下一篇
无影云桌面