加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

关于对FLASH开发,starling、starling feathers、starling MVC框

发布时间:2020-12-15 17:30:00 所属栏目:百科 来源:网络整理
导读:说在前头:楼主之前没有任何flash开发经验,只是从一次尝试中总结自己的理解和经验而已。如果有写的不对的地方,欢迎大家指正。 前一段时间尝试想用flash(as3)重新制作一下之前做的一个游戏,作为从来没有接触过flash开发的我来说,花了一些时间研究现有的一

说在前头:楼主之前没有任何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,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,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("",false,12);
			_descInfoLabel.x = 104;
			_descInfoLabel.y = 40;
			_descInfoLabel.width = 250;
			_descInfoLabel.height = 56;
			_descInfoLabel.filter = BlurFilter.createDropShadow(2,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,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,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、开发手机游戏的话,还是用专业的引擎吧。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读