网页浏览器安装FlashPlayer(调试版)插件

我又来唠叨debug版本的重要性… 非debug版本Flash插件的话, 程序出错是不报任务错误信息的, 你甚至感觉不到游戏出错了. 这对于开发人员来讲即使发现bug了, 我们也束手无策.
您可以这么想: 如果不装debug版本FlashPlayer插件的话, 就叫Flash程序员去死好了.

浏览器的选择
不推荐使用搜狗浏览器, 因为它(在”高速模式”下)无法设置FlashPlayer版本.

下载并安装插件
你可以到Adobe官网下载安装,Plugin content debugger (非IE浏览器)    ActiveX control content debugger (IE内核浏览器), 建议都装上.
内网的话也可以直接到\\192.168.25.20\软件\FlashPlayer11\browsers下载安装.

安装成功了?
如何确定你现在使用的是debug版本的FlashPlayer插件呢?很简单: 请在Flash上单击右键, 如果右键菜单里看到了:”显示重绘区域”和”调试器”这两项. 那么恭喜你!你做到了.
QQ截图20121106161541.jpg
如果没有这两个菜单项, 那么你使用的仍然是非debug版本的FlashPlayer插件(我们称为release版本). “怎么会这样呢? 我明明装了呀!” 请往下看.

安装失败了?
如果你把插件装上了, 但是发现你的浏览器使用的仍然不是debug版本的FlashPlayer插件, 那么极有可能是因为浏览器使用的是它自带的FlashPlayer插件, 这种情况下我们要做的是:设置浏览器, 让它使用我们安装的debug版本FlashPlayer插件.

  • 搜狗浏览器
    菜单-工具-搜狗调整浏览器选项-页面设置-使用系统公用的Flash Player, 注意这个方法只对”兼容模式”有效.
    “高速模式”下如何设置FlashPlayer插件, 目前不清楚.
  • 谷歌浏览器(Google Chrome)或者360浏览器
    • 在地址栏输入chrome://plugins
    • 点击”详细信息”以展开插件列表
    • 停用所有类型是”PPAPI(进程外插件)“, 只保留NPAPI类型的.
      QQ截图20121106161401.jpg

用TweenLite制作窗口拖动特效(1)

本教程讲解窗口(图片)拖动特效的制作.
主要是利用drawTriangles绘制变形位图,用TweenLite实现移动过程的缓动.

先看下最终的效果(鼠标点击拖动面板):
[kml_flashembed publishmethod="static" fversion="10.0.0" movie="http://www.itamt.com/wp-content/uploads/2011/10/Step4.swf" width="550" height="400" targetclass="flashmovie"]
Get Adobe Flash player
[/kml_flashembed]

大体的思路是:把图片矩形分段,把矩形的运动分解为各个顶点的运动,结合各个顶点利用drawTriangles绘制变形位图,最后用TweenLite加入缓动效果.
null
接下来逐步讲解:

1.图片矩形的分段

如果图片位置是pos,要分的段数是segments,取得分段后的顶点,我们通过buildSegments方法来实现.具体如下:

		/**
		 * 对面板分段, 返回顶点(Point)的二维数组
		 */
		private function buildSegments(pos : Point) : Array
		{
			var pts : Array = new Array();

			// 分段后平均每段的宽/高
			var unitW : Number = this.panel.width / segments;
			var unitH : Number = this.panel.height / segments;

			// 遍历, 把分段后的顶点存放在pts数组(二维)中.
			for (var col : int = 0; col < segments + 1; col++)
			{
				pts[col] = new Array();
				for (var row : int = 0; row < segments + 1; row++)
				{
					pts[col][row] = new Point(pos.x + col * unitW, pos.y + row * unitH);
				}
			}

			return pts;
		}

通过buildSegments方法,取得分段后的顶点,并以二维数组([列,行])的形式保存下来.

2.drawTriangles绘制图片

drawTriangles是FP 10后Graphics增加的方法.可用来绘制三角形,并进行贴图.它提供三个参数

  • vertices(Vector.<Point>),三角形的顶点,顶点的数据形式不是Point而是x,y的数值(所以长度必定是6的倍数).
  • indices(Vector.<int>),三角形的边,根据顶点在数组中的索引,两个索引表示一条边.
  • uvData(Vector.<Number>),三角形顶点对应的贴图比例.

把面板分段后,循环绘制出每一个网格矩形.每一个矩形有四个顶点(tl,tr,br,bl),切分成两个三角形来绘制:
null
绘制(render)方法具体如下:

		/**
		 * 绘制面板
		 */
		public function render() : void
		{
			var g : Graphics = this.graphics;
			g.clear();
			var tl : Point, tr : Point, bl : Point, br : Point;
			// 使用drawTriangles绘制分段矩形
			var vertices : Vector. = new Vector.();
			var indices : Vector. = new Vector.();
			var indiceIndex : int;
			var uvData : Vector. = new Vector.();
			var seg : Number = segments;
			for (var col : int = 0; col < segments; col++)
			{
				for (var row : int = 0; row < segments; row++)
				{
					// 单个矩形的四个顶点
					tl = pts[col][row];
					tr = pts[col + 1][row];
					br = pts[col + 1][row + 1];
					bl = pts[col][row + 1];

					vertices.push(tl.x, tl.y, tr.x, tr.y, br.x, br.y, bl.x, bl.y);

					var nextU : Number = (col != segments - 1) ? (col + 1) / seg : (1 + 1 / this.panel.width);
					var nextV : Number = (row != segments - 1) ? (row + 1) / seg : (1 + 1 / this.panel.height);
					uvData.push(col / seg, row / seg, nextU, row / seg, nextU, nextV, col / seg, nextV);

					indices.push(indiceIndex, indiceIndex + 1, indiceIndex + 3, indiceIndex + 1, indiceIndex + 2, indiceIndex + 3);
					indiceIndex += 4;
				}
			}
			g.beginBitmapFill(new IMAGE().bitmapData);
			g.drawTriangles(vertices, indices, uvData);
			g.endFill();
		}

这里有个问题,我在实际书写drawTriangles的uvData并测试最终效果时,发现右边缘与下边缘都是少一个像素的.所以在遍历到边缘(col == segments – 1 || row == segments – 1)时, 把这一个像素转成百分比(1/panel.width, 1/panel.height)加到uv中.

3.实现鼠标拖动

鼠标拖动的实现主要是侦听处理鼠标的三个事件:MOUSE_DOWN,MOUSE_UP,MOUSE_MOVE

		/**
		 * 侦听鼠标交互
		 */
		private function buildInteractor() : void
		{
			this.stage.addEventListener(MouseEvent.MOUSE_DOWN, mouseEventHandler);
			this.stage.addEventListener(MouseEvent.MOUSE_UP, mouseEventHandler);
		}

		/**
		 * 处理鼠标事件,实现拖动
		 */
		private function mouseEventHandler(event : MouseEvent) : void
		{
			switch(event.type)
			{
				case MouseEvent.MOUSE_DOWN:
					this.mouseOffset = new Point(this.mouseX - this.posPt.x, this.mouseY - this.posPt.y);
					// 开始拖动
					this.stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseEventHandler);
					break;
				case MouseEvent.MOUSE_UP:
					// 结束拖动
					this.stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseEventHandler);
					break;
				case MouseEvent.MOUSE_MOVE:
					this.move(this.mouseX - this.mouseOffset.x, this.mouseY - this.mouseOffset.y);
					break;
				default:
			}
		}

在鼠标移动时,调用move方法传递目标位置,移动面板.看下一步.

4.移动面板,实现缓动

面板移动时,我们先把各个顶点的目标位置通过buildSegments计算出来,然后遍历对每个顶点添加缓动.每个顶点的移动时间需要不一样(如果一样的话,最终效果还是整个面板在平移),这里顶点的移动时间根据它与鼠标的距离来计算得出.

		/**
		 * 实现移动动过程缓动
		 */
		private function move(tx : Number, ty : Number) : void
		{
			this.endPt = new Point(tx, ty);

			// 计算各个分段顶点的目标位置
			var endPts : Array = this.buildSegments(this.endPt);

			// 创建缓动引擎
			this.engine = new TimelineLite({onUpdate:this.render, onComplete:this.onMoveComplete});

			// 遍历, 把分段后的顶点存放在pts数组(二维)中.
			for (var col : int = 0; col < segments + 1; col++)
			{
				for (var row : int = 0; row < segments + 1; row++)
				{
					var end : Point = endPts[col][row];
					var time : Number = Math.sqrt((end.x - mouseX) * (end.x - mouseX) + (end.y - mouseY) * (end.y - mouseY)) / 400;
					this.engine.insert(new TweenLite(this.pts[col][row], time, {x:end.x, y:end.y}));
				}
			}

			// 播放缓动
			this.engine.play();
		}

注意代码在TimelineLite.onUpdate时执行render重新绘制面板.

源码下载

源码打包,包里不含有TweenLite库.

后续

好了,初步完成,还有很多优化的空间,下回继续.

FlashFirebug 3.0

FlashFirebug 3.0已经推出!
新版本重写显示对象树面板,整合了FlashInspector,也修复了大量的bug。
除此之外,FlashFirebug 3.0增加了专业版,专业版多出的功能是控制台(Console),通过控制台你可以运行AS3代码。我想对绝大多数用户来说非专业版的功能已经够用了。
更多信息请访问:http://www.o-minds.com/products/flashfirebug

HtmlText及打字效果

HtmlText目的是方便对TextField.htmlText字符串进行分割,如下图:

可以直接利用TextField.text来的字符索引来定位分割,但返回的字符串仍保留html的所有标签。使用方法如下:

var html:HtmlText = new HtmlText('Hello &lt;b&gt;world&lt;/b&gt;!');
//输出&lt;b&gt;world&lt;/b&gt;,而不是&lt;b&gt;wo
trace(html.slice(5, 10));

一个简单的应用:HtmlText实现支持html的打字效果:

[kml_flashembed publishmethod="static" fversion="10.0.0" movie="http://www.itamt.com/wp-content/uploads/2011/06/Demo.swf" width="590" height="242" targetclass="flashmovie"]Get Adobe Flash player

[/kml_flashembed]
源码下载:
HtmlText.zip

计算网格中直线经过的格子

关于在位图上像绘制直线的算法,可以参见:http://free.pages.at/easyfilter/bresenham.html。但是不同于在位图上绘制直线,需要的是:一条直线经过哪些格子。

  1. 假设有p0,p1两个点,位置如下图:
  2. 我们很容易得到连线的方程。首先我们按照在x上取整递增,很容易计算出x=1, 2, 3, 4…时y的值是多少。
  3. 然后对y值取整,所得到(x1,y1),(x2,y2),(x3,y3)…肯定是连线过的格子。
  4. 但是我们遗漏了这种情况,左上格也是连线经过的格子,但由于我们只在x轴上进行取整递增运算,没有被考虑在内。
  5. 在(2)时已经可以知道A点坐标,我们可以斜率来判断连线是否经过上面一格。如果“蓝色线的斜率小于p0-p1的斜率”,说明连线经过了上面一格。
  6. 利用这种方法,可以轻松计算出连线经过的所有格子。

AS3实现的demo:
[kml_flashembed publishmethod="static" fversion="10.0.0" movie="http://www.itamt.com/wp-content/uploads/2011/04/TestLineCrossPoints.swf" width="550" height="400" targetclass="flashmovie"]Get Adobe Flash player

[/kml_flashembed]

源码:

/**
* 返回网格中两个点,连线经过的格子。
* @see  http://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm
*/
public static function determineTouchedTiles(p0:Point, p1:Point):Vector.
{
var touched:Vector.=new Vector.();
var x0:Number=p0.x;
var y0:Number=p0.y;
var x1:Number=p1.x;
var y1:Number=p1.y;

var steep:Boolean=Math.abs(y1 - y0) &gt; Math.abs(x1 - x0);
if (steep)
{
x0=p0.y;
y0=p0.x;
x1=p1.y;
y1=p1.x;
}

if (x0 &gt; x1)
{
var x0_old:Number=x0;
var y0_old:Number=y0;
x0=x1;
x1=x0_old;
y0=y1;
y1=y0_old;
}

var ratio:Number=Math.abs((y1 - y0) / (x1 - x0));
var mirror:int=y1 &gt; y0 ? 1 : -1;

for (var col:int= Math.floor(x0); col &lt; Math.ceil(x1); col++)
{
var currY:Number=y0 + mirror * ratio * (col - x0);

//第一格不进行延边计算
var skip:Boolean = false;
if(col == Math.floor(x0)){
skip = (int(currY) != int(y0));
}

if(!skip){
if (!steep)
{
touched.push(new Point(col, Math.floor(currY)));
}
else
{
touched.push(new Point(Math.floor(currY), col));
}
}

//根据斜率计算是否有跨格。
if ((mirror &gt; 0 ? (Math.ceil(currY) - currY) : (currY - Math.floor(currY))) &lt; ratio)
{
var crossY:int = Math.floor(currY) + mirror;

//判断是否超出范围
if(crossY&gt;Math.max(int(y0), int(y1)) || crossY

//跨线格子
if (!steep)
{
touched.push(new Point(col, crossY));
}
else
{
touched.push(new Point(crossY, col));
}
}
}
 return touched;
}

FlashInspector、FlashFirebug与Flash Builder的概要分析工具冲突

FlashInspector与FlashFirebug(2.0)和Flash Builder的概要分析工具(Profiler)都会设置mm.cfg的PreloadSWF参数, 所以会产生冲突, 导致Flash Builer的Profiler失效. 如果遇到这种情况, 可以先禁用FlashInspector和FlashFirebug(2.0), 或者为Firefox建个新的Profile.

FlashInspector 0.2.3更新

Flash Inspector更新至0.2.3. 加入了我最期待的一个功能:与FlashFirebug整合. FlashFirebug是对Flash开发很有用的一个调试工具. 但是使用它必须在swf里面先导入FlashFirebug的一些类. 通过Flash Inspector就不必这么麻烦了.

Flash Inspector采用了插件机制, 对FlashFirebug的支持, 其实就是编写一个插件负责与FlashFirebug交互. 要使用这个插件需要Firefox安装:Firebug(对于使用Firefox的前端开发者这应该是必备了吧?), FlashFirebug, Flash Inspector.
安装之后, 在状态栏上右击Flash Inspector的图标, 勾选”FlashFirebug”. 刷新一下页面.

不过FlashFirebug本身是针对自主项目的, 要求swf必须是”allowScriptAccess”的. 所以网页的swf不满足这个条件就没办法使用Flash Inspector的这个功能. Flash Inspector会尝试10次连接Flash Firebug, 如果连接失败, 会在左上角的工具栏中显示一个tip.

这次更新也加了对Firefox 4的支持.

关于在FlashInspector主页找不到其它版本的问题

现在访问Flash Inspector的主页,只能看到FlashInspector 0.1.7版本。其它版本不是被删除了,而是因为被禁用而没有列出来。

下面是Flash Inspector的组件管理面板的截图,可以看到很基本上所有版本都被禁用了。

Mozilla(应该是在上周)修改了关于附加组件的策略,Flash Inspector所有未审核过的版本全部被禁用了。Flash Inspector 0.1.7是Mozilla唯一审核过的一个版本。坦白讲这挺挫伤对Flash Inspector开发的积极性,因为Flash Inspector被审核很难通过,而一个不为人知不为人用的东西,做了有虾米意义呢?

关于Firefox大量组件的审核,我非常理解Mozilla,想象得出来他们的工作量非常的大。
Flash Inspector很难通过审核的原因:Flash Inspector包含了三个的swf文件,提交新版本后,最快一周内,开始接受审核,审核人员可以很容易看到JS、文本文件的哪些代码修改、增减,但是只能看三个swf文件发生了改变,为了保证这些文件是安全的,我会收到一封邮件要求提供这三个swf文件的源代码,当然我立马就给发了过去,啥子时候能审核通过真是不知道。