用Flash和Director实现简单的AI

软件世界

在Flash流行的今天,很多人已经可以用其内部的Action做出一定功能的应用程序动画,他们也时常想利用外部的一些程序来弥补Flash的不足。本文就是通过Flash与Director的交互控制,以实例介绍Director 8.5对Flash5的控制和简单的AI制作。文中涉及的AI(Artificial与Intelligence 人工智能)属于Expert级模式,该模式通过分层判断加上概率算法实现。

制作过程

本文使用一个婴儿图片,并对背景稍加装饰了下,我将Flash和Director分成两部分功能模块,以Director为主程序,Flash为扩展AI程序库。
思路:做一个会和人“交谈”的婴儿(下称“Flactor”),利用的AI范畴属于Expert专家模式判断,把婴儿的年龄和问题的判断程序加在Flash内,需要时通过Director主程序激活。

Flash部分

在Flash 5内新建一个文件,取名flactor_function.fla。
1.首先设置环境,Modify菜单下的Movie,设置Dimensions的width和height为50px×30px;设置同级菜单Scene的名称为flactor_function。
2.用Tools工具箱的“text tool”工具在主场景中央划出一块Text区,这时按“Ctrl+T”打开文本属性面板,设置成Dynamic Text,同时设置变量“myAge”。
3.按“Ctrl+E”返回主场景,然后新建一个Movieclip 取名为“age”,用于控制“Flactor”的年龄myAge,在MC内部第36帧的位置(3秒刷新一次)按F6插入关键帧,并按“Ctrl+Alt+A”写入Action:_parent.myAge++;
4.新建一个Movieclip “AI”,用来判断主程序呼叫的问题并产生答案。
5.在“AI”内部的第1帧插入关键帧并加入Action:stop 说明初始状态是停止的;接着,在第2帧也插入关键帧,并输入Action:
// ai expert mode
myAge=_parent.myAge;
if (qst ne "") {
asw="";
if (qst eq "hi") {
if (myAge<5) {
asw="a..ha......";
} else if (myAge<10) {
asw="Hello~.";
} else {
asw="What's up,my friend?";
}
} else if (qst eq "what's your name?" or qst eq "what is your name?") {
asw="I am flactor.";
} else if (qst eq "how old are you?") {
asw="I am "+myAge+".";
} else {
asw="... ...";
}
qst="";
}
// ai end
当这段程序被呼叫时。首先,获取到“Flactor”的年龄,根据问题变量qst的状态来产生几个分支,这个分支按照一定的概率排列先后顺序,例如“hi”一般放在前列;在判断问题的分支层的下层也可能有些特别处理,例如根据年龄的不同而说出不同的话来,这需要对myAge进行判断,甚至可以随机说出不同的话(Random和数组的应用)。
当准备好了模块,就可以放在主场景内实际测试了,按“Ctrl+L”打开库,把刚做好的“ai”和“age”从库中拉出并放入场景的适当位置,然后按“Ctrl+I”依次名“ai”和“age”((图1))。

图1
图1

6.按“Ctrl+Enter”测试,可以看到文本内年龄不断增长,这就Ok了。但为了确保程序的正常运行,我们还要在主场景第1帧加入一段初始化Action:
// initiation
if (not inited) {
inited=true;
myAge=0;
age.gotoAndPlay(1);
ai.gotoAndPlay(1);
ai.qst="";
ai.asw="";
}
// initiation end
到这里,Flash部分已经完成。

Director部分

新建一个文件,取名为“Flactor.dir”。
设置环境,按“Ctrl+Alt+S”打开Property Inspector,设置长宽为500×330。
1.首先,设计好背景,并排列好布局,这时,按“Ctrl+7”打开“Tool Palette”,用Field工具做两个文本区分别放在场景上下,上面的要拉大一些,并在Property Inspector内的field窗口内的“formatting”选项选择“fixed”,并激活“Wrap”,最后设置Information窗口内的member name为“spr_answer”;第二个文本用于用户输入问题,所以field窗口内的“editable”要选中,并给与member name为“spr_question”。
2.文本框做好之后,还需要一个按钮。用tool palette的Button工具画一个按钮,并写入按钮文字为“Ask”,member name为“btnAsk”((图2))。

图2
图2

3.感性的作品已经完成,下面调用它的功能。按“Ctrl+3”打开Cast演员表,选择ChooseCase内的new case,产生一个新的演员表叫做“Box”,把和程序无关的东西全扔(拖动)进去。
4.在Internal cast演员表内,右击鼠标,选择“Import”,把刚才做好的flactor_function.swf导入进来,并放置在场景中((图3))。
图3
图3

5.右击按钮“btnAsk”,选择script,并输入lingo:
on mouseup me
--get question
question = member("spr_question").text
--check result
if not(question = "" or voidP(question)) then
sprite (18).setVariable("_root.ai.qst", question)
sprite (18).tellTarget("_root.ai")
sprite (18).gotoFrame(2)
sprite (18).endTellTarget()
answer=""
repeat while answer = "" or voidP(answer)
answer = sprite (18).getVariable("_root.ai.asw")
end repeat
member("spr_answer").text = answer
sprite (18).tellTarget("_root.ai")
sprite (18).gotoFrame(1)
sprite (18).endTellTarget()
end if
--clear question
member("spr_question").text=""
end
6.当用户输入问题并按下按钮时,便激活这段代码。首先获取spr_question的值并通过setVariable语句传递给Flash的ai.qst变量,并激活Flash内的判断模块(root.ai.gotoandstop(2);)。当Flash进行判断的时候,Director处于等待状态,直到用GetVariable获取的Answer的值不为空时才继续运行,当得到了需要的值,便会在第一时间把结果传递给spr_answer显示出来,并使得Flash的AI复位,等待用户下次输入。
到此为止,主要的部分大体完成。为了确保正常运行,我们还需要写一段Lingo进行初始化,按“Ctrl+0”打开script window,写入movie script:
on prepareMovie
member("spr_answer").text=""
member("spr_question").text=""
end
这段代码在每次程序运行前执行,作用是把问题答案文本框清空。
7.最后,我们可以按“Ctrl+Alt+P”测试场景了,这时,你可以看到一个可以跟你对话的Flash与Director相结合的婴儿“诞生了”……
本文使用的所有源文件下载地址为http://alldemons.51.net/ds_flash/flactor.zip