博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
关于对FLASH开发,starling、starling feathers、starling MVC框架的理解
阅读量:6831 次
发布时间:2019-06-26

本文共 8728 字,大约阅读时间需要 29 分钟。

说在前头:楼主之前没有不论什么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:( )

我到网上翻了一些关于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函数来自己加入控件类型。支持控件的组合等等。
啰啰嗦嗦说了这么多,发几个终于做出来的效果的图吧……还是非常丑……
算是写了一些代码。但越做越不正确头,由于UI这东西还真不是写写控件布局就能做好的。没有一个非常好的可视化的编辑工具,我也越来越力不从心。
之后出于多方考虑,还是弃坑投入了unity3d的怀抱。
最后总结一下吧:
1、用starling这一系列东西开发的过程中到是没遇到太多框架性的BUG。已有的特性和功能都能够用。
2、starling等提供的功能还是比較原始,我认为用来开发小游戏可能还不错,规模略微大一点,就须要好好考量了。
3、PC上性能还OK,但最后貌似我也没上手机真机调试,这个我没有发言权。
4、as3还是比較灵活。写代码也有挺爽快的感觉,给我留下的印象仅次于c#。假设以后有机会开发flash游戏,我还是挺乐观的。
5、Adobe对于这块的投入貌似非常萎缩。flash开发人员们以及社区都不够繁荣。
6、开发手机游戏的话。还是用专业的引擎吧。

你可能感兴趣的文章
Nginx和PHP-FPM的启动、重启、停止脚本分享(转)
查看>>
如何拷贝CMD命令行文本到粘贴板
查看>>
Oracle数据库—— 存储过程与函数的创建
查看>>
兼容iOS 10 资料整理笔记
查看>>
逻辑回归原理小结
查看>>
php 7.0 安装以及老版本php删除
查看>>
【Machine Learning】决策树案例:基于python的商品购买能力预测系统
查看>>
servlet生成验证码
查看>>
oracle存储过程中使用execute immediate执行sql报ora-01031权限不足的问题
查看>>
Zing 5.0发布,包含原生支持Linux的无停顿垃圾回收器
查看>>
解决Fiddler不能监听Java HttpURLConnection请求的方法
查看>>
串的模式匹配算法---Horspool
查看>>
Python基础07 函数
查看>>
Android学习
查看>>
Windows Phone 7 EKB系列文章发布
查看>>
Jmeter(六)-关联设置
查看>>
Mvc 3 中的分部视图
查看>>
android学习笔记之ProgressDialog的使用
查看>>
hdu 4557 非诚勿扰 vector的应用 原来vector 可以删除指定位置元素 不过消耗大
查看>>
tomcat支持中文文件名下载
查看>>