使用 image lingo 制作模拟刮胡子的演示程序

4/7/2006来源:Director教程人气:9617

Director 8 相对于 director 7 有很多增量型的改动,其中对于 lingo 程序员来说,最引人注目的就是增加了相关的 image lingo 指令。有了它,我们可以做很多以前用 director 7 所无法做到的效果,例如你可以自己编写一些 transition 过渡效果,还有你还可以编写类似于 photoshop 的滤镜效果。这也进一步体现出 director 相对于 Flash 的优势所在--即:对于位图的强大处理能力。在这里我们将领略一下新增加的 image lingo 命令带来的强大功能。

有很多人在论坛上讨论 director 与 flash 孰优孰劣,无论是国内论坛还是国外讨论组,情况都是相同的。双方的拥护者都尽可能的说服对方自己喜欢的软件是最棒的,其实在很多情况下这种争论是没有任何意义的。我本人两种软件都使用,我喜欢用 flash 来做简单的动画角色,然后导入 director ,而不是象以前那样全部在 director 中做 film loop 动画。做动画方面, director 确实不如 flash, 但是我还是喜欢使用 lingo 来编写程序。所以我不会象一个真正的 flasher (\"闪客\")那样不停的发掘 flash 的潜力来做出一切效果(尽管有的效果做出来很勉强,或是效率太低,性能较差)。 最近我通过做一个剃须刀演示项目,进一步验证了 director 在处理点阵图像方面的确优于 flash。

其实这个项目很简单: 通过在网页中拖动剃须刀,将一个的人的面部胡须刮干净。
这个项目最开始的想法是用 flash 来做。我们的 flash 技术人员最开始的想法是,将这个人脸部胡须部分的照片图案(矩形区域),细致切分,然后将同一个人的脸部没有胡须的照片(为了达到头部图案完全吻合,我们是在同一张照片上通过 photoshop 做添加胡子的处理)同样分割为很多相同的小块,然后作为元素导入 flash。这样有胡须的部分分为很多小块,导入 flash ,然后相同的无胡须的部分也分为相同个数的小块导入 flash ,然后将对应的每一个小块做一个 MC.
这个 MC 的第一帧放置有胡须的切块图案,第二帧放置无胡须的切块图案,mc 的第一帧放置 stop action, 当鼠标 over 的时候,让这个 mc 跳动到第二帧没有胡须的小切块。这样,当用剃须刀做的 mc 替代鼠标后,当它滑动到这些MC(有胡须的小切块图案)的时候,他们就会跳到相应第二帧(也就是没有胡须的小切块图案),这样就可以完成刮胡子的演示了。
方法是很简单的: 但是实际做起来却出现了如下的问题。
1:通常这样的切图文件必须非常细,才可以满足客户的要求,然后切图越细致就意味在 flash 中要作更多的 mc 和 symbol。 这样不但增加了文件的大小,而且也使得文件运行特别慢。
2:由于这种方法制作的切图大小是开始定好的,如果希望将切块更加细分的话,你必须从新切图和导入。必须重复劳动。
3:这种方法制作 swf 文件通常比 director 制作的 dcr 文件大不少(至少是一倍)。

而采用 director 8 的 image lingo 指令,你可以完全的避免上述问题。

制作方法如下:
所需的素材:
一张没有刮胡子的照片位图,和一张同一个人刮完胡子的照片位图。(为了版权问题,我将脸部部分去掉,保留胡须部分的位图图案。)见图如下:

图形 1 face.jpg
图形 2 faceoff.jpg

 

接着我们开始介绍程序部分,这段程序非常的短小,核心部分的代码总共 6 行。然是为了理解这六行代码,你需要了解 director 8 新增加的 image lingo 的一个核心函数,这就是 copyPixels
copyPixels 的功能就是将位图数据从一个 image 复制到另一个 image。
现在任何一个 director 角色(member)都有一个 image 的属性,这是很多人忽略的地方。这个 image属性是内存中的一个图形对象的引用,而这个图形对象是角色成员的一个图形表示。角色成员可以是 位图,flash 角色,文字角色,甚至是舞台 stage. 我把刚刚导入的两个位图角色起名为 source (刮完胡子的照片位图 face.jpg)和 targer (未刮完胡子的照片位图 faceoff.jpg)

在 director 中角色分布图如下:

control + M 打开 director 中的消息窗口,输入
put member(\"source\").image
n <image:1d151c> -- 1d151c 就是该 image 对象在内存中的地址。

而 image 属性是对实际数据的一个引用。而 image 图形对象是角色成员在内存中的实际数据。
任何对 image 对象的改动都是对 cast 中相应的原始角色的改动。这一点要注意,除非 image 对象是你自己创建的而且和角色成员不相关联,否则必须注意不要意外改动的原始角色成员。
你可以调用 image() 函数来创建自己的对象。实例如下:
image (width, height, bitdepth)
thisImage = image (320,240,16)
你现在创建了一个宽为 320 pixel 高为 240 pixel ,位深为 16 bit 图形对象。

你可以用 copyPixels 函数来给图形对象添加数据。该函数的格式如下(这是本程序的关键):
targetImage.copyPixels(sourceImage, destinationRect, sourceRect, <parameters>)
该函数功能是通过目标图形对象调用 copyPixels 函数,将 源图形对象,从源图形对象的矩形区域 sourceRect 复制到 目标图形对象的矩形区域destinationRect。

以本程序为例子,我们的目的: 程序记录鼠标移动的轨迹,从鼠标滑动的点为左上角开始,记录一个虚拟的矩形区域,将这个矩形坐标(相对与该图形左上角为原点)记录下来。然后通过targetimage (就是我们这个程序的角色 \"target \"-未刮胡子的照片图案)调用 copyPixels 函数将 sourceimage (就是我们这个程序的角色 \"source \"-刮胡子后的照片图案)中鼠标滑动矩形区域的图形复制到相应的 targetimage 中,记住我们对 targetimage 角色的改动直接改动了 target 角色,所以我们必须有另外一个角色,它和 target 角色完全相同,但是名字不同,为的是在需要的时候恢复 target 角色的原貌。所以我们从新复制一下 target 角色,放在第 3 号角色,起名字为 \"s\"。下面会讲解为什么这样作。

现在开始制作:
1: 在第一帧的帧脚本 frame script 中写上
on exitframe me
 go the frame
end
目的是让播放停止在这个帧上。让 director 等待响应鼠标事件。

将 target 角色拖动到 score 中的第一帧的 6号通道(可以是任何通道,但是最好不要用 1,2 号通道,因为你有可能将来在这些地方放置底图。所以尽量将变动的角色放在稍微高通道中。这是个人习惯的问题)。鼠标右键单击这个角色选中 script 打开该 sPRite 的 sprite script 。
我们必须响应 exitfame 事件。

首先我们将定义一个属性(这是一个习惯性的写法)
就是在每个角色的 beginsprite 事件handle 中做初始化属性和某些全局变量的操作。
这部分代码是为了方便对大量 sprite(me.spritenum) 的调用而写的,其实在本程序中并不一定需要
property pMySprite
 on beginsprite me
 pMySprite = sprite(me.spritenum)
end

下面是真正的核心代码
通过在响应 exitframe handle 中处理 mouseDown 来复制位图,也就是当鼠标在图形上拖动的时候将鼠标滑过的位置的矩形小区域记录下来,然后从 source 角色中将相应矩形区域的位图部分复制到 target 角色部分相应的位图部分。

on exitframe me
 if (the stillDown) then - 当鼠标一直按下的时候,才开始复制
  thisPoint = the mouseLoc - point(pMySprite.left, pMySprite.top) - 将记录鼠标相对与角色左上角为原点的坐标
  top = thisPoint.locV
  left = thisPoint.locH
  sourceRect = rect (left, top, left + 10, top + 10) -- 定义一个虚拟的小矩形复制区域(从鼠标开始处计算),我们这里采用 10*10 的方块
  member(\"target\").image.copyPixels (member(\"source\").image, sourceRect, sourceRect)
-- 将从 \"source\" 角色中复制一个小块到 target 角色中相同坐标区域部分。
 end if
end

 

好了,所有关键程序部分都已经完成了。这里,我们可以简单的通过
sourceRect = rect (left, top, left + 10, top + 10) 这条语句来容易的改动复制区域的大小和形状, 这比起 flash 从新切割图片来说真是太方便了。
任何人只要有两张照片文件,都可以很容易的制作这个程序。似乎所有的程序都已经写完了。好像还有些问题,记得我在前面说过任何对图形角色 image 对象的修改都是对原角色成员的修改,我们复制完毕后,两张图形就完全一样了,这样原来的 target (就是未刮胡子的图案)就无法恢复原来的样子了,为了让这个程序可以反复的玩,我们在开始导入角色的时候,曾经将 target 复制为另一个相同的角色。名字是 \"s\".
现在我们在这个 director 程序中建立一个 movie script
在里面键入如下语句
on startmovie
member(\"s\").duplicate(2).member.name = \"target\"
-- 该语句很简单,就是将 member 角色 \"s\" 复制到 2 号 角色,然后起名字为 \"target\"
end

这样我们就恢复了 target 角色的本来面貌。
如下是全部角色,舞台,和 score 安排图:



图形 (cast.gif)


在这个程序中,通过使用 director 8 中清晰简捷的 image lingo 代码完成了 flash 做起来很麻烦的操作。这就是 director 在处理图像方面的优势所在。 Flash 在处理适量方面的确是有目共睹的,但是我希望大家能够更多的关注 director 对于位图的处理技术。在不同的场合采用最适合的技术这才是我真正要表达的意图。

我已经将该程序的 demo 放置在我的主页上,你可以通过输入这个网址来看,http://www.matrixfox.com/newface.htm
该网页需要用 shockwave 插件来观看,没有该插件的人请去 http://www.5dmedia.com 主页下载。
原程序代码的下载地址为 http://www.matrixfox.com/faceoff.zip
我希望和广大的 director 爱好共同交流 director 技术。我的 email : matrixfox@21cn.com