skip to main |skip to sidebar

2007-12-31

2007年,我 blog 的一年总结

谢谢大家对我 Blog 的关注。我的 Blog 自从 2007-3-24 开通以来,今年共写了 116 篇文章(包含本篇),总共4655人访问

访问内容排行榜

  1. 主页 —— 1121人访问
  2. Fedora 7(Linux)之旅 —— 150人访问
  3. Flex2 Tag for JSP —— 118人访问
  4. [AS3]位图的色阶控制(2) -- 伽玛校正(Gamma Correction) —— 101人访问
  5. Flash CS3 = Flash 8 + AS3.0 + CS3 UI ? —— 92人访问

文章内容排行榜

  1. ActionScript 类 —— 27篇
  2. AIR 类 —— 16篇
  3. flash 类 —— 11篇
  4. flex 类 —— 10篇

历史回顾

2007-12-29

MXNA最近很怪

最近,MXNA 上有很多垃圾信息。

今天中午去查看 Google Reader 时,发现从昨天晚上到今天中午,MXNA 的中文内容有102条。其中"自由鸟的BLOG"与"windflower"占了大多数。其中包含了大量的广告信息。

我一气之下把 MXNA 的中文内容退订了!

2007-12-26

[AI]高级人工智能(2)——结合队伍

[AI]高级人工智能(1)——回避障碍物

结合队伍就是诱导各个人到周围的人的平均位置。这是队伍一起行动的三大步骤之一。通过结合,各个人就会聚合到一起,出现队伍。

效果:

人刚开始是随机移动,但遇到其他的人时,就会跟随他。但碰到障碍物等时有可能无法跟上,而又开始随机移动。当一群(boids)遇到另外一群时有可能结合在一起,也有可能队员发生互换后分开。

得到周围的人

每一个人有一个视野距离与视野范围。比如某个机器人可以看到 100m ,眼睛的夹角在120度 以内的物体。其中"100m"为视野距离(以下称为 r),"120度"为视野范围(以下称为 th)。

核心代码:

//周围的人列表。
internal var aroundList:Array;

//可视列表。
internal var inViewList:Array; //创建可视列表。
public function resetViewList():void {
inViewList = [];
aroundList = [];
for each(var u:C2Unit in onwer.unitsList) {
if(!u.following && u != this) {
if(inAround(u)) {
aroundList.push(u);
if(inView(u)) {
inViewList.push(u);
}
}
}
}
} //判断是否在周围。
public function inAround(u:C2Unit):Boolean {
if(Vector2d.distance(pos, u.pos) > VIEW_DISTANCE) {//VIEW_DISTANCE 为 r
return false;
}
return true;
}

//判断是否在视野范围内。
public function inView(u:C2Unit):Boolean {
var dsu:Vector2d = new Vector2d().sub(u.pos, pos);//dsu = u - pos (pos为自己的坐标)
if(dsu.angle2(pos)>VIEW_WIDTH) {//VIEW_WIDTH 为 th/2
return false;
}
return true;
}

结合

实现结合,其实很简单,就是把速度(方向和长度)设为周围的人的平均速度即可。

核心代码:

//结合。
internal function follow():void {
if(inViewList.length) {
var avg:Vector2d = new Vector2d();
for each(var u:C2Unit in inViewList) {
avg.addTo(u.v);
}
avg.scaleTo(1/inViewList.length);
v.reset(avg);
following = true;
}else{
following = false;
}
}

完整源码下载:结合队伍.rar,或访问我的附件

2007-12-24

[AS3.0]使用":?"运算符来代替"if..else"的函数型编程

在函数型语言中,所有的语句都有返回值,当然 if..else 也不例外。这个功能在命令型语言中是没有的。

比如以下代码:

public function foo(a:int):int {
if(a<0) {
return -1
}else if(a==0) {
return 0
}else{
return 1
}
}

既难读也麻烦。如果使用 haskell(一种函数型语言) 来写的话:

foo a = if a<0 then -1 
else if a==0 then 0
else 1

十分简练。注意,AS3.0 有一个 :? 运算符,可以用它来实现,如果把格式写好的话,可读性会比 if..else 还要好。

public function foo(a:int):int {
return a<0 ? -1 :
a==0 ? 0 :
1;
}

if..else 相套时,可以这样写:

public function foo2(x:int, y:int):int {
return x>0 ? (
y>0 ? 1 :
y<0 ? 4 :
-1
): x<0 ? (
y>0 ? 2 :
y<0 ? 3 :
-1
):
-1;
}

2007-12-23

[AI]高级人工智能(1)——回避障碍物

效果:

在连续动作环境(不是Tile Based 环境)中,回避障碍物是很复杂。因为不像 Tile Based 环境,"点"在理论上有无限多,很难准确地判断。

但不是没有办法的,回避障碍物可以使用 Lenard-Jones potential 函数

它的方程为:

[U = -A/pow(r,n) + B/pow(r,m)]

n、m 为不同常量时的曲线为:

[Graph]

Lenard-Jones potential 函数是物理中的一个函数,他表示分子间的引力与斥力的势能。U 为原子间的势能,它与原子间的距离 r 成反比。AB 就像 mn 一样,是常量,其中 -A/pow(r,n) 表示引力部分,B/pow(r,m) 表示斥力部分。在 r 很小时会产生斥力,当 r 很大时会产生引力。参数 mn 控制曲线的斜率,AB 控制力的强度。

如果在游戏中,把障碍物与人物看成原子的话,就可以使用 Lenard-Jones potential 函数来实现回避障碍物。当十分接近时,会产生很大的斥力,再把 A 设为0,使引力始终为0这样回避障碍物就实现了。

核心代码:

var vo:Vector2d = new Vector2d();//障碍物的坐标
var vp:Vector2d = new Vector2d().reset(player);//人物的坐标
var r:Vector2d = new Vector2d();//人物与障碍物的差
var u:Vector2d = new Vector2d();
var dv:Vector2d = new Vector2d();
var B:Number = 20;//函数的 B 常量
for each(var i:Obstacle in obstaclesList) {
vo.reset(i);//vo = (i.x, i.y)
r.sub(vp, vo);//r = vp - vo
if(r.length >40) {//当 距离>40 时不判断,直接返回。
continue;
}
u.reset(r);//u = r
u.normalize();//把 u 设为单位向量
var d:Number = r.length/i.r;//d = |r| / i.r (i.r为障碍物的半径)
var U:Number = B/Math.pow(d,2.5);//A = 0,n = 1,m = 2.5
u.scaleTo(U);//u *= U
dv.add(player.v, u);//dv = player.v + u (player.v为人物的速度)
dv.length = 5//|dv| = 5
player.v.reset(dv);//player.v = dv
}

源码下载:AI_Avoid.rar

参考文献:AI for Game Developers

[AI for Game Developers]

2007-12-19

[AIR]Adobe AIR 1.0 Beta 3 的变更详情

执行环境

AIR 支持的 OS 有:

  • Windows Vista Home、Ultimate Edition, Windows XP SP2
  • Windows 2000 SP4 (不支持无缝安装)
  • Mac OS 10.5 Leopard 、 Mac OS 10.4.x Tiger (Intel 与 PowerPC)

AIR 1.0 Beta 1 的执行环境将会在 2007-12-15 开始无法使用。AIR 1.0 Beta 1 用的程序应该及时升级为 AIR 1.0 Beta 3。AIR 1.0 Beta 3 预定为发布正式版前的最后一个测试版,今后应该不会有较大的改变。还有,AIR 1.0 Beta 2 将会在 2008-6-1,AIR 1.0 Beta 3 将会在 2008-11-1 过期。在那以前,AIR 1.0 Beta 2 可以与 AIR 1.0 Beta 3 一起使用,但须先安装 AIR 1.0 Beta 2。

AIR 1.0 Beta 1 的卸载在 Windows 里可以使用"添加/删除",Mac 可以使用程序路径里的"AdobeAIR Unistaller"。注意,删除 AIR 1.0 Beta 3 时,以前的版本将会一起被卸载。

无缝安装的改变

无缝安装即为从浏览器里安装。安装 AIR 1.0 Beta 3 后,AIR 1.0 Beta 2 的无缝安装将会失效。要想继续使用无缝安装,需要使用 AIR 1.0 Beta 3 SDK 里的 AIR 1.0Badge.as 来设置。设置需要 Flash CS3,并且要执行 AIR 1.0 Beta 3 的无缝安装需要 Flash Player 9.0.115.0。

程序描述文件的改变

  • xmlns 变为 "http://ns.adobe.com/air/application/1.0.M6"
  • <title> 标签变为 <name> 标签。
  • <name> 标签变为 <filename> 标签。
  • <handleUpdates> 标签变为 <customUpdateUI> 标签。
  • appId 属性从 <application> 标签的属性变为 <id> 标签。
  • version 属性从 <application>标签的属性变为<version> 标签。
  • <application> 标签添加了 <allowBrowserInvocation> 子标签。
  • <fileType> 标签添加了 <icon> 子标签。

数据库的改变

SQL 的 BLOG 类型将会自动序列化为 ActionScript 3.0 的 ByteArray 类型。在以前的版本里,明确使用了 ByteArray 的需要做处理。

并且,ISQLUserDefinedFunctionSQLUserDefinedFunctionType 将不再支持,应该马上停止使用。

2007-12-16

郁闷!自己 ping 自己不通

实在是郁闷,今天我 ping 自己的 IP,却 ping 不通。

不知道怎么的,上网没事,ping 路由器也没事,ping localhost 还是没事,但 ping 192.168.x.x(自己的 IP)却弹出 "Request timed out."。我关掉了防火墙,但还是不行。使用 IPBook 可以查看到自己的 IP,但使用 Wireshark 进行抓包时,不管从哪一台机器来 ping,都没有任何相关的信息。

请为大家,这是为什么?该怎么解决?

[Flash Player]Flash Player 9.0.115.0 的安全策略的变化

前几天公开的 Flash Player 9.0.115.0 的安全策略发生了一些变化,有可能导致安装了新的 Player 后无法正确显示某些内容。

这次变更主要有以下3点:

安全策略文件的格式

如果安全策略文件的格式不是正确的 XML,将会被忽视。比如顶级标签必须为 <cross-domain-policy>

Adobe 已经公开了每个协议的安全策略文件的正确的格式,详细请查看以下的 xsd(XML Schema) 文件。

Flash Player 9.0.115.0 的 Debug 版添加了安全策略文件的历史记录功能,如果有问题可以查看历史记录。

在域名内的重定向

在请求安全策略文件时,如果发生了在域名内的重定向,Flash Player 9.0.115.0 将对重定向后的 URL 使用安全策略。

比如请求 http://example.com/foo/crossdomain.xml 时,如果重定向为 http://example.com/bar/crossdomain.xml,读入的安全策略文件将会对 http://example.com/bar/ 以下的 URL 生效。

这个信息也会写到历史文件里。

Content-type 的值

Flash Player 9.0.115.0 以后,读入的安全策略文件如果不包含以下任意的值的话,将会被忽视。

  • text/*
  • application/xml
  • application/xhtml+xml

这样多少可以保证安全策略文件为文字文件。

Socket的连接

从 Flash Player 9.0.115.0 开始,不管是否在同一个域名,ActionScript 连接Socket 时都必须使用安全策略文件。

但实际上 Flash Player 9.0.115.0 在大多数的情况下只是弹出警告,是可以连接的。但连接本地服务器等时必须按照新的规则来制定安全策略文件。

历史文件

首先需要安装新的 Debug 版的 Player。(下载:Flash Player Support Center

再编辑 mm.cfg 文件(在用户的根目录,如果没有,就创建一个),追加一下2句。

PolicyFileLog=1   # 启用安全策略文件的历史记录
PolicyFileLogAppend=1  # 是否为追加模式,默认为0即不(可要可不要)

启动 Flash Player 9.0.115.0 后将会在以下的地方做成叫 policyfiles.txt 的历史文件。

  • Windows --------- C:\Documents and Settings\username\Application Data\Macromedia\Flash Player\Logs
  • Windows Vista -- C:\Users\username\AppData\Roaming\Macromedia\Flash Player\Logs
  • Macintosh -------- /Users/username/Library/Preferences/Macromedia/Flash Player/Logs
  • Linux -------------- /home/username/.macromedia/Flash_Player/Logs

关于本次变更的详细情况可以参照Security changes in Flash Player 9(e文)

2007-12-15

Adobe BlazeDS 详情

BlazeDS 为 Adobe 的一个新的关于远程(Remoting)与网络信息系统(Web Messaging,类似于 JMS)的开源项目。BlazeDS 是以前的 LCDS ES 的一部分变为开源的。它是基于 LGPL v3 协议发布的。并且同时公开了 AMF(Action Message Format)的格式。

现在从 Adobe Labs 可以下载 BlazeDS 的 Beta 版(BlazeDS@Labs)。Adobe 将会把 BlazeDS 加进 LiveCycle Data Services, Community Edition 里。以前的 LCDS ES 还将继续贩卖。

BlazeDS的主要功能为:

远程(remoting)

它使用 Java 实现了 RPC(Remote procedure call)。并且不写逻辑也可以简单地转换数据格式,还可以利用2进制的 AMF 来减少通讯量,改善性能。

网络信息系统(Web Messaging)

它可以使 Flex 、Ajax 程序等向服务器发送信息,客服端也可以收到从服务器发出的信息,以实现双向通讯。

注意,BlazeDS 的网络信息系统是使用 Comet 方式的持久的 HTTP 连接来实现的。一个CPU大概可以同时处理100~200个连接(与一般的 servlet 差不多)。但 LCDS ES 提供了一个CPU可以处理数千个连接的功能,对于高负荷的环境需要使用 ES 版。RTMP 协议也只有 LCDS ES 支持。

2007-12-09

[AIR]AIR 1.0 = 危险?

今天看了 AIR Security Model(J文),发现 AIR 很危险,比如:

访问系统
AIR可以任意地访问系统。也就是说 AIR等于桌面程序。而 JavaApplet、Google Gear 却为 受限制的访问,这样必究安全。
AIR 1.0 没有提供的
 
AIR 1.0 没有提供安全运行不信任的程序的功能,防止开发者制作安全漏洞的功能,保障绝对安全的沙箱。
安全沙箱不安全
在 AIR 1.0 的两个沙箱(Application 与 Classic)之间有一个桥梁(SandboxBridge),如果被恶用,Classic 沙箱就可以拥有 Application沙箱的功能。(关于沙箱请看这里 [AIR]Adobe AIR Beta 2的安全方面的变化)

因此,AIR 1.0 有可能与桌面程序同样危险!但注意,这指的是 AIR 1.0,不是AIR 1.x。

2007-11-25

[JavaScript]奇迹!JavaScript居然可以使用Java的类!

今天,编程时无意发现JavaScript可以使用Java的类。但他虽然可以使用,但无法继承。这是从JavaScript 1.1开始支持的。

比如以下代码:

var str = new java.lang.String("Hello world.");//字符串
alert(str);
var sr = java.io.StringReader(str);
alert(sr.read());
var arr = str.getBytes();//数组
alert(arr[0]);
var vector = new java.util.Vector();
vector.add(1);
alert(vector.elementAt(0));

这个功能的支持如下:

  • IE7 - 不行
  • FF2 - 可以
  • Opera9 - 可以

因为安全性的问题,只可以使用部分类,比如java.lang.Thread就无法使用。也就是说无法开多线程。

2007-11-18

[AS3]高级图形处理(2)——老照片滤镜

照片的时间久了,就会出现褪色、模糊、杂色

实现方法

褪色
使用ColorTransform。参数为new ColorTransform(0.7, 0.7, 0.7, 0x44, 0x33, 0x22)
模糊
使用BlurFilter。参数为new BlurFilter(0.2, 0.2)
添加杂色
使用BitmapData.noise($randomSeed, 0xee, 0xff, 7, true)

核心代码

//Color Transform
outputBitmapData.colorTransform( sourceRect, new ColorTransform(0.7, 0.7, 0.7, 0x44, 0x33, 0x22) );
//Blur
outputBitmapData.applyFilter( outputBitmapData, sourceRect, destPoint, new BlurFilter(0.2, 0.2) );
//Noise
var noise:BitmapData = new BitmapData($width, $height, false);
noise.noise(0, 0xee, 0xff, 7, true);
outputBitmapData.draw(
noise,
new Matrix(1, 0, 0, 1, destPoint.x, destPoint.y),
null,
BlendMode.MULTIPLY
);

完整代码下载

2007-11-06

悲哀!谷歌的新版主页

网址:http://www.google.cn/hp?sp=china

实在是悲哀!Google到了中国怎么就变了味?难道这就是国情吗?

本地化并不一定表示要庸俗化吧,与其这样还不如坚持走高端路线。

中国的网络何时才能成熟?

昨天又遭遇了spam广告评论

实在是愤怒!

前几天,我的Blog的PR上升到了6以后,又有人发布广告评论。

发布广告评论的人注意了,当你发了评论时,我将会收到有评论的消息,也就是说你的评论的生命超不过一天!打验证码不累吗?我删除你的评论只需要1秒,你这样做值得吗?

2007-11-03

ECMAScript4 草案的新标准解读

概要

ECMAScript4的新标准可以分为

  • 从 ActionScript 3.0 继承的新标准
  • 从 JavaScript1.7 继承的新标准
  • 其他的新标准

从 ActionScript 3.0 继承的新标准

与OOP和类型相关的标准与ActionScript 3.0几乎一样。

  • class,interface
  • 属性,const
  • 继承
  • 命名空间,package
  • int,double类型
  • ...args
  • is,as运算符
  • try-catch的类型匹配
  • 末尾的逗号(Trailing commas),比如{a : 10,}

从 JavaScript1.7 继承的新标准

  • 作用域(let)
  • 多值代入([a, b] = [1, 2])
  • 迭代(Iterator)
  • yield
  • 数组闭包

FireFox 2使用的是 JavaScript 1.7。

其他的新标准

重载函数(generic functions)

使用Overload可能更恰当。

generic function intersect(s1, s2); // No body here

generic function intersect(s1: Shape, s2: Shape) {
    // general intersection method 
}

generic function intersect(s1: Rect, s2: Rect) {
    // fast intersection for rectangles 
}

模板类 (parameterized class)

类似于 Java 5.0 新添加的Generics。可以避免运行时的类型检查,提高运行速度。

class Pair.<T> {
var first: T, second: T;
}

new Pair.<int>(3, 4);
type Box.<T> = {
 value: T
}
var v: Box.<boolean> = new Box.<boolean>(true);

function f.<T>( x:T ): T {
    //Do sth...
}

f.<int>(37)

Vector与Map

Vector为Array的严密版;Map为使用Object的HashTable,相当于 ActionScript3.0 的 Dictionary类的严密版。它们都支持迭代与模板。并且在编译时做了类型检查,所以速度很快。

var xs = new Vector.<double>;
var map = new Map.<*,int>;

记录与数组类型(Record and array types)

记录类型(Record type)就像{x:int, y:string}的样子,好像受了Scheme等函数型语言的影响。Object的模板?

var samplevar = new { x:int, y:string }( 3, "foo" );
var samplevar = { x:10, y:"foo" } : { x:int, y:string }; 

但是属性可以进行添加与删除,也就是说并非制定严密的类型。如果想严密,必须定义Class!

就我看来,这种语法不大好,有点罗嗦。我认为以下似乎更好:

var samplevar = new {x:int = 3, y:String = "foo"};

数组类型使用[int]的方式来定义。

var intarray = new [int](7);
var intarray = [1, 2, 3]:[int];

以上两种类型均可以与新添加的关键字 likewarp 组合起来使用。

function func1( pt: like { x: int, y: int } ) {...}
function func2( pt: * ) {
     if( pt is like {x : int, y : int} ) { ... }
}
function func3( pt: wrap { x: int, y: int } ) {...}

有趣的是使用 like 可以匹配特定种类的class,而不必非要在继承树下面的。比如ActionScript3.0的 PointSprite 的超类虽然不一样(除 Object 以外),但都有xy属性。使用记录类型的话,就可以匹配以上两种类型,增加了柔软性。

每次都写 { x:int, y:int } 太麻烦了,多次使用时可以使用新的关键字 type 来定义。

type Position = { x:Number, y:Number };

其他,数组类型与变长参数可以一起使用。

function (int, ...[string]): void {...}

运算符的重载(Operator overloading)

运算符均为全局函数,在 intrinsic 的命名空间里面定义。

class Complex {...}
generic intrinsic function +( a: Complex, b: Complex ) {
     new Complex( a.real + b.real, a.imag + b.imag )
}
generic intrinsic function +( a: Complex, b: Number ) {
     a + Complex(b)
}
generic intrinsic function +( a: Number, b: Complex ) {
     Complex(a) + b;
}

禁止null值(Nullability)

在类型后面添加!来禁止null值的代入。

var v:C! = ...
function (v:Object!) {...}
class Complex! {...}

末尾调用(Tail calls)

在函数的末尾调用函数或返回调用函数的值时,不进行压栈、调用,而直接使用 goto 来编译。特别在递归调用时,调用过程变为了循环,对速度有显著的提高。

元层次挂钩(Meta-level hooks)

管理函数的调用,值的代入等,可以使用meta::invokemeta::getmeta::setmeta::hasmeta::delete。类似于 ActionScript 3.0 的 Proxy,只能在动态类里使用。

Array与Vector也使用了Meta-level hooks。在之前无法自己写Arra(因为无法同时继承 ArrayProxy),但通过使用Meta-level hooks,这一切将成为历史。

结合类型(Union type)

创建可以匹配多个类型的类型比如 (int,String) 可以匹配 intString 类型。

type AnyNumber = (byte,int,uint,double,decimal,Number);//匹配任何数字的类型

特别地,常量 any 等于 (null,undefined,Object),可以匹配任何类型。

选择类型(switch type)

以前,switch只匹配较值,需要匹配类型时只能使用 if(v is String){...}else if(v is Number) {...}... 但现在可以使用switch type。

switch type (v) {
    case (s:string) { ... }
    case (d:Date) { ... }
}

截取(Slicing)

截取子集,可以在 StringArrayVector 里使用。

"ecmascript"[5:2:-1]// => "sam"

正则表现(Regular Expressions)的多行与注释

正则表现支持多行与以#开头的注释。复杂的正则表现的阅读性大大提高!

/# The protocol is an alpha name followed by colon and double slash
 (?P<protocol> [a-z]+)
 :
 \/\/
 # The host is two or more dot-separated alpha names
 (?P<host> [a-z]+ (?: \. [a-z]+ )+)
 # The path is optionally present
 (?P<path> (?: \/ [a-z]+ )* \/? )
/x

支持JSON

toJSONStringString.parseJSON

还有很多新标准,详细请看 Proposed ECMAScript 4th Edition – Language Overview

Blog改版二期工程基本完毕!

本次改版,对SEO与用户体验做了改动。比如:

  • 以前在Google上搜索的结果的简略信息都是一样的,而现在可以搜索到真正的内容了。
  • 添加了相关链接,使用了Ajax技术以防止页面出现停顿(表示相关链接的网络开销有点大)
  • 把以前的标签改成了标签云。
  • 让从手机上也能正常阅读。

2007-10-28

[AS3]高级图形处理(1)——自定义颜色比率的噪音(Noise)

一般制作线性噪音(0~255之间呈线性分布的噪音)很简单。使用BitmapData.noise()即可。

但要求产生的噪音当中,红色占10%、绿色占10%、蓝色占80%该怎么办?没有现成的方法可以用。但这类噪声却很有用,比如游戏地图的随机生成、制作宇宙的繁星等。

其实很简单!可以使用BitmapData.pixelDissolve()BitmapData.pixelDissolve()是用来溶解像素,制造马赛克的过渡效果的。但它还可以制造噪音!

代码:

package advancedflex.display.images {
import flash.display.BitmapData;
import flash.geom.Point;
import flash.geom.Rectangle;

public class ImageRandom {

public static function customColorNoise(
src:BitmapData,
sourceRect:Rectangle,
colors:Array,
ratios:Array,
randomSeed:int = 0):int
{
if(colors.length != ratios.length) {
throw new ArgumentError("colors.length != ratios.length.")
}
if(!src) {
throw new ArgumentError("src is null.")
}
var length:int = colors.length;
var s:int = src.width * src.height;
for(var i:int = 0; i < length; i++) {
ratios[i] = s*ratios[i];
}
return customColorNoize2(src, sourceRect, colors, ratios, randomSeed);
}

public static function customColorNoize2(
src:BitmapData,
sourceRect:Rectangle,
colors:Array,
numPixels:Array,
randomSeed:int = 0):int
{
if(colors.length != numPixels.length) {
throw new ArgumentError("colors.length != numPixels.length.")
}
if(!src) {
throw new TypeError("Src must not be null.");
}
var length:int = colors.length;
var point:Point = new Point(sourceRect.x, sourceRect.y)
for(var i:int = 0; i < length; i++) {
randomSeed = src.pixelDissolve(src, sourceRect, point, randomSeed, numPixels[i], colors[i]);
}
return randomSeed;
}
}
}

2007-10-27

奇迹!我的Blog的GooglePR上升为6

简直不敢相信我的眼睛。

昨天,Google PR 还为2,今天居然为6!而且用多种方式查看了,都为6。

奇迹!

2007-10-21

[AS3]位图的色阶控制(2) -- 伽玛校正(Gamma Correction)

[AS3]位图的色阶控制(1) -- 得到色阶

位图调节色阶时,在内部使用的是曲线校正中的伽玛校正。

伽玛校正为调整亮度的方法,它只有一个参数即γ(Gamma)。伽玛校正的变换公式为:

X'=X_max*(x/X_max)^(1/γ)

x'为变换后的亮度。xmax为x的最大值。

γ = 1 x' = x (没有变化)
γ = 0.5 x' = x2(变暗)
γ = 2 x' = √x(变亮)

调整色阶的三个滑条的意思

Plotoshop的调整色阶里有黑,灰,白三个滑条,黑为阴影,白为高亮。从0到黑均为黑色;从白到255均为白色;从黑到白为以灰为中值的伽玛校正。(xb为黑,xg为灰,xw为白)

Actionscript 3.0的实现

实现曲线、伽玛校正等可以使用BitmapData.paletteMap。

三个滑条的值分别为xb、xg、xw (0≤xb≤xg≤xw≤255)。Xmax = xb - xw。当x = xg - xb时,因为想x' / xmax = 0.5,所以

g=( log(Xg-Xb / Xw-Xb) ) / (log(0.5)

var gamma:Number = Math.log((xg - xb) / (xw - xb)) / Math.log(0.5);
var mapR:Array = [], mapG:Array = [], mapB:Array = [];
for(var i:int = 0; i < 256; i++) {
 mapB[i] = i < xb ? 0 : i > xw ? 0xff : 255 * Math.pow((i - xb) / (xw - xb), 1 / gamma);
 mapG[i] = mapB[i] << 8;
 mapR[i] = mapB[i] << 16;
}
image.paletteMap(bmdOrigin, bmd.rect, new Point(), mapR, mapG, mapB);

完整的实现代码:


package bitmap {
 import flash.display.*;
 import flash.filters.*;
 import flash.geom.*;
 import flash.events.Event;

 [SWF(width="256", height="410")]
 public class Histogram3 extends Sprite {
  [Embed(source="023.jpg")]
  private var SampleImage:Class;

  private var dragging:Sprite;
  private var h2pos:Number = 0.5;
  private var h1:Sprite;
  private var h2:Sprite;
  private var h3:Sprite;

  public function Histogram3() {
   stage.scaleMode = "noScale";

   var bmd:BitmapData = Bitmap(addChild(new SampleImage())).bitmapData;

   var s:Sprite = new Sprite();
   addChild(s).y = bmd.height + 10;
   createHistogram(bmd, s);

   s = new Sprite();
   addChild(s).y = bmd.height + 140;
   createHistogram(bmd, s);

   addChild(createSlider()).y = bmd.height + 115;

   var bmdOrigin:BitmapData = bmd.clone();
   addEventListener(
    Event.ENTER_FRAME, 
    function(e:*):void {
     if(dragging) {
      var gamma:Number = Math.log((h2.x - h1.x) / (h3.x - h1.x)) / Math.log(0.5);
      var mapR:Array = [], mapG:Array = [], mapB:Array = [];
      for(var i:int = 0; i < 0x100; i++) {
       mapB[i] = i < h1.x ? 0 : i > h3.x ? 0xff : 255 * Math.pow((i - h1.x) / (h3.x - h1.x), 1 / gamma);
       mapG[i] = mapB[i] << 8;
       mapR[i] = mapB[i] << 16;
      }
      bmd.paletteMap(bmdOrigin, bmd.rect, new Point(), mapR, mapG, mapB);
      
      s.graphics.clear();
      createHistogram(bmd, s);
     }
    }
   );
  }

  // 生成色阶
  private function createHistogram(bmd:BitmapData, s:Sprite):void {
   // 灰度化
   var cmf:ColorMatrixFilter = new ColorMatrixFilter(
    [1 / 3, 1 / 3, 1 / 3, 0, 0, 
     1 / 3, 1 / 3, 1 / 3, 0, 0, 
     1 / 3, 1 / 3, 1 / 3, 0, 0]
   );
   var bmd2:BitmapData = bmd.clone();
   bmd2.applyFilter(bmd2, bmd2.rect, new Point(), cmf);

   // 用threshold来得到颜色分布
   var values:Array = [];
   for(var i:int = 0; i < 0x100; i++) {
    values[i] = bmd2.threshold(bmd2, bmd2.rect, new Point(), "==", 
     i + (i << 8) + (i << 16), 0, 0xffffff, false);
   }
   bmd2.dispose();

   // 画色阶
   var max:int = bmd.width * bmd.height / 50;
   s.graphics.lineStyle(1);
   for(i = 0; i < 0x100; i++) {
    s.graphics.moveTo(i, 100);
    s.graphics.lineTo(i, Math.max(0, 100 - values[i] / max * 100));
   }
  }

  // 生成滑条
  private function createSlider():Sprite {
   // 画滑条可移动的范围
   var slider:Sprite = new Sprite();
   slider.graphics.beginFill(0xffffff);
   slider.graphics.drawRect(0, 0, 256, 10);
   slider.graphics.endFill();
   slider.graphics.lineStyle(1, 0);
   slider.graphics.lineTo(255, 0);
   slider.buttonMode = true;
   slider.useHandCursor = true;

   // 画滑条
   h1 = Sprite(slider.addChild(createButton(0x000000))); h1.x = 0;
   h2 = Sprite(slider.addChild(createButton(0x999999))); h2.x = 128;
   h3 = Sprite(slider.addChild(createButton(0xffffff))); h3.x = 255;

   // mouseDown
   slider.addEventListener("mouseDown", function(e:*):void {
    var localX:Number = slider.globalToLocal(new Point(mouseX, mouseY)).x;

    // 滑动滑条
    var d1:Number = Math.abs(localX - h1.x);
    var d2:Number = Math.abs(localX - h2.x);
    var d3:Number = Math.abs(localX - h3.x);
    var max:Number = Math.min(d1, d2, d3);
    dragging = (max == d1 ? h1 : max == d2 ? h2 : h3);

    // 验证滑条是否超出范围
    var bounds:Rectangle = getDraggableBounds(dragging);
    dragging.x = Math.max(Math.min(localX, bounds.right), bounds.x);
    updateH2(null);

    dragging.startDrag(false, bounds);
   });

   // mouseMove
   stage.addEventListener("mouseMove", updateH2);

   // mouseUp
   stage.addEventListener("mouseUp", function(e:*):void {
    if(dragging) {
     dragging.stopDrag();
     dragging = null;
    }
   });

   return slider;
  }

  // 生成滑条
  private function createButton(color:int):Sprite {
   var s:Sprite = new Sprite();
   s.graphics.lineStyle(1, 0);
   s.graphics.beginFill(color);
   s.graphics.lineTo(5, 8.6);
   s.graphics.lineTo(-5, 8.6);
   s.graphics.endFill();
   return s;
  }

  // 计算滑条的移动范围
  private function getDraggableBounds(s:Sprite):Rectangle {
   if(s == h1) return new Rectangle(0, 0, h3.x - 4, 0);
   if(s == h2) return new Rectangle(h1.x + 2, 0, h3.x - h1.x - 4, 0);
   if(s == h3) return new Rectangle(h1.x + 4, 0, 255 - h1.x - 4, 0);
   return null;
  }

  // 计算灰滑条的移动
  private function updateH2(e:*):void {
   if(dragging && dragging != h2) {
    h2.x = (h3.x - h1.x) * h2pos + h1.x;
    h2.x = Math.max(Math.min(h2.x, h3.x - 2), h1.x + 2);
   }
   else if(dragging == h2){
    h2pos = (h2.x - h1.x) / (h3.x - h1.x);
   }
  }
 }
}

最终效果下载:Histogram2.swf

2007-10-20

[AIR]Adobe AIR Beta 2的安全方面的变化

AIR的更新补丁已经公开了(air_b2_badge_100907.zip : 50.5KB)。它是为了解决之前版本的XSS(cross Site Script)攻击漏洞。最好马上更新。 HTML的安全沙箱也发生了变化。为了对付Javascript的eval()、JSON、innerHTML等的攻击,从Beta 2开始,提供了2种安全沙箱。

第一种安全沙箱叫程序沙箱(Application Sandbox)。它能自由地使用AIR的API,但无法使用外部的Script与eval()。

第二种叫经典沙箱(Classic Sandbox)。它提供与HTML浏览器相同的功能,但无法调用AIR的API。

AIR Beta 2的默认沙箱为程序沙箱。所以几乎所有的AJAX框架都无法正常工作。在这种情况,应该先在经典沙箱里写HTML程序。再在使用AIR的API的地方转换为程序沙箱。最后再添加从经典沙箱调用程序沙箱的处理。使用SandboxBridge,可以使两种沙箱共存。

经典沙箱的指定方法、SandboxBridge的API的具体使用方法等可以参照一个简单的例子(air_htmlsecurity_sample_100107.zip : 64.7KB)。并且在AIR Developer Center(en)里有关联的文章(Building an expense tracker on the new Adobe AIR HTML security model)。

[AS3]RegExp的命名捕获组

命名捕获组为正则表现的捕获组的一种。它利用名字来指定捕获组(当然也可以用下标引用)。它经常使用在层次复杂、难以使用下表的表达式里。

定义命名捕获组使用(?P<名字>)的格式。

比如以下将会定义命名为digits的命名捕获组:

var myPattern:RegExp = /(?P<digits>\d+)/g; //命名捕获组
var str:String = "abc123def";
var result:Array = myPattern.exec(str);
trace(result.digits); //123

再如以下将会定义name与dom两个命名捕获组分别匹配用户名与域名:

var emailPattern:RegExp =
/(?P<name>(\w|[_.¥-])+)@(?P<dom>((\w|-)+))+\.\w{2,4}+/;
var address:String = "bob@example.com";
var result:Array = emailPattern.exec(address);
trace(result.name); // bob
trace(result.dom); // example

注意,命名捕获组不是ECMA-Script定义的。为Actionscript自行扩展的。

2007-10-19

[笑话]2007年BBS上最经典的话

2007年BBS上最经典的71句话[值得你看!] - 文学城: 热点论坛 web.wenxuecity.com
  1. 这个世界上我只相信两个人,一个是我,另一个不是你。
  2. 生活真他妈好玩,因为生活老他妈玩我。  
  3. 好好学习,天天想上!  
  4. 花前月下,不如花钱“日”下。  
  5. 叶子的离开,是因为风的追求还是树的不挽留?   
  6. 有些人就是这样不懂事,你不X他妈,他就不知道你是他爹。    
  7. 你以为我会眼睁睁地看着你去送死吗?我会闭上眼睛的!  
  8. 佛曰:“前世的500次回眸才换来今生的一次擦肩而过”。我宁愿用来世的一次擦肩而过来换得今生的500次回眸。   
  9. 我拿什么整死你的爱人……  
  10. 黑夜给了我一双黑色的眼睛,可我却用它来翻白眼。    
  11. 网络就像是监狱,本来是偷了个钱包进来的,等出去的时候就什么都学会了。    
  12. 女娲日天,后羿射之。    
  13. 兄弟如手足,女人如衣服,谁动我手足,我扒他衣服!    
  14. 我是个演员,一看见漂亮MM眼就圆……    
  15. 上帝把所有人都骗了,因为地狱才是最美的!佛知道真相,所以佛说:“我不入地狱,谁入地狱?”    
  16. 我床上的不知道是谁媳妇,我媳妇不知道在谁的床上!    
  17. 看到你我连食欲都没了,还谈什么性欲?    
  18. 天使之所以会飞,是因为她们把自己看得很轻……    
  19. 我想早恋,但是已经晚了……    
  20. 别人的失败就是我的快乐!    
  21. 天哪!我的衣服又瘦了。    
  22. 生下来的人没有怕死的,怕死的都TM没生下来,所以谁都别TM的装横!    
  23. 现实的社会,毁了我一个做好人的机会!    
  24. 以后不要在我面前说英文,OK?    
  25. 名花虽有主,我来松松土!    
  26. 有钱男子汉,没钱汉子难!    
  27. 我要是妞,早爱上我了……    
  28. 我以为我颓废,原来我报废了!    
  29. 问世间情为何物?圣人答曰:“废物!”    
  30. 我不能给你幸福,但可以给你舒服!    
  31. 思想有多远,你就给我滚多远!    
  32. 流氓不害怕,就怕流氓有文化……    
  33. 客官请自重,小女子只卖身不卖艺。    
  34. 你不能让所有人满意,因为不是所有的人都是人!    
  35. 有事秘书干,没事干秘书。    
  36. 你给我一份爱,我还你一夜情!    
  37. 师太!你就从了老衲吧!    
  38. 我爱你!关你什么事?    
  39. 你的就是我的,我的还是我的!    
  40. 不错!人都是逼出来的。    
  41. 时间就像乳沟,只要挤一挤总还是有的!      
  42. 男人的谎言可以骗女人一夜,女人的谎言可以骗男人一生!     
  43. 鸳鸯戏水,都他妈淹死;比翼双飞,都他妈摔死。    
  44. 承诺就象“CN妈”一样 经常说却很难做得到!    
  45. 我的爱人都叫我第三者!    
  46. 喜欢是淡淡的爱;爱是深深的喜欢!    
  47. 人不猥琐枉少年!    
  48. 我不是一个随便的人,我随便起来不是人……     
  49. 如果你不能给你的女人穿上嫁衣,那么千万别停下你解开她衣扣的手!   
  50. 宁可牺牲中国最后一个处男,决不留下日本任何一个处女!    
  51. 走牛B的路,让去说吧!    
  52. 我不喜欢只和一个女人上很多次床,而是喜欢和很多女人只上一次床。    
  53. 我为兄弟两肋插刀,为女人插兄弟两刀。    
  54. 怀才就像怀孕,时间久了才能让人看出来。    
  55. 想污染一个地方有两种方法:用垃圾,或者用钞票!    
  56. 水能载舟,亦能煮粥!    
  57. 子在川上曰:“有船多好!”    
  58. 骑白马的不一定是王子,可能是唐僧;有翅膀的不一定是天使,也可能是鸟人!     
  59. 大学毕业才明白,原来不是我上大学,而是大学“上”我!    
  60. 我很丑可是我很持久!    
  61. 数钱数到手抽筋,睡觉睡到自然醒!    
  62. 有钱人终成眷属。    
  63. 鸟大了什么林子都有!    
  64. 锄禾“日”当午,弯弓“射”大雕。     
  65. “捷克斯洛伐克”!我叫JACK,我老婆总这样抱怨我。
  66. 只有在大排长龙时,才能真正意识到自己是“龙的传人”。

2007-10-14

[AS3]位图的色阶控制(1) -- 得到色阶

色阶为位图的颜色分布的图。做过图形处理的应该很熟悉。

比如下图:上面为原图,下面为色阶。

Historgram

得到方法:

  1. 灰色化。把各个通道求平均。用ColorMatrixFilter即可。
  2. 用threshold来得到颜色分布。threshold的返回值为匹配的像素的个数。

代码:


package {
    import flash.display.*;
    import flash.filters.ColorMatrixFilter;
    import flash.geom.Point;

    public class TestBitmap extends Sprite {
        [Embed(source="023.jpg")]
        private var SampleImage:Class;

        public function TestBitmap() {
            var bmd:BitmapData = Bitmap(addChild(new SampleImage())).bitmapData;
            var s:Sprite = new Sprite();
            createHistogram(bmd,s);
            addChild(s).y = bmd.height + 10;
        }

        //生成色阶
        private function createHistogram(bmd:BitmapData, s:Sprite):void {
            //灰度画
            var cmf:ColorMatrixFilter = new ColorMatrixFilter(
                [1 / 3, 1 / 3, 1 / 3, 0, 0, 
                 1 / 3, 1 / 3, 1 / 3, 0, 0, 
                 1 / 3, 1 / 3, 1 / 3, 0, 0]
            );
            var bmd2:BitmapData = bmd.clone();
            bmd2.applyFilter(bmd2, bmd2.rect, new Point(), cmf);

            //用threshold来得到颜色分布
            var values:Array = [];
            for(var i:int = 0; i < 0x256; i++) {
                values[i] = bmd2.threshold(bmd2, bmd2.rect, new Point(), "==", i, 0, 0xff, false);
            }
            bmd2.dispose();

            //画色阶
            var max:int = bmd.width * bmd.height / 50;
            s.graphics.lineStyle(1);
            for(i = 0; i < 256; i++) {
                s.graphics.moveTo(i, 100);
                s.graphics.lineTo(i, Math.max(0, 100 - values[i] / max * 100));
            }
        }
    }
}

我的附件

我的附件。

[AS3]位图过度之模板过度

先来看效果:

它使用的模板为:

运行原理很简单,主要是运用阈值,再设置原图的Alpha通道。详细看源码

源码下载BitmapPatternTween.fla

2007-10-09

Adobe AIR的电子署名

AIR Beta 2以后,在打包时必须制作电子署名。电子署名的目的为:

  1. 确认包未被修改(比如说被绑定病毒)
  2. 确认包的创建者。

如果未署名,将会生成扩展名为airi的文件,这个如果不用adt等来署名的话,将无法安装到AIR运行环境。

署名可以使用CA发行的或者自己的署名的证明书。用自己的署名的证明书的话无法用于以上的确认包的创建者的目的。

注意,电子署名并不保证程序能够正常运行。并且,因为现在为Beta,所以并不能保证电子署名本身功能的正确性。

自己的署名的证明书的制作

自己的署名的证明书可以用 Flex Builder 3 Beta 2,Flash CS3/Dreamweaver CS3 的 AIR Beta 2用的扩展插件来制作。注意,千万别忘了密码

用Flex Builder 3 Beta 2来制作

执行Export向导,当显示"Digital Signature"的画面时,点"Create..."按钮。再输入署名,密码,生成的文件,点OK。注意在名字里可以使用的只有英数字。

用Flash CS3来制作

选择AIR->Application & Installer Settings打开设置窗口,并且确认 Sign the AIR file with a digital certificate 是选中的。再点击"Digital Signature"右边的 "Change..."按钮。这将会打开设定署名的窗口。以后与Flex Builder相同。(可以选择1024 Bit与2048 Bit)

用Dreamweaver CS3来制作

选择Site->AIR Application Settings...打开设置窗口。再点击"Digital signature"右边的"Set..."。这将会打开设定署名的窗口。以后与Flash CS3相同。

2007-10-03

新的RIA制作工具 - Thermo

Thermo是为了提高RIA的UI设计的工具。

ThermoMain

Thermo的功能如下(预定):

  1. 用Photoshop, Illustrator, Fireworks来设计画面。
  2. 创建的文件可以直接用Thermo来打开,并用它的绘画工具来设计画面。
  3. 对画面设计添加交互功能。
  4. 制定过度与特效。
  5. 设定测试数据来运行与测试。
  6. 输出MXML。

有一种Photoshop, Illustrator, Fireworks为平面设计者,Thermo为交互设计者的工具的感觉。因为可以与FlexBuilder的文件共享,所以RIA的开发效率会大大提高。

Demo的图片等详细参见Adobe Lab(Thermo@Labs

2007-10-02

Spry 1.6 与 AIR Extension for Flash & Dreamweaver CS3

Spry 1.6 Pre-realse 发布了!Spry Framework 是为Ajax开发的轻量级的UI等的库。它可以高校地开发出强壮的Ajax网页。 Spry Framework 的 Dreamweaver CS3 的升级也公开了。(Spry Prerelease 1.6 Download@Labs)变更已经写在上面了,大家可以去看一看。(Spry Change Log@Labs)Log也更新了。(Spry framework for Ajax@Labs

并且AIR Beta 2 的Dreamweaver CS3 与 Flash CS3功能扩展插件也发布了。均支持以下环境

  • Windows XP SP2
  • Windows Vista
  • Mac OS 10.4.x (Intel or PPC)

注意,必须先卸载以前的版本在安装。

Flash Player 10的特大新闻!

在US的MAX大会上,公布了Code名为Astro的Flash Player 10的部分新功能如下:

新的Text Layout 渲染引擎

Astro将会添加新的Text Layout 渲染引擎。有了这个就有可能能够做到类似于HTML的表现能力的Text。这个功能有可能会在Flash Player 9的新版本中添加。

3D

终于来了!

Flash 的 MovieClip将会能够在3D空间内操作了。虽然Demo是很简单的效果,离真正的3D还有一定的距离,但表现将会有大幅度的提升。

自定义滤镜,混合模式,特效

将会可以自己开发滤镜等了。这些的制作将会使用已发布的Adobe Image Foundation (AIF) Toolkit。AIF Toolkit虽然为预览版,但已经能够下载了。会C,OpenGL的开发者可以试一试。(Adobe Image Foundation (AIF) Toolkit@Labs

看来Flash Player 与 Silverlight的大战开始了!

2007-10-01

Flex 3 beta 2

Flex 3 Beta 2 在Adobe Lab 发布了。详细参见(Adobe FlexBuilder@Labs, Adobe Flex SDK@Labs

根据Flex 3 Planning的最新信息,Flex 3 的时间表如下:

  • April 9, 2007 M1 Release (Alpha)
  • June 11, 2007 M2 Release (Beta 1)
  • October M3 Release (Beta 2) - Feature Complete
  • Late 2007 M4 - Release Candidate
  • Early 2008 Final Release

本次的内部版本为M3,即第三个测试版本。功能已经完全实装了。在今年内将发布RC版本,即M4。

使用CrossDomain RSL时,必须使用一起发布的Flash Player(9.0.60.235)。这个Flash Player 为Beta版。

Flex Skin Design Extensions

为CS3的产品的Flex 3 Skin制作的导入的功能扩展也发布了。目前的版本为Pre-release。提供了Photoshop, Illustrator, Flash, Fireworks的功能扩展。

下载地址(Flex Skin Design Extensions@Labs Downloads

2007-09-17

[AS3] Base85 的实现

Base85 与 Base64 相似,为一种把2进制的数据转换为文字数据的编码方式。它将4个2进制字节转换为5个字符,数据的增加率为25%。(Base64为33%)

Base85是在RFC-1924里面定义的。详细请参照RFC-1924

编码方式:

  1. 开始
  2. 从输入流读4个字节,把值放入uint类型的变量a中。
  3. 把a转换为85进制(除以85,求余数)的字符串,并写入输出流。
  4. 当输入流的剩余少于4个字节时
    1. 从输入流读入剩余的字节,把值放入uint类型的变量a中。
    2. go to 3 (为了效率,这一步应该分为3种情况来写。)
  5. 结束

源码:

Base85CharSet.as

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2007 Advanced Flex Project http://code.google.com/p/advancedflex/.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package advancedflex.io.format {
/**
* Base85的字符集(Character Set)
*
* @see http://rfc.net/rfc1924.html RFC-1924
* @see Base85Decoder
* @see Base85Encoder
*/
public final class Base85CharSet {

/**
* 在<strong>RFC-1924</strong>里定义的一般的字符集(根据编码算字符)
*/
//0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~
public static const RFC_1924:Array =
[
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T",
"U", "V", "W", "X", "Y", "Z", "a", "b", "c", "d",
"e", "f", "g", "h", "i", "j", "k", "l", "m", "n",
"o", "p", "q", "r", "s", "t", "u", "v", "w", "x",
"y", "z", "!", "#", "$", "%", "&", "(", ")", "*",
"+", "-", ";", "<", "=", ">", "?", "@", "^", "_",
"`", "{", "|", "}", "~",
];
/**
* 在<strong>RFC-1924</strong>里定义的一般的逆字符集(根据字符算编码)
*/
public static const DECODE_RFC_1924:Object =
{
"0":0, "1":1, "2":2, "3":3, "4":4, "5":5, "6":6, "7":7, "8":8, "9":9,
"A":10, "B":11, "C":12, "D":13, "E":14, "F":15, "G":16, "H":17, "I":18, "J":19,
"K":20, "L":21, "M":22, "N":23, "O":24, "P":25, "Q":26, "R":27, "S":28, "T":29,
"U":30, "V":31, "W":32, "X":33, "Y":34, "Z":35, "a":36, "b":37, "c":38, "d":39,
"e":40, "f":41, "g":42, "h":43, "i":44, "j":45, "k":46, "l":47, "m":48, "n":49,
"o":50, "p":51, "q":52, "r":53, "s":54, "t":55, "u":56, "v":57, "w":58, "x":59,
"y":60, "z":61, "!":62, "#":63, "$":64, "%":65, "&":66, "(":67, ")":68, "*":69,
"+":70, "-":71, ";":72, "<":73, "=":74, ">":75, "?":76, "@":77, "^":78, "_":79,
"`":80, "{":81, "|":82, "}":83, "~":84
};
/**
* 在<strong>ascii85</strong>里定义的一般的字符集(根据编码算字符)
*/
//!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuv
public static const ASCII85:Array =
[
"!", "\"", "#", "$", "%", "&", "'", "(", ")", "*",
"+", ",", "-", ".", "/", "0", "1", "2", "3", "4",
"5", "6", "7", "8", "9", ":", ";", "<", "=", ">",
"?", "@", "A", "B", "C", "D", "E", "F", "G", "H",
"I", "J", "K", "L", "M", "N", "O", "P", "Q", "R",
"S", "T", "U", "V", "W", "X", "Y", "Z", "[", "]",
"^", "_", "`", "a", "b", "c", "d", "e", "f", "g",
"h", "i", "j", "k", "l", "m", "n", "o", "p", "q",
"r", "s", "t", "u", "v",
];
/**
* 在<strong>ascii85</strong>里定义的一般的字符集(根据编码算字符)
*/
public static const DECODE_ASCII85:Object =
{
"!":0, "\"":1, "#":2, "$":3, "%":4, "&":5, "'":6, "(":7, ")":8, "*":9,
"+":10, ",":11, "-":12, ".":13, "/":14, "0":15, "1":16, "2":17, "3":18, "4":19,
"5":20, "6":21, "7":22, "8":23, "9":24, ":":25, ";":26, "<":27, "=":28, ">":29,
"?":30, "@":31, "A":32, "B":33, "C":34, "D":35, "E":36, "F":37, "G":38, "H":39,
"I":40, "J":41, "K":42, "L":43, "M":44, "N":45, "O":46, "P":47, "Q":48, "R":49,
"S":50, "T":51, "U":52, "V":53, "W":54, "X":55, "Y":56, "Z":57, "[":58, "]":59,
"^":60, "_":61, "`":62, "a":63, "b":64, "c":65, "d":66, "e":67, "f":68, "g":69,
"h":70, "i":71, "j":72, "k":73, "l":74, "m":75, "n":76, "o":77, "p":78, "q":79,
"r":80, "s":81, "t":82, "u":83, "v":84
}
}
}

Base85Encoder.as

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2007 Advanced Flex Project http://code.google.com/p/advancedflex/.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
////////////////////////////////////////////////////////////////////////////////
package advancedflex.io.format {
import flash.utils.ByteArray;
import flash.utils.IDataInput;

/**
* Base85的编码器
* <p>他把4个字节的2进制数据转换为5个字节的文本数据。数据的增加度为25%。</p>
*
* @see Base85CharSet
* @see Base85Decoder
*/
public class Base85Encoder {
/**
* 用String来编码
*
* @param src 原文
* @param charSet Base85字符集,默认为 Base85CharSet.RFC_1924
* @return 密文(原文编码后的数据)
*
* @see Base85CharSet#RFC_1924
*/
public static function encode(src:String, charSet:Array = null):String {
// Convert string to ByteArray
var bytes:ByteArray = new ByteArray();
bytes.writeUTFBytes(src);
bytes.position = 0;
return encodeByteArray(bytes, charSet ? charSet : Base85CharSet.RFC_1924);
}

/**
* 用ByteArray来编码
* @param data 原文的输入流
* @param charSet Base85字符集,默认为 Base85CharSet.RFC_1924
* @return 密文(原文编码后的数据)
*
* @see Base85CharSet#RFC_1924
*/
public static function encodeByteArray(data:IDataInput, charSet:Array = null):String {
charSet = charSet ? charSet : Base85CharSet.RFC_1924;
// Initialise output
var output:String = ""; //output
var srcLength:int = data.bytesAvailable; //length of normal bytes
var endbytes:int = srcLength % 4; //length of extra bytes.
var buf:uint; //encode buffer

//set this var to correct value.(normal = all - extra)
srcLength -= endbytes;

//encode normal group of bytes
for(var i:int = 0; i < srcLength; i+=4) {
buf = data.readUnsignedInt();
output += charSet[buf % 85];
buf /= 85;
output += charSet[buf % 85];
buf /= 85;
output += charSet[buf % 85];
buf /= 85;
output += charSet[buf % 85];
buf /= 85;
output += charSet[buf % 85];
}

//encode last group of bytes
buf = 0;
for(var j:int = 0; j < endbytes; j++) {
buf = (buf << 8) | data.readByte();
}
switch(endbytes) {
case 0: //no extra byte
break;
case 3: //has 3 extra bytes
output += charSet[buf % 85];
buf /= 85;
case 2: //has 2 extra bytes
output += charSet[buf % 85];
buf /= 85;
default: //has 1 extra byte
output += charSet[buf % 85];
buf /= 85;
output += charSet[buf % 85];
}
return output;
}
}
}

Base85Decoder.as

/////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2007 Advanced Flex Project http://code.google.com/p/advancedflex/.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
//////////////////////////////////////////////////////////////////////////////// package advancedflex.io.format {
import flash.utils.ByteArray;
import flash.utils.Endian;
import flash.utils.IDataOutput;

/**
* Base85的解码器
* <p>他把5个字节的文本数据4转换为个字节的2进制数据。</p>
* @see Base85CharSet
* @see Base85Encoder
*/
public class Base85Decoder { /**
* 解码为String
*
* @param src 密文
* @param charSet 逆字符集
* @return 原文
*
* @see Base85CharSet#RFC_1924
* @see Base85Encoder#encode
*/ public static function decode(src:String, charSet:Object = null):String {
var bytes:ByteArray = new ByteArray();
bytes.writeUTFBytes(src);
var mark:int = bytes.length;
decodeByteArray(src, bytes, charSet ? charSet : Base85CharSet.RFC_1924);
bytes.position = mark;
return bytes.readUTFBytes(bytes.bytesAvailable);
} /**
* 解码为ByteArray
*
* @param data 密文
* @param output 输出流
* @param decharSet 逆字符集
*
* @see Base85CharSet#RFC_1924
* @see Base85Encoder#encodeByteArray
*/
public static function decodeByteArray(data:String, output:IDataOutput, decharSet:Object = null):void {
decharSet = decharSet ? decharSet : Base85CharSet.DECODE_RFC_1924;
var dataLength:int = data.length;
var endbytes:int = dataLength % 5;
dataLength -= endbytes;
//decode normal group of bytes
for(var i:int = 0; i< dataLength;i++) {
output.writeUnsignedInt(
decharSet[data.charAt(i)] +
decharSet[data.charAt(++i)]*85 +
decharSet[data.charAt(++i)]*(85*85) +
decharSet[data.charAt(++i)]*(85*85*85) +
decharSet[data.charAt(++i)]*(85*85*85*85)
);
}
//decode last group of bytes
var buf:int;
switch(endbytes) {
case 0:
break;
case 4:
buf =
(
decharSet[data.charAt(i)] +
decharSet[data.charAt(++i)]*85 +
decharSet[data.charAt(++i)]*(85*85) +
decharSet[data.charAt(++i)]*(85*85*85)
);
if(output.endian == Endian.BIG_ENDIAN) {
output.writeByte(
(buf&0xFF0000) >> 16
);
output.writeByte(
(buf&0x00FF00) >> 8
);
output.writeByte(
(buf&0x0000FF)
);
} else {
output.writeByte(
(buf&0x0000FF)
);
output.writeByte(
(buf&0x00FF00) >> 8
);
output.writeByte(
(buf&0xFF0000) >> 16
);
}
break;
case 3:
output.writeShort(
(
decharSet[data.charAt(i)] +
decharSet[data.charAt(++i)]*85 +
decharSet[data.charAt(++i)]*(85*85)
)
);
break;
default: //2
/* buf =
(
decharSet[data.charAt(i)] +
decharSet[data.charAt(++i)]*85
); */
output.writeByte(
decharSet[data.charAt(i)] +
decharSet[data.charAt(++i)]*85
);
break;
}
}
}
}

asdoc的技巧 - 链接的别名

在asdoc里,使用@see时有时候需要给链接去一个别名。 即http://syncspace.blogspot.com/ 应为 Synchronous Space

其实@see的语法为

@see URL [别名]

别名可以包含任何字符(除了换行符以外)

所以上面的例子应为

@see http://syncspace.blogspot.com/ Synchronous Space

2007-09-09

AS3.0的优化(1)

AS3.0在内部做了一些优化,并引入了JIT,但还是有需要争分夺秒的地方。比如游戏的AI等运算量大的算法。

以下列出一些优化公式:(每个公式均测试5次,取平均值,每次循环次数为6000000,单位为ms)

//当x为int时
-x    => ~x+1 // 从 134 到 8
-x-1  => ~x   // 从 154 到 5
-(~x) => x+1  // 从 130 到 8

在内部,-x有可能被编译为(-1) * x。而~x+1却为inc ~x(inc 为CPU的内部命令,意思是加一)。下面的两个公式就不用解释了。

2007-09-05

Flash Player9的普及率突破90%的大关!

Flash Player9的普及率终于突破90%的大关!

AS3.0终于可以成为主流了!

2007-09-02

本博客的版本声明(Copyright)

本博客的除计算机源代码与特别注明以外均采用

Creative Commons 署名-非商业性使用-相同方式共享 3.0 Unported

CreativeCommonsLicense

的许可协议

您可以自由:

  • 复制、发行、展览、表演、放映、广播或通过信息网络传播本作品
  • 创作演绎作品

惟须遵守下列条件:

  • 署名. 您必须按照作者或者许可人指定的方式对作品进行署名。

  • 非商业性使用. 您不得将本作品用于商业目的。

  • 相同方式共享. 如果您改变、转换本作品或者以本作品为基础进行创作,您只能采用与本协议相同的许可协议发布基于本作品的演绎作品。

详细条款请参看法律文本(许可协议全文)(英文)

对于计算机源代码,除特别注明以外均采用

Apache License Version 2.0

  Copyright 2007 Stephen 

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

协议。需要满足的条件:

1. 需要给代码的用户一份Apache Licence

2. 如果你修改了代码,需要再被修改的文件中说明。

3. 在延伸的代码中(修改和有源代码衍生的代码中)需要带有原来代码中的协议,商标,专利声明和其他原来作者规定需要包含的说明。

4. 如果再发布的产品中包含一个Notice文件,则在Notice文件中需要带有Apache Licence。你可以在Notice中增加自己的许可,但不可以表现为对Apache Licence构成更改。

详细条款请看Apache License, Version 2.0(英文)

博客的模板等关于博客的格式(非文章内容):

(c)Copyright All Rights Reserved.

用Ant来打包(compc)flex的源文件为SWC

直接用compc来打包flex源文件是很复杂且繁琐的事。但用了Ant,在Eclipse里一切都变为按一个键。

compc.xml:

<!--/////////////////////////////////////////////////////////////////////////////
//Copyright 2007 Advanced Flex Project http://code.google.com/p/advancedflex/.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
///////////////////////////////////////////////////////////////////////////// -->
<project name="Compc build" default="main">
<!-- defines all values for the Compc compiler -->
<property file="compc.properties" />
<!-- main target: cleans and compiles ASDocs -->
<target name="main" depends="clean, log, compc" />
<!-- deletes and recreates the compc directory -->
<target name="clean">
<delete dir="${output.dir}" failonerror="true"/>
<mkdir dir="${output.dir}"/>
</target>
<!-- runs the compc.exe compiler on the source -->
<target name="compc">
<exec executable="${compc.exe}" failonerror="true">
<arg line="-include-sources '${src}'" />
<arg line="-output '${output.dir}/${output.file}'" />
</exec>
</target>
<!-- writes compc output to log file: compc-log.log -->
<target name="log">
<record name="${output.dir}/compc-log.log" action="start" append="true" />
</target>
</project>

compc.properties:

################################################################################
##Copyright 2007 Advanced Flex Project http://code.google.com/p/advancedflex/.
##
## Licensed under the Apache License, Version 2.0 (the "License");
## you may not use this file except in compliance with the License.
## You may obtain a copy of the License at
##
## http://www.apache.org/licenses/LICENSE-2.0
##
## Unless required by applicable law or agreed to in writing, software
## distributed under the License is distributed on an "AS IS" BASIS,
## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
## See the License for the specific language governing permissions and
## limitations under the License.
############################################################################### #compc.exe的位置
compc.exe =C:/Program Files/Adobe/Flex Builder 2 Plug-in/Flex SDK 2/bin/compc.exe #源文件的位置
src = #输出的位置
output.dir = #输出的文件名
output.file =

2007-08-31

Shockwave Player 10 发布了

8/22,Adobe 发布了Shockwave Player 10.2.0.023。莫非Director要发布新版本了?

下载Shockwave Player 10

2007-08-29

各国Google的搜索结果比较

搜索“生当作人杰 死亦为鬼雄”的结果

Google日本有89400项

Google日本有89400项

Google.com有88400项

Google.com有88400项。

Google中国没有!

Google中国没有!

悲哀!这句李清照的名句不知道犯了某些人的什么忌讳?

2007-08-27

和谐了的谷歌算Evil呢还是不Evil呢?

看到Isaac Mao的twitter说Google.cn在一位女士的名字搜索上居然也和谐了:

Google中国已搜不到"石靖": 石靖一夜红遍了网络,其自己在myspace上发布自己的性感照,本意是出名,但没想到,这个名出得太大了. 也许是自己的太红了,结果连Google中国都拜倒.. http://tinyurl.com/2nzz5k

和谐版的Googl

好奇地去尝试一下,果然谷歌给出了以下和谐版的答案:

Google

无法访问您所搜索的信息,请返回 google.cn 查询其它信息.

虽然self censored 版本的Google.cn推出已经有一段时间了,反对的声音一大片, 但是我一直还是比较支持google.cn的做法。 因为无论如何,google要在一个政府管辖的地方做生意就无法和一个政府对抗,推出自我审查的版本虽然看起来是一种妥协,其实却是一种进步,对google和用户来说都是有利的。

然而这次的和谐却有着质的区别,这次google.cn和谐掉的不是政治敏感的话题,而是一个普通的中国名字。也许全中国叫“石靖”的人有几十万, 但也许google只是忠实执行了某些政府部门的指令从而导致这个普通的中国名字在google.cn上消失了!

Don’t be evil

和谐掉“石靖”是be evil 还是don’t be evil? 这个答案不知道google是否能给出官方的解释, 我期待着他们能对此说些什么。

作为在中国经营过网站的人来说,我不难想象google面临的官僚机构的压力。 官僚机构(也就是所谓的“有关部门”,其实他们是否“有关”你根本无法知道。 )在要求和谐掉某些关键词的时候根本没有道理可言,比如当年他们要求和谐掉“一塌糊涂”这个词,根本不在乎“一塌糊涂”这是一个中国成语,是中华民族语言文化中的一部分。 这次他们要求和谐掉“石靖”,他们不会介意中国人民中可能有几十万人叫做“石靖”。

然而,作为google这样的公司在这个名字的问题上也如此懦弱的表现,我只能深深表示失望。也许是对他们有过太多的期望,才如此失望吧。一个曾经把"Don’t be evil"写在他们使命宣言中的公司在中国表现上的陨落,我不知道这说明了我们的土壤无法"don’t be evil",抑或"don’t be evil"其实只是某些公司的文字游戏。

作为中国人,我为“有关部门”对名字也进行和谐而深深悲哀;作为曾经的google fans, 我为他们远离"don’t be evil"的初衷而深深悲哀。

关于石靖

差不多一周前在MITBBS这个被和谐了的站点上我看到了这个名字和一些照片。我认为她并不是“自己在myspace上发布自己的性感照,本意是出名”,而是被一个低劣的美国混蛋Robert Kuglger炫耀下的受害者。

然而这却意外导致了“石靖”成为了热门的搜索关键词,而中文网络上铺天盖地都是对她照片的转载和猎奇性质的评论。 除了部分抨击那个美国佬的文字外,更多我看到的是看热闹的和冷嘲热讽的声音,那些肆意装载她的照片的人其实只是这个无耻美国混蛋的帮凶而已。

一个我们中国的女同胞被个别无耻的老外欺凌(我指其照片被公布,而不是其私生活的选择,作为成人她有权选择她私生活的方式,但作为那个老外她无权公布那些照片),得到确是广大同胞的冷嘲热讽和故意的帮凶,我不得不再次悲哀一下。

悲哀

越来越觉得自己成为了“愤青”,呵呵,无奈。

为中国悲哀,为中国人悲哀,为google 悲哀,为石靖悲哀.

转自和谐了的谷歌算Evil呢还是不Evil呢? | 我blog故我在

2007-08-19

声音编辑不是梦! - AS3.0的声音合成

以前,在Flex2刚发布时,有人说AS3.0能够编辑声音,方法是用ByteArray与SoundMixer。但被证明这是的,SoundMixer能读不能写!

但现在新的方法出现了!把声音用SWF的格式写到ByteArray里,再用Loader读进来,最后把它变为Sound!

实现这个的是Andre Michelle 与 Joa Ebert 开发的popforge Project。

Sample:

package {
 import de.popforge.audio.output.Audio;
 import de.popforge.audio.output.AudioBuffer;
 import de.popforge.audio.output.Sample;
 import de.popforge.audio.output.SoundFactory;
 
 import flash.display.Sprite;
 import flash.events.Event;
 import flash.utils.describeType;
 import flash.media.Sound;

 public class popforge extends Sprite
 {
  public function popforge()
  {
   var samples:Array = [];
   var phase:Number = 2;
   var freq:Number = 0.12
   for( var i: int = 0 ; i < 44100*3 ; i++ ) {
   
    //-- create an amplitude [-1,1]
   
    var amplitude:Number = Math.sin( phase * Math.PI * 2 );
   
    //-- create a sample
   
    var sample:Sample = new Sample( amplitude, amplitude );
   
    //-- push in array
   
    samples.push( sample );
   
    //-- increase phase
   
    phase += freq / Audio.RATE44100;
   
   }
   SoundFactory.fromArray(samples,
    Audio.MONO,
     Audio.BIT16, 
     Audio.RATE44100, 
     func);
  }
  private function func(event:Sound):void {
   event.play();
  }
 }
}

2007-08-12

Fedora 7(Linux)之旅

今天试用了Fedora 7,好!

在UI方面,Linux越来越接近Windows了。比以前用的Redhat 4好了N倍。因为是Linux,比Windows轻了许多。Windows有时程序死了时,结束进程都不行,但我还没有遇到Linux杀不死的进程(非内核的)。

我是在VMware 6上安装的。下载 Fedora 7(2G多) 用了30分,BT下载的(光纤就是快!)。安装用了近1小时。但安装VMware Tools时提示没有Linux Kernel Source包。郁闷!(至今未解)

*2007-09-19更新,问题已解决!

2007-07-29

technorati认证

Technorati Profile

Flash-Ajax Video Component

最近,在Adobe Labs公开了一个 Flash-Ajax Video Component

什么是Flash-Ajax Video Component?

Flash-Ajax Video Component(FAVideo) 是一个轻量级的,开源的用 Ajax+Flash 来播放flv的组件。它可以运用在 Ajax 的程序里。它可以使在 Javascript 里控制 Video 像在 Flash 那样容易。

Hello World 程序

<html>
 <head>
  <title>Various ways to work with FAVideo</title>
  <script src="AC_RunActiveContent.js" type="text/javascript"></script>
  <script src="FAVideo.js" type="text/javascript"></script>
 </head>
 <body onLoad="">
  <div id="divOne"></div>
  <script type="text/javascript">
   playerOne = new FAVideo(
    "divOne", "demo_video.flv",0,0,{ autoLoad:true, autoPlay:true });
  </script>
  <script>
   playerOne.addEventListener("playheadUpdate",this,myHandler);
   playerOne.removeEventListener("playheadUpdate",this,myHandler);
   function myHandler() {
    //alert("eh");
   }
  </script>
 </body>
</html>

运行截图:

FAVideo Demo

2007-07-27

SWF与FLV ver 9 的文件格式公开了!

SWF与FLV ver 9 的文件格式终于公开了。在这里(Adobe Player Licensing)可以签约得到。

现在,可以研究SWF的格式了。

注意,根据Licence,这个文件格式只能用于SWF的生成,而不能用于开发Player。

2007-07-26

Flex 2.0.1 Hotfix 3

Flex 2.0.1 SDK Hotfix 3 在 US 的支持中心里发布了。

利用在US发布的LCDS 2.5.1时,需要添加Hotfix 3。注意Hotfix 3是专门针对LCDS 2.5.1的,使用FDS 2.0.1时最好不要添加。

其他的注意事项:

  • 不支持Flex Builder 2.0
  • 添加Hotfix 3前,需要添加Hotfix 2。
  • 如果没有出现Hotfix修正的问题,最好不要添加。

详细看下面:

2007-07-22

递归算法(2) - 勾股树

先来看一下效果:

 
GouguTree

实现代码:

/**
 * 勾股树
 * @param g Graphics
 * @param p1 起始点1
 * @param p2 起始点2
 * @param angle 每次迭代时的偏移角(弧度)
 * @param n 迭代次数
 */
function gouguTree(g:Graphics, p1:Point, p2:Point, angle:Number, n:int):void {
 /*
  *    p5
  *    /\
  * p3/A \p4
  *  +---+
  *  |   |
  *  +---+
  * p1   p2
  */
 var p3:Point, p4:Point, p5:Point;
 var length:Number;
 var p1_p2:Point = p2.subtract(p1);
 var baseAngle:Number = Math.atan2(p1_p2.y, p1_p2.x); 
 length = p1_p2.length;
 p3 = p1.add( Point.polar(length, baseAngle + Math.PI/2) );
 p4 = p3.add(p1_p2);
 g.moveTo(p1.x, p1.y);
 g.lineTo(p2.x, p2.y);
 g.lineTo(p4.x, p4.y);
 g.lineTo(p3.x, p3.y);
 g.lineTo(p1.x, p1.y);
 if(n > 0) {
 //if(length > 10) { //改为此句将会当长度小于10时结束。
  /*
   * cosA = |p3_p5| / |p3_p4|
   * |p3_p5| = cosA * |p1_p2| (p3_p4 = p1_p2)
   */
  var p3_p4:Point = p4.subtract(p3);
  var l_p3_p5:Number = Math.cos(angle) * length;
  p5 = p3.add( Point.polar(l_p3_p5, baseAngle + angle) );
  trace("@l_p3_p5",l_p3_p5);
  n--;
  gouguTree(g, p3, p5, angle, n);
  gouguTree(g, p5, p4, angle, n);
 }
}

FireBug的功过

FireBug太强大了。

我的Blog改版时全靠它来debug。没有它,还不知现在CSS怎么样了。

FireBug太脆弱了。

我每次浏览了含有不正确的网页时,它就有可能造成死机。而且每次关闭Firefox时都会出现Error。

我想,大家应该可能遇到过这样的问题。请告诉我该怎么办?

2007-07-21

递归算法(1) - 科赫曲线

先来看一下效果:

KochCurve

实现代码:

/**
 *科赫曲线
 *@param g Graphics
 *@param p1 起始点
 *@param p2 结束点
 *@param p1 迭代次数
 */
function kochCurve(g:Graphics, p1:Point, p2:Point, n:int):void {
 if(n == 0) {
  g.moveTo(p1.x, p1.y)
  g.lineTo(p2.x, p2.y);
  return;
 }
 var p3:Point, p4:Point, p5:Point;
 //     p4
 //p1   /\   p2
 // ---/  \---
 //   p3  p5
 p3 = Point.interpolate(p2, p1, 1/3);
 p5 = Point.interpolate(p2, p1, 2/3);
 var p1_p3:Point = p3.subtract(p1);
 var angle:Number = Math.atan2(p1_p3.y, p1_p3.x)
 p4 = p3.add(Point.polar(p1_p3.length, angle + 1/3*Math.PI));
 kochCurve(g, p1, p3, n-1);
 kochCurve(g, p3, p4, n-1);
 kochCurve(g, p4, p5, n-1);
 kochCurve(g, p5, p2, n-1);
}

2007-07-17

3D的宇宙树

一个用Papervision 3D写的3D的宇宙树

World Tree in Papervision 3D and AS3

2007-07-15

After Effect CS3 的新功能

  • Shape Layers(图形层,可以轻易地创建和做动画的矢量图)
  • Puppet tool(如下图)

Powerful motion controls screenshot

  • Adobe Photoshop CS3 Extended integration(与 Photoshop CS3 Extended 的集成)
  • Tight integration with Adobe Flash CS3 Professional(与 Flash CS3 Professional 的无缝集成)
  • Per-character 3D text animation(可以给每一个字添加3D动画,如下图)

Per-character 3D text animation screenshot

  • Brainstorm(高级的特效预览与变更,如下图)

Brainstorm screenshot

  • Complete color management workflow(完整的颜色管理)
  • Adobe Clip Notes
  • Enhanced performance(提高了运行效率)
  • Video for mobile(为移动设备设计影片)

Production Premium CS3 发布了!

Production Premium CS3 包含了

售价$1699(好贵!)

新版的AE又来了!

详细请看http://www.adobe.com/products/creativesuite/production/?tab=whats-inside

AS3.0的动态语言特性(4) - 等号(==)

  1. AS3.0的动态语言特性(1) - 类型检查
  2. AS3.0的动态语言特性(2) - 变量声明的省略
  3. AS3.0的动态语言特性(3) - AS3.0的变量声明与效率

AS3.0的等号,知道的人很多。但真正知道的人却很少。

ECMA-262的等号的运算规则

x == y(x,y为一个值)返回truefalse根据以下的规则:

  1. 如果 Type(x) 不等于 Type(y), 跳到规则14。 (*Type(v)返回v的类型)
  2. 如果 Type(x) 未定义 ,返回 true。
  3. 如果 Type(x) 为null ,返回 true。
  4. 如果 Type(x) 不为 Number ,跳到规则11。
  5. 如果 x 为 NaN ,返回 false。
  6. 如果 y 为 NaN ,返回 false。
  7. 如果 x = y(数学上,数字的比较),返回 true。
  8. 如果 x 为 +0 并且 y 为 -0,返回 true。 (*在计算机内部,+0与-0是不一样的)
  9. 如果 x 为 -0 并且 y 为 +0 ,返回 true。
  10. 返回 false。
  11. 如果 Type(x) 为 String 并且 x 等 于 String(y) , 返回 true。否则返回 false。
  12. 如果 Type(x) 为 Boolean 并且 x 等 于 Boolean(y) , 返回 true。 否则返回 false。
  13. 如果 x,y指向相同的对象 返回 true。否则返回 false。
  14. 如果 x 未定 并且 y 为 null,返回 true。
  15. 如果 x 为 null 并且 y 未定义,返回 true。
  16. 如果 Type(x) 为 Number 并且 Type(y) 为 String ,返回 x == Number(y)。
  17. 如果 Type(x) 为 String 并且 Type(y) 为 Number ,返回 Number(x) == y。
  18. 如果 Type(x) 为 Boolean ,返回 Number(x) == y。
  19. 如果 Type(y) 为 Boolean ,返回 x == Number(y)。
  20. 如果 Type(x) 为 String 或 Number 并且 Type(y) 为 Object, 把 y 变成基本类型在比较。
  21. 如果 Type() 为 Object 并且 Type(y) 为 String 或 Number, 把 x 变成基本类型在比较。
  22. 返回 false。

等号的一般规则(数学定义的规则)

  • a==b <=> b==a
  • a==b, a==c => b==c
  • a===b => a==b
  • a != b => !(a==b)

等号的特殊规则

先来看下面的代码:

var foo:Object = 0;
if ("" == foo) {
    trace("foo is Empty String.");
}

上面的代码感觉是判断foo是不是空字符串。因为foo == 0,所以foo.toString() == "0"。因为""不等于"0" 所以 什么也不输出。

但实际上,因为Number("") == 0所以输出的是"foo is Empty String."

这是因为根据ECMAScript的定义,(字符串) == (数字) 的规则是Number(字符串) == (数字)

其他重要的规则:

  • NaN != NaN
  • null == undefined

2007-07-08

AS3.0的动态语言特性(3) - AS3.0的变量声明与效率

  1. AS3.0的动态语言特性(1) - 类型检查
  2. AS3.0的动态语言特性(2) - 变量声明的省略

变量声明有无和效率

首先创造一个 Date 对象,在调用 getTime() 10万次。

  • 变量没有明确声明:
date = new Date();
for (i=0; i<100000; i++)
   date.getTime()

执行大约用了470ms。

  • 变量明确声明:
date = new Date()
var dateVar = date  // 添加
for (i=0; i<100000; i++)
  dateVar.getTime()

执行大约用了340ms。快了38%

因为用var声明的为本地变量,所以能快速访问。

但不用var声明的为全局变量,访问速度较慢。

类型声明有无和效率

指定类型:

date = new Date()
var dateTyped:Date = date  // 指定类型
for (i=0; i<100000; i++)
  dateTyped.getTime()
 

执行大约用了300ms。比前面的340ms快了13%,比470ms快了56%

这是因为AS3.0支持类型(对dynamic的类用prototype添加的函数无效)。

变量声明的总结

如果把i也用var声明的话:

date = new Date()
var dateTyped:Date = date
for (var i=0; i<100000; i++)  // i也用var声明
 dateTyped.getTime()

执行大约用了20ms!比300ms快了1400%,比470ms快了2250%

再给i添加上类型:

date = new Date()
var dateTyped:Date = date
for (var i:int=0; i<100000; i++)  // 把i声明成int型
 dateTyped.getTime()

执行大约用了13ms。比20ms快了35%,300ms快了2208%,比470ms快了3515%

这是因为i调用了两次。

所以写代码最好:

  • 加上var
  • 加上类型

AS3.0的动态语言特性(2) - 变量声明的省略

AS3.0的动态语言特性(1) - 类型检查

去掉strict模式,AS3.0的自由度大大提高了。 但 ”With great power comes great responsibility”选择越大,风险也越大

不用var来初始化变量

不管是 Flash CS3 还是 Flex2 ,去掉strict模式后就可以不用var来初始化变量。比如以下代码就可以通过编译。


public class Foo {
 public function setMyGlobal(val:int):void {
  i = val;
 }
 public function printMyGlobal():void {
  trace(i);
 }
}

以下代码会正常工作。

var foo:Foo = new Foo();
foo.setMyGlobal(10);
foo.printMyGlobal(); // ->10

但不调用setMyGlobal(),直接调用printMyGlobal()的话,执行时,会弹出i未定义的错误。

var foo:Foo = new Foo();
foo.printMyGlobal(); // 执行时错误

这是因为没有在setMyGlobal()里初始化i


public function setMyGlobal(val:int):void {
 i = val;  // 最先执行这一行时初始化i。
}

不用var声明的变量的作用域

var foo1:Foo = new Foo();
var foo2:Foo = new Foo();
 
foo1.setMyGlobal(10);
foo2.printMyGlobal(); // ->10

foo1里设定的值,在foo2里也能参照。也就是说不用var声明的变量是在实例间共用的