说在前头:楼主之前没有不论什么flash开发经验,仅仅是从一次尝试中总结自己的理解和经验而已。假设有写的不正确的地方,欢迎大家指正。

前一段时间尝试想用flash(as3)又一次制作一下之前做的一个游戏。作为从来没有接触过flash开发的我来说。花了一些时间研究现有的一些框架。尽管如今我已经放弃了使用flash来开发(后面会说原因),但我认为还是有必要总结一下这个过程中对于flash、starling、starling mvc的一些理解。

由于一開始我是使用silverlight开发游戏的,它有一个极大的便利是微软提供了强大好用的Microsoft Blend Expression。能够非常好的、所见即所得用它来制作UI。自然而然,我非常想在flash的开发环境下找一个替代品。但非常遗憾。最后我自己得出的结论是:没有。

1、flex和blend有点像。但flex(后来叫flash builder)貌似某个版本号以后就不提供图形编辑器了。而且通过网上大家的讨论得出,flex性能特别差,差点儿无法在手机上执行。果断弃坑。

2、flash cs能够制作游戏UI,但给我的感觉是提供的功能特别基础。也不甚符合程序猿的逻辑思维。

3、另一些其它的第三方或者个人提供的UI库、编辑工具。如flexlite等——不敢用,怕有大坑。并且翻了一下代码更新日志,也是好久都没动过了——更加怕。

4、starling貌似是大家比較推崇的flash移动端解决方式。大概看了一下,从原理上来说肯定是性能比传统的flash要好得多。

通过一番调研。决定用starling试试。

非常自然的,游戏须要比較好的扩展性的话,我们须要一个好的代码框架,找了一圈找到starling MVC。

大概看了一下功能介绍,感觉和j2ee的spring MVC有一点像。

starling MVC是一个IOC框架,提供下面特性:

  • 依赖注入(DI)/控制反转(IOC)
  • 视图仲裁(View Mediation)
  • 事件处理
  • 不影响原生的Starling游戏代码
  • 简易配置
  • 易扩展
  • 提供一些有用工具

我翻译了一部分它的介绍,有兴趣的同学能够看我的github上的starling MVC的一个branch:(https://github.com/chenggong-china/starlingMVC)

我到网上翻了一些关于starling MVC编写的游戏例程,怎么说呢。我感觉是没一个靠谱的。

大部分人都是浅尝辄止。并且都是生搬硬套。想把游戏逻辑拼命的塞到starling MVC中,而不是真正的用它来做代码的整理、规划,没有理解MVC、IOC、DI等思想,于是我索性自己開始琢磨。

我整理的starling MVC的调用逻辑关系例如以下:

1、启动时初始化各个bean(包含model、mediator、controller、view我觉得都应该实例化为bean)

2、starling MVC提供方法将bean依赖注入([Inject]等标签)

3、MVC的连接方式为:

  • controller中注冊EventHandler。接收消息。然后直接调用ViewManager的addView/removeView方法。来改动元素。
  • 调用了addView/removeView实际上会被相关的Mediator拦截到,在Mediator中编写界面展示的逻辑。

    (调用view的改动方法,调用Model的逻辑)

  • Model中提供业务逻辑方法
  • View中定义界面元素
实际上是把传统的MVC中的“C”分成了两个部分:controller和mediator。controller负责消息接收和路由、mediator负责衔接M和C


开发过程中逻辑还是比較顺畅的,只是后来我一直没去搞清楚比方要实现场景切换的过渡特效。在starling MVC中怎么实现……由于每次都是直接addView、removeView,木有一个中间状态啊。只是还没等我去研究,我就弃坑了……呵呵呵呵呵呵……

另外提一下starling feathers这个东东。

starling没有可视化的UI开发工具(拖界面的工具),那么意味着你须要手动在代码里去写x、y坐标,写width、height等属性(我了个擦,坑爹啊!

)——当然。假设你说你能够自己开发一个可视化的工具,那么,我仅仅能说:祝你好运……


OK。那么我先硬着头皮写一下用代码来布局的UI吧……

			var stateBackground : ImageLoader = new ImageLoader();
stateBackground.source = assets.getTexture("nick");
stateBackground.x = 0;
stateBackground.y = -12;
stateBackground.width = 200;
stateBackground.height = 70;
stateCanvas.addChild(stateBackground); _nickLabel = ComponentFactory.getSmallFontLabel("初出茅庐", 0xEF5E00, true, 20);
_nickLabel.x = 62;
_nickLabel.y = -4;
stateCanvas.addChild(_nickLabel); _gameModeLabel = ComponentFactory.getSmallFontLabel("难度:普通", 0xFFFFFF, true, 12);
_gameModeLabel.x = 61;
_gameModeLabel.y = 24;
stateCanvas.addChild(_gameModeLabel); _zhujueHead = new ImageLoader();
_zhujueHead.x = 4;
_zhujueHead.y = -4;
_zhujueHead.width = 40;
_zhujueHead.height = 49;
_zhujueHead.source = assets.getTexture("zhujue");
stateCanvas.addChild(_zhujueHead); _descCanvas = new Sprite();
_descCanvas.x = 100;
_descCanvas.y = 100;
_descCanvas.visible = false;
this.addChild(_descCanvas); //提示框
var descBackground : Scale9Image = ComponentFactory.getScale9Image("info", new Rectangle(7,9,360,87));
descBackground.x = 0;
descBackground.y = 0;
descBackground.width = 377;
descBackground.height = 103;
descBackground.alpha = 0.8;
_descCanvas.addChild(descBackground); _descImage = new ImageLoader();
_descImage.x = 14;
_descImage.y = 14;
_descImage.width = 80;
_descImage.height = 80;
_descImage.maintainAspectRatio = false;
_descCanvas.addChild(_descImage); _descLocationLabel = ComponentFactory.getSmallFontLabel("", 0xffffff, true, 18);
_descLocationLabel.x = 104;
_descLocationLabel.y = 6;
_descLocationLabel.filter = BlurFilter.createDropShadow(4,0.7,0x000000,0.8,0.5,1);
_descCanvas.addChild(_descLocationLabel); _descInfoLabel = ComponentFactory.getSmallFontLabel("", 0xffffff, false, 12);
_descInfoLabel.x = 104;
_descInfoLabel.y = 40;
_descInfoLabel.width = 250;
_descInfoLabel.height = 56;
_descInfoLabel.filter = BlurFilter.createDropShadow(2,0.7,0x000000,0.8,0.5,1);
_descCanvas.addChild(_descInfoLabel);

上面这一段截取于我刚開始写的一个布局view,实在是蛋疼至极有木有!

。!

于是楼主愤慨的自己写了一个布局基类,能够实现成以下这种写法了……

this.initComponents([
{type:Scale9Image, source:"UI-kuang", rect:new Rectangle(15,40,315,328), width:500, height:585},
{type:RoleUI, id:"roleUI", x:80, id:"roleUI"},
{type:Label, text:"当前队伍", color:0xffffff, fontSize:14, width:110, x:25, y:73},
{type:ScrollContainer, width:80, height:435, x:25, y:108, id:"teamlist" },
{type:ImageLoader, source:"back", width:20, height:20, x:470, y:5, id:"close"},
]);

自己感觉好多了……但还是非常蛋疼有木有


这里奉上基类BaseUI,有兴趣拿走~

package cn.hanjiasongshu.jygame.views.components
{
import com.creativebottle.starlingmvc.views.ViewManager; import flash.geom.Rectangle;
import flash.utils.Dictionary; import cn.hanjiasongshu.jygame.core.assets.Assets;
import cn.hanjiasongshu.jygame.views.factorys.ComponentFactory; import feathers.controls.ImageLoader;
import feathers.controls.Label;
import feathers.controls.ScrollContainer;
import feathers.core.FeathersControl;
import feathers.display.Scale9Image;
import feathers.textures.Scale9Textures;
import feathers.dragDrop.DragDropManager; import starling.display.Sprite;
import starling.textures.Texture; /**
* UI基类
* @author cg
*
*/
public class BaseUI extends FeathersControl
{
private static const ANONYMOUS_PREFIX:String = "__"; public function BaseUI()
{
_components = new Dictionary();
_autoId = 0;
} public function get assets():Assets
{
return Assets.instance;
} /**
* 初始化组件
* @param componentsArray
*
*/
protected function initComponents(componentsArray:Object):void
{
this.addComponents(componentsArray, this);
} /**
* 为一个组件加入孩子
* @param componentsArray
* @param parent
*
*/
private function addComponents(componentsArray:Object, parent:Sprite):void
{
for each(var c:Object in componentsArray)
{
if(c.type == null)
{
trace("[error]undefined component type:" + c);
continue;
}
var type:String = c.type;
var id:String = "";
if(c.id != null)
{
id = c.id;
}
else
{
id = String(ANONYMOUS_PREFIX + _autoId + ":" + String(c.type));
_autoId++;
}
var component:Sprite = null;
switch(c.type)
{
case Label:
var text:String = c.text==null?"":c.text;
var color:int = c.color==null?0:c.color;
var bold:Boolean = c.bold==null?true:c.bold;
var fontSize:int = c.fontSize==null?11:c.fontSize; if(c.align != null && c.align == "center")
{
component = ComponentFactory.getCenterAlignedFontLabel(text,color,bold,fontSize);
}
else
{
component = ComponentFactory.getSmallFontLabel(text,color,bold,fontSize);
}
break;
case ImageLoader:
var tmp:ImageLoader = new ImageLoader();
tmp.maintainAspectRatio = false;
var source:String = c.source==null?"":c.source;
tmp.source = c.source==null? "":assets.getTexture(source);
component = tmp;
break;
case Scale9Image:
component = ComponentFactory.getScale9Image(c.source, c.rect);
break;
case ScrollContainer:
component = ComponentFactory.generateVerticalScrollContainer(c.layout, c.backgroundSkin);
break;
case ToolTipUI:
component = new ToolTipUI(parent);
break;
default:
var clz:Class = c.type;
var instance:Object = new clz();
if(instance is Sprite)
{
component = instance as Sprite;
}
else
{
trace("[error]invalid component type:" + c.type);
}
break;
}
if(component != null)
{
this.setIfExist(c, component, ["x","y","width","height","visible"]);
_components[id] = component;
parent.addChild(component);
if(c.children != null) //遍历孩子组件
{
this.addComponents(c.children, component);
}
}
}
} /**
* 通过ID获取组件
* @param id
* @return
*
*/
public function getComponentById(id:String):Sprite
{
if(_components[id] == null)
{
trace("[error]get undefined component id:"+id);
return null;
}
return _components[id];
} public function getLabel(id:String):Label
{
return this.getComponentById(id) as Label;
} public function getImageLoader(id:String):ImageLoader
{
return this.getComponentById(id) as ImageLoader;
} private function setIfExist(dataSource:Object, obj:Sprite, params:Array):void
{
for each(var p:String in params)
{
if(dataSource[p]!=null)
obj[p]=dataSource[p];
}
} private var _components:Dictionary;
private var _autoId:int;
public override function dispose():void
{
for each(var key:String in _components)
{
var sprite:Sprite = _components[key] as Sprite;
sprite.removeFromParent(true);
}
_components = null;
}
}
}

你能够改动addComponent函数来自己加入控件类型。支持控件的组合等等。



啰啰嗦嗦说了这么多,发几个终于做出来的效果的图吧……还是非常丑……

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcmNmYWxjb24=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">






算是写了一些代码。但越做越不正确头,由于UI这东西还真不是写写控件布局就能做好的。没有一个非常好的可视化的编辑工具,我也越来越力不从心。
之后出于多方考虑,还是弃坑投入了unity3d的怀抱。

最后总结一下吧:

1、用starling这一系列东西开发的过程中到是没遇到太多框架性的BUG。已有的特性和功能都能够用。
2、starling等提供的功能还是比較原始,我认为用来开发小游戏可能还不错,规模略微大一点,就须要好好考量了。
3、PC上性能还OK,但最后貌似我也没上手机真机调试,这个我没有发言权。
4、as3还是比較灵活。写代码也有挺爽快的感觉,给我留下的印象仅次于c#。假设以后有机会开发flash游戏,我还是挺乐观的。
5、Adobe对于这块的投入貌似非常萎缩。flash开发人员们以及社区都不够繁荣。
6、开发手机游戏的话。还是用专业的引擎吧。


关于对FLASH开发,starling、starling feathers、starling MVC框架的理解的更多相关文章

  1. 【转】Flash:同志们,这些知识点你们知道多少?(一些必备的Flash开发知识点)

    1.理解flash的显示列表                2.理解事件冒泡,理解鼠标事件等        3.理解flash的性能瓶颈和大多数影响性能的地方4.理解帧跑道模型,知道timer和ent ...

  2. Flash 开发环境搭建和文字滚动效果实例

    Flash 开发环境搭建和文字滚动效果实例 一.Flash 开发环境搭建 Flash发布的时候可以将资源(即将库中的元件)集成到swf运行文件中.Flash没有代码自动输入补全功能,因此需要一个英文一 ...

  3. 关于NAND flash的MTD分区与uboot中分区的理解

    关于NAND flash的MTD分区与uboot中分区的理解 转自:http://blog.csdn.net/yjp19871013/article/details/6933455?=40085044 ...

  4. 分享一实战性开源MVC框架<Linux、Windows跨平台开发so easy>

    一.引子   开源地址 https://github.com/564064202/Moon.Mvc 欢迎加入开发 .NET Core微软还在发力,但作为商用还有一段距离,很多开发库尚不能用于.NET ...

  5. 全端开发必备!10个最好的 Node.js MVC 框架

      Node.js 是最流行的 JavaScript 服务端平台,它允许建立可扩展的 Web 应用程序.Node.js 包含不同类型的框架,如 MVC 框架.全栈框架.REST API  以及大量的服 ...

  6. 【原创】三分钟教你学会MVC框架——基于java web开发(2)

    没想到我的上一篇博客有这么多人看,还有几位看完之后给我留言加油,不胜感激,备受鼓励,啥都别说了,继续系列文章之第二篇.(如果没看过我第一篇博客的朋友,可以到我的主页上先浏览完再看这篇文章,以免上下文对 ...

  7. iOS开发网络篇—简单介绍ASI框架的使用

    iOS开发网络篇—简单介绍ASI框架的使用 说明:本文主要介绍网络编程中常用框架ASI的简单使用. 一.ASI简单介绍 ASI:全称是ASIHTTPRequest,外号“HTTP终结者”,功能十分强大 ...

  8. [课程设计]Scrum 1.3 多鱼点餐系统开发进度(系统主界面框架&美化)

    Scrum 1.3 多鱼点餐系统开发进度(系统主界面框架&美化) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选题:餐厅 ...

  9. [课程设计]Scrum 1.4 多鱼点餐系统开发进度(点餐页面框架布置)

    Scrum 1.4 多鱼点餐系统开发进度 (点餐页面框架布置) 1.团队名称:重案组 2.团队目标:长期经营,积累客户充分准备,伺机而行 3.团队口号:矢志不渝,追求完美 4.团队选题:餐厅到店点餐系 ...

随机推荐

  1. CNN完成mnist数据集手写数字识别

    # coding: utf-8 import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data d ...

  2. sed替换字符串中的某些字符

    test.txt原文内容 http://jsldfjaslfjsldfjasl/test?jlsdfjsalfjslfd 使用sed替换 sed -ri 's/(http:\/\/)[^\/]*(\/ ...

  3. C字符串指针遇到的问题

    看下面的示例代码: int main() { char *ptr = "GeeksQuiz"; printf("%c\n", *&*&*ptr) ...

  4. phpStrom+xdebug调试php

    1>xdebug下载 1.1>xdebug官网可以根据phpinfo()源代码来提供对应版本的xdebug,地址:https://xdebug.org/wizard.php 如下截图 1. ...

  5. phpstorm的全局操作快捷键ctrl+shift+f被搜狗占用处理方法

    1.找到搜狗软件,右键选择属性设置 2.如图选择系统功能快捷键 3.去掉简繁切换快捷方式,确定后即可使用phpstorm的ctrl+shift+f来进行全局查找

  6. 【JDBC】java连接MySQL数据库步骤

    java连接数据库步骤 1. 加载驱动 Class.forName("com.mysql.java.Driver"); 或: registerDriver(new com.mysq ...

  7. JavaScript中函数的定义

    JavaScript中函数的定义 制作人:全心全意 在JavaScript中,函数是由关键字function.函数名加一组参数以及置于大括号中需要执行的一段代码定义的.定义函数的基本语法格式如下: f ...

  8. 使用window.open打开新窗口被浏览器拦截的解决方案

    问题描述: 代码中直接使用window.open('//www.baidu.com', '_blank');会被浏览器窗口拦截 原因浏览器为了维护用户安全和体验,在JS中直接使用window.open ...

  9. Windows使用Nginx+ffmpeg搭建RTMP服务器

    简介Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器.nginx-rmtp-module是Nginx服务器的流媒体插件.nginx通过rtmp模块提供r ...

  10. Spring拓展接口之BeanPostProcessor,我们来看看它的底层实现

    前言 开心一刻 小明:“妈,我被公司开除了”,妈:“啊,为什么呀?”, 小明:“我骂董事长是笨蛋,公司召开高层会议还要起诉我”,妈:“告你诽谤是吧?”,小明:“不是,他们说要告我泄露公司机密” Bea ...