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

关于在位图上像绘制直线的算法,可以参见: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;
}

翻页时钟组件(SenseFlipClock)


Get Adobe Flash player

下载SenseFlipClock

提供的是MXP的组件安装文件,下载:SenseFlipClock(mxp)

自定义时钟皮肤

  1. 新建一个MovieClip,然后先画一个矩形,这会作为时钟的背景;然后在背景矩形上面放一个文本框(动态文本),用来显示时间文本。
  2. MovieClip设置为链接导出,并取一个类名,比如:CustomClockSkin
  3. 设置SenseFlipClockskin参数为CustomClockSkin
  4. 测试影片,现在你应该看到翻页时钟使用的是自定义皮肤。

代码使用

除了组件参数面板中的那些参数,SenseFlipClock还提供以下属性、方法:

  • SenseFlipClock.value: 用于设置值
  • SenseFlipClock.flip(): 翻页,一般是和SenseFlipClock.value配合使用。
  • SenseFlipClock.update(): 立即更新渲染,不建议使用。

注意,如果你想手动调用flip来翻页,必须先把flipOn设置为custom。

最后

希望SenseFlipClock对您有用
: )

htc Sense翻页时钟效果(SenseFlipper)

效果如下:

Get Adobe Flash player

核心类是SenseFlipper, 用于对位图(BitmapData)进行翻页, 不是电子书那种翻页效果.使用方法上:只要调用SenseFlipper.next方法, 指定下一状态的位图即可.用到了SnapShoter对显示对象进行”拍照”(获取位图数据).

呃…打包的代码里面, SnapShoter没有提供翻页时间的API, 如果有需要, 直接修改SnapShoter中的maxTime即可(单位:帧).

源码下载:

SenseFlipperDemo.

跨域加载swf进行类型转化失败

在实现tInspector的插件机制时碰到的这个问题。要实现的插件机制大概是这样子:定义一个PluginManager,定义一个IPlugin接口,然后来各个Plugin都实现IPlugin。使用插件时就是:在PluginManager.swfplugin.swf加载到它的子域中(new ApplicationDomain(ApplicationDomain.currentDomain))。这个机制没什么问题。

问题出现在:在PluginManager中把(通过Loader)加载进来的Plugin swf进行类型转化为IPlugin结果总是失败,无法把加载进来的内容转化为IPlugin类型。
最后发现我是把PluginManager.swf保持在本地,而plugin.swf放置IIS服务器上的。当把PluginManager.swfplugin.swf放在一个目录下就正常了。

也就是说如果PluginManager.swfplugin.swf放置再不同的域底下就无法进行类型转化了。
这个问题的解决方法:使用URLLoader以数据的形式加载plugin.swf然后再用Loader.loadBytes加载为swf,加载完成后,类型转化就可以顺利进行。

也可以使用下面这篇参考文章里提供的类文件:
http://blog.aleksandarandreev.com/?p=42

组件安装后没有显示在Flash面板中

情形是这样的:在中文的系统上安装英文版的Flash CS5,那么用Adobe Extension Manager安装mxp后,Flash CS5中的组件面板没有显示出刚装的组件。
问题在于Adobe Extension Manager会把组件安装在系统语言(中文)的路径下,像这样:

Flash CS5读取的组件时安装自身语言版本的,像这样:

解决方法是,让Extension Manager把组件安装在Flash CS5语言的路径下,方法有两个:

  • 启动Extension Manager时指定语言,再安装组件:给Extension Manager的快捷方式中添加一个启动参数:
  • Flash CS5中启动Extension Manager,方法是Flash CS5菜单栏:Help – Manager Extension…,然后再安装组件。

相关文章:

窗口拖动特效

这几天正在制作的窗口特效组件,关于Genie特效的as3实现可以参考这个例子。实现方法是:tween + drawTriangles + 点。


Get Adobe Flash player

想来特效就是关于点的运动,针对点的计算。一个点从原始位置运动到目标位置,过程是怎么样的。把窗口从一个位置拖动另一个位置,就可以抽象成一个矩形从一个位置移动到另一个位置,再把一个矩形分解成四个点,还是点的运动。从原点到目标点的计算就是tweentween的核心各式各样的ease,这些公式才是最难的地方。开源的tween非常丰富,已经可以不必去碰那些头大的数学公式就做出看上去很酷的效果。数学是研究3D、物理引擎、粒子特效最该学习的了。