我又来唠叨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

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

先看下最终的效果(鼠标点击拖动面板):

Get Adobe Flash player

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

1.图片矩形的分段

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

通过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)方法具体如下:

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

3.实现鼠标拖动

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

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

4.移动面板,实现缓动

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

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

源码下载

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

后续

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

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

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

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

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

Get Adobe Flash player


源码下载:
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:
Get Adobe Flash player

源码:


/**
* 返回网格中两个点,连线经过的格子。
* @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) > Math.abs(x1 - x0);
if (steep)
{
x0=p0.y;
y0=p0.x;
x1=p1.y;
y1=p1.x;
}

if (x0 > 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 > y0 ? 1 : -1;

for (var col:int= Math.floor(x0); col < 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 > 0 ? (Math.ceil(currY) - currY) : (currY - Math.floor(currY))) < ratio)
{
var crossY:int = Math.floor(currY) + mirror;

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

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

return touched;
}