Attention, Zin 的交互设计之路。

User interface, user experience and interactive design.

« Yahoo!提出网站内容性能优化的10条建议CSS2属性对照表 »

有道谜题的回忆

有道谜题上线到现在已经一个多月了,这个游戏是给有道难题做的一个在线解谜游戏,游戏规则就是回答问题,答对了会按照顺序解开后面锁定的问题,有些问题可以解开隐藏关。
现在抽出时间来回忆一下当时开发的过程,参考意义并不大,只做日后个人参考。
这个游戏使用是在Flash IDE环境下使用Flash Develop编写ActionScript 3脚本做开发,应用到了TweenLite库做Tween Motion的动画处理,在视觉效果上没有特别的,有一个地方用到了alpha通道跟blend mode等做了处理。在数据方面使用PHPRPC加密内容传输,但是疏忽了客户端从内存提取数据,最后改用MD5加密答案的方式。
分析一下类部分:
信息传输用RPCer 是一个EventDispatcher子类,用来处理问题请求、数据提交、抽奖、列表获取等请求。

package com.didipub.puzzle {
    import flash.events.Event;
    import flash.events.EventDispatcher;
    //import flash.system.Security;
    import org.phprpc.PHPRPC_Client;
    import org.phprpc.PHPRPC_Error;
    public class RPCer extends EventDispatcher {
        
        public static var QuestionsComplete:String = "questionsComplete";
        public static var BillsComplete:String = "billsComplete";
        public static var TotalListComplete:String = "totalListComplete";
        public static var WeekListComplete:String = "weeklyListComplete";
        public static var ScoreComplete:String = "scoreComplete";
        public static var ContactComplete:String = "contactComplete";
        
        private var _client:PHPRPC_Client;
        private var _questionList:XML;
        private var _billList:XML;
        private var _totalList:XML;
        private var _weekList:XML;
        private var _scoreResult:*;
        private var _contactResult:*;
        
        public function RPCer(p:String):void {
            //Security.loadPolicyFile(global.puzzlePath + "crossdomain.xml");
            _client = new PHPRPC_Client(p, ["getQuestions", "getBills", "getTotalList", "postScore", "postContact"]);
            _client.keyLength = 256;
            _client.encryptMode = 2;
        }
        //property
        public function get questionList():XML {
            return _questionList;
        }
        public function get billList():XML {
            return _billList;
        }
        public function get totalList():XML {
            return _totalList;
        }
        public function get weekList():XML {
            return _weekList;
        }
        public function get scoreResult():*{
            return _scoreResult;
        }
        public function get contactResult():*{
            return _contactResult;
        }
        //method
        public function getQuestions():void {
            //获取题目
            _client.getQuestions(function(result:*, args:Array, output:String, warning:PHPRPC_Error) {
                global.debug(result);
                var wn:String = warning.toString();
                if (wn.split(":")[0] > 0) global.debug(wn);
                _questionList = XML(result);
                getQuestionsComplete();
            });
        }
        public function getBills():void {
            //获取IQ排行
            _client.getBills(function(result:*, args:Array, output:String, warning:PHPRPC_Error) {
                global.debug(result);
                var wn:String = warning.toString();
                if (wn.split(":")[0] > 0) global.debug(wn);
                _billList = XML(result);
                getBillsComplete();
            });
        }
        public function getTotalList(t:String="all"):void {
            //获取总积分排行
            _client.getTotalList(t, function(result:*, args:Array, output:String, warning:PHPRPC_Error) {
                global.debug(result);
                var wn:String = warning.toString();
                if (wn.split(":")[0] > 0) global.debug(wn);
                t == "week"?_weekList = XML(result):_totalList = XML(result);
                getTotalListComplete(t);
            }, true);
        }
        public function postScore(u:String, e:String, s:Number, c:Array, iv:*):void {
            //发送用户名及分数
            _client.postScore(u, e, s, c, iv, function(result:*, args:Array, output:String, warning:PHPRPC_Error):void {
                global.debug(result);
                var wn:String = warning.toString();
                if (wn.split(":")[0] > 0) global.debug(wn);
                _scoreResult = result;
                postScoreComplete();
            }, true);
        }
        public function postContact(u:String, tel:String, addr:String, post:String, size:String):void {
            //发送用户名及分数
            _client.postContact(u, tel, addr, post, size, function(result:*, args:Array, output:String, warning:PHPRPC_Error):void {
                global.debug(result);
                var wn:String = warning.toString();
                if (wn.split(":")[0] > 0) global.debug(wn);
                _contactResult = result;
                postContactComplete();
            }, true);
        }
        //private method
        private function getQuestionsComplete():void {
            //得到题目以后,发布QuestionsComplete事件
            dispatchEvent(new Event(RPCer.QuestionsComplete));
        }
        private function getBillsComplete():void {
            //取得IQ名单后,发布BillsComplete事件
            dispatchEvent(new Event(RPCer.BillsComplete));
        }
        private function getTotalListComplete(t:String = "all"):void {
            //取得总积分列表,发布TotalListComplete事件
            t == "week"?dispatchEvent(new Event(RPCer.WeekListComplete)):dispatchEvent(new Event(RPCer.TotalListComplete));
        }
        private function postScoreComplete():void {
            //发送数据后,发布ScoreComplete事件
            dispatchEvent(new Event(RPCer.ScoreComplete));
        }
        private function postContactComplete():void {
            //发送数据后,发布ContactComplete事件
            dispatchEvent(new Event(RPCer.ContactComplete));
        }
    }
}

在游戏中,因为要考虑到不同尺寸屏幕下的自适应,例如logo在左上,抽奖按钮在左下等等,为了方便管理这些元素,将他们各自做成了子类继承自sprite 类,例如Logo类,LuckyDraw类等,这里LuckyDraw类实际是扩展了在Flash IDE中手动创建的一个MovieClip子类BottomCenter(抽奖按钮本来计划放在中间的),这样做的一个原因是为了可以在Flash Develop中能有LuckyDraw的自动提示(囧)。
另外有一个重要的类是Panel类扩展Sprite,游戏中有很多对话面板,例如开场的提示、规则介绍、抽奖面板、操作提示信息、游戏排行、中奖信息等,需要满足基本要求是,打开、关闭、设置颜色、尺寸等样式、关闭按钮获取、关闭及打开是的callback、数据:

package com.didipub.puzzle {
    import flash.display.SimpleButton;
    import flash.display.Sprite;
    import flash.events.MouseEvent;
    import gs.TweenLite;
    public class Panel extends Sprite {
        private var _bg:PanelBackGround;
        private var _mask:PanelBackGround;
        
        protected var _xml:XML;
        protected var _container:Sprite;
        protected var _closeBtn:CloseBtn;
        
        public function Panel() {
            init();
        }
        //property
        public function set data(xml:XML):void {
            _xml = xml;
        }
        public function get closeBtn():SimpleButton {
            return SimpleButton(_closeBtn);
        }
        public function get bg():PanelBackGround {
            return _bg;
        }
        //metod
        public function doOpen(callback:Function = null):void {
            //open
            TweenLite.to(this, .5, { alpha:1, onComplete:callback } );
        }
        public function doClose(callback:Function = null):void {
            //close
            TweenLite.to(this, .3, { alpha:0, onComplete:deleteMe, onCompleteParams:[callback] } );
        }
        public function setSize(w:Number, h:Number):void {
            //set width and height
            with (_bg) {
                width = w;
                height = h;
            }
            with (_closeBtn) {
                x = w;
                y = 0;
            }
            with (_mask) {
                x = -1000 + w / 2;
                y = -1000 + h / 2;
            }
        }
        public function setColor(color:uint=0x000000, a:Number = .95):void {
            TweenLite.to(_bg, .3, { tint:color, alpha:a } );
        }
        //private method
        private function init():void {
            alpha = 0;
            
            _mask = new PanelBackGround;
            addChild(_mask);
            TweenLite.to(_mask, 0, { tint:0x000000 } );
            with (_mask) {
                width = 2000;
                height = 2000;
                alpha = .7;
            }
            
            _bg = new PanelBackGround;
            addChild(_bg);
            //setColor();
            
            _container = new Sprite;
            addChild(_container);
            _container.alpha = 0;
            
            _closeBtn = new CloseBtn;
            addChild(_closeBtn);
            _closeBtn.addEventListener(MouseEvent.CLICK, closeClickHandler);
        }
        private function deleteMe(fn:Function):void {
            if (fn != null) fn();
            _container.alpha = 0;
            parent.removeChild(this);
        }
        //handler
        private function closeClickHandler(e:MouseEvent):void {
            doClose();
        }
    }
}


这是第三次使用action script做项目,第一次是做一个有道桌面词典的gadget当时还弄了个AIR版本的,第二个是帮有道音乐盒的心情音乐做了个minisite,虽然有进步,但还有很多东西都处在学习跟实践的阶段。

欢迎发表看法:

您的讨论更有价值!

订阅

  • 欢迎订阅我的博客Attention!
  • 订阅到有道阅读

© 2008 7thPark.com. Some rights reserved! Z-blog inside. 粤ICP备05035430号

返回页首