MSAgent
开篇:
可能 MSAgent 这个名字你不清楚,但如果提起 Office 助手我想在这个目前 MicroSoft 独霸天下的电脑世界应该鲜有人不知道,本文就是交给你如何在网页中调用这个在线尤物。
入题:
一、抛砖引玉
首先,我们先来看一下一个最简单的效果:
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID = "Merlin";
var AgentACS = "merlin.acs";
MSAgent.Connected = true;
MSAgent.Characters.Load(AgentID,AgentACS);
Agent = MSAgent.Characters.Character(AgentID);
Agent.Show();
</script>
看到没有,如果顺利的话,你的屏幕上会出现一个很 Q 的卡通魔法师。对,这就是传说中的 MSAgent !下面讲解一下各个部分的作用:
AgentID 内部索引字串,由用户定义;
AgentACS 所调用的角色文件,可以为浏览者本地或远程文件,后面会有单独的部分说明。
MSAgent.Connected 建立连接;
MSAgent.Characters.Load 读取角色;
MSAgent.Characters.Character 返回角色对象;
Agent.Show 显示角色;
好了,我现在已经把 MSAgent 带到你面前了。什么?什么东西都没看到?只有浏览器的报错!没关系,在后面的文章里,我也会告诉你如何才能看到他,当然,这个看到指的是所有浏览你网页的人!
二、伶牙俐齿
下面,我们就让他来做一点实际的东西 —— 说话!还是接续上例:
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID = "Merlin";
var AgentACS = "merlin.acs";
MSAgent.Connected = true;
MSAgent.Characters.Load(AgentID,AgentACS);
Agent = MSAgent.Characters.Character(AgentID);
Agent.LanguageID = 0x0409;
Agent.Show();
Agent.Speak("Hello Everybody, I am Merlin!");
Agent.Think("What shall I do the next?");
</script>
Merlin 说话了(如果要读出声音来的话,需要客户端在 MicroSoft 的网站上下载并安装相应的语音引擎)!这里涉及到这么几个新的东西:
Agent.LanguageID 声明语言种类,0x0409是英文的编号(有关语言编号请参考 www.microsoft.com/globaldev/reference/oslocversion.mspx ),目前如果没有这个声明,或声明为错误的语种,则语言只是一次性完全显示。
Agent.Speak() 和 Agent.Think() 是 MSAgent 的两个语言表达显示行为,只有显示图形的区别。
了解了这些功能,是不是正在陶醉呀?别急,还有更好的东西呢!
三、活灵活现
总是看着一个呆头呆脑的东西一动不动,即使是很 Q ,也会有感到多少的厌烦,下面我们就让他动起来。
这个例子由于调用的是网络文件,所以会慢一点,请耐心等待一下!
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID = "Merlin";
var AgentACS = "http://agent.microsoft.com/agent2/chars/merlin/merlin.acf";
var AgentStates = "Showing, Hiding, Speaking, Moving";
var AgentAnimations = "GetAttention, GetAttentionReturn, Congratulate, Acknowledge, Read, WriteContinued, WriteReturn, wave";
var AgentLoadRequest, AgentStateRequest, AgentAnimationRequest;
MSAgent.Connected = true;
AgentLoadRequest = MSAgent.Characters.Load(AgentID,AgentACS);
Agent = MSAgent.Characters.Character(AgentID);
Agent.LanguageID = 0x0409;
AgentStateRequest = Agent.get("state", AgentStates);
AgentAnimationRequest = Agent.get("animation", AgentAnimations);
Agent.Show();
Agent.MoveTo(400,300);
Agent.Play("GetAttention");
Agent.Play("GetAttentionReturn");
Agent.speak("Hi, may I have your attention, please?");
Agent.Play("Congratulate");
Agent.speak("So nice to meet you!");
Agent.Play("Think");
Agent.speak("How do think about me?");
Agent.Play("Acknowledge");
Agent.Speak("It's very cool, ya?");
Agent.Play("Read");
Agent.Play("WriteContinued");
Agent.Play("WriteReturn");
Agent.Speak("Oh, I have lots of things to do, see you !");
Agent.Play("wave");
Agent.Speak("Bye-bye!");
Agent.Hide();
</script>
看到没有?其实只要你善于调动它的积极性,MSAgent 也蛮活泼的!信息观察,不难发现,原来让 MSAgent 动起来,也不过就这么简单:
Agent.MoveTo(x, y) 是角色移动到指定的坐标;
Agent.Play(action) 命令角色做某个动作,动作列表见: msdn.microsoft.com/library/default.asp?url=/library/en-us/msagent/deschar_3pgy.asp (这里需要说明一下,不是所有的角色都支持这些动作的,处理方法后面会有说明!)
Agent.Hide() 隐藏角色(不是释放角色,通过 Agent.Show() 可以再次显示)
Agent.get(Request, list) 预载相关 MSAgent 动画数据,MSAgent人物数据文件支持单结构角色文件(.acs,角色数据与动画数据存于同一个文件),也支持分离结构角色文件(.acf,角色数据存于.acf中,动画数据存于.aca中)。基于本地硬盘和网络调用均可采用这两种模式,当调用网络 acf 文件时,由于角色数据与动画数据分别下载,所以需要预载相关动画数据,使用 acs 文件(一般没有本地 acf 文件的可能性),不需要预载。
AgentLoadRequest, AgentLoadRequest 和 AgentAnimationRequest 这三个参数本例并没有实际用到,返回应相关操作的状态对象(相当于 readystatus 属性),在调用网络 acf 文件时有比较实际的用途,这个会在后面说明!
四、改头换面
MSAgent = Merlin ? 错!MSAgent 是指一系列动画人物的总称,最常见的 office 中的那些活宝,各位应该都熟悉吧?先来看看下面的这个例子:
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID, AgentACS;
var AgentLoad = false;
function LoadAgent(NewAgent) {
if(AgentLoad) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
}
AgentID = NewAgent;
AgentACS = "http://agent.microsoft.com/agent2/chars/" + NewAgent + "/" + NewAgent + ".acf";
MSAgent.Connected = true;
MSAgent.Characters.Load(AgentID, AgentACS);
AgentLoad = true;
Agent = MSAgent.Characters.Character(AgentID);
Agent.get("state", "Showing, Hiding");
Agent.MoveTo(400, 300);
Agent.Show();
return;
}
LoadAgent("Merlin");
</script>
MSAgent Select :
<SELECT name="Agent_select" onchange="LoadAgent(this[this.selectedIndex].text)">
<OPTION>Merlin</OPTION>
<OPTION>Peedy</OPTION>
<OPTION>Genie</OPTION>
<OPTION>Robby</OPTION>
</SELECT>
看到没有? 原来 MSAgent 还有这么多可爱的造型呢!上面的例程中,我定义了一个读取角色的函数 LoadAgent ,通过这个函数更换角色,其中的大部分的功能在前面的章节中已经介绍了,这里仅仅说明一下,新的方法:
MSAgent.Characters.Unload() 卸载角色,其中 AgentID ,必须是 MSAgent.Characters.Load() 中声明过的
Agent.MoveTo() 这个方法上一节中介绍过,但是如果把它放在 Agent.Show() ,则相当于定义角色的出现位置
其实,MSAgent 绝对不仅仅是那么多,但是 MicroSoft 的官方网站上只提供了那么多……怎么办?可以从他的网站上连接角色,当然可可以从你的网站上呀!你可以在这里 www.microsoft.com/msagent/downloads/user.asp 下载官方角色以及语音引擎(可惜没有中文);当然,如果你有兴趣的话也可以开发一个属于自己的 Agent ,相关开发工具 www.microsoft.com/msagent/downloads/developer.asp ,网上也有很多高手做好的动画人物,读者可以搜索一下。
安装后角色文件存放在 %WINDOWS%\msagent\chars 目录下的 *.acs 文件,上传到服务器上,直接引用到那个路径就可以了!(你也可以在你的硬盘里搜索一下 *.acs 会有不小的收获呦)这里要说明一下,请自行更改程序中标明网络路径的相关语句,且注意扩展名是 .acs !
如果要让本机支持相应的 MSAgent ,也就是说不用网络调用,只要把 *.acs 文件 copy 到 %WINDOWS%\msagent\chars 目录就可以了,但如果是 *.exe 的安装文件,则会自动把角色文件放置到相应的路径下。
五、排难解错
能否显示 MSAgent 的关键在于是否安装了 MSAgent 的核心组件( Microsoft Agent core components - activex.microsoft.com/activex/controls/agent2/MSagent.exe ),但是如何让这一被动行为变为主动呢?可以用下面两种方法:
方法一:
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F" CodeBase="http://activex.microsoft.com/activex/controls/agent2/MSagent.exe#VERSION=2,0,0,0"></object>
特点:自动下载组件并安装,比较方便,但会下载的等待时间不会提示,在网速慢的时候会以为页免死掉,且不是很方便控制。
方法二:
程序代码:
<script language="javascript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
function Agent_load_error(){
alert("To make the MSAgent available, /nplease install Microsoft Agent core components first !");
window.open("http://activex.microsoft.com/activex/controls/agent2/MSagent.exe");
return;
}
</script>
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F" onerror="Agent_load_error()"></object>
特点:方便出错控制,用户控制下载,但是不能当时显示,需要安装后再次刷新页面。
使用哪种方法就属于见仁见智了,但是最不明智的方法就是两种方法一起上,实践证明 CodeBase 会先于 onerror 生效!
同理,如果想要角色发声,只要在控件声明中加上如下的 CodeBase 就可以了:
程序代码:
<Object style="visibility:hidden" id="L&HTruVoice" ClassID="CLSID:B8F2846E-CE36-11D0-AC83-00C04FD97575" CodeBase="http://activex.microsoft.com/activex/controls/agent2/tv_enua.exe#VERSION=6,0,0,0"></Object>
以上是 MicroSoft 的 lernout & Hauspie TruVoice 朗读引擎,我所引用的是美国英语的引擎文件,其他语种请见 www.microsoft.com/msagent/downloads/user.asp#tts ,可惜,还是没有中文引擎……
不管怎么说,调用本地角色也比网络角色速度上要快得多,但是你如何预知客户端是否安装了该角色呢?看看下面的例子:
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID, AgentACS;
var AgentLoad = false;
function LoadAgent(NewAgent) {
var remote = false;
if(AgentLoad) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
}
AgentID = NewAgent;
AgentACS = NewAgent + ".acs";
MSAgent.Connected = true;
try {
MSAgent.Characters.Load(AgentID, AgentACS);
agent_exist.innerText = "Local MSAgent load successfully!";
} catch(e) {
AgentACS = "http://agent.microsoft.com/agent2/chars/" + NewAgent + "/" + NewAgent + ".acf";
remote = true;
MSAgent.Characters.Load(AgentID, AgentACS);
agent_exist.innerText = "Local MSAgent load unsuccessfully, as a advice, you'd better to download the charactor file to your hard disk!";
}
AgentLoad = true;
Agent = MSAgent.Characters.Character(AgentID);
if(remote) Agent.get("state", "Showing, Hiding");
Agent.MoveTo(400, 300);
Agent.Show();
return;
}
window.onload = function(){LoadAgent("Merlin");};
</script>
MSAgent Select :
<SELECT name="Agent_select" onchange="LoadAgent(this[this.selectedIndex].text)">
<OPTION>Merlin</OPTION>
<OPTION>Peedy</OPTION>
<OPTION>Genie</OPTION>
<OPTION>Robby</OPTION>
</SELECT>
<br /><br />
Load Status: <span id="agent_exist"></span>
通过设置错误捕获,可以方便的找到调用 MSAgent 的最佳方式,当然,你还可以通过 DHTML 加上相应的角色下载链接,并指导用户将 *.acs 文件 copy 到相应目录(%WINDOWS%\msagent\chars)或直接安装 *.exe 的角色安装文件以方便下次浏览,本文仅仅是为你提供一个思路,具体实践还是自己发挥吧!
六、事件响应
像所有 OOP 一样,MSAgent 也设置有相应的事件响应,看看下面的例子,试试在角色或任务栏的图标上点击鼠标(单/双击),你也可以移动一下角色,看看它有什么反应:
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<Script Language="JavaScript" For="MSAgent" Event="Click(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(Button==1 && Agent.Visible) {
if(remote) {
Agent.get("state", "Speaking");
Agent.get("animation", "Acknowledge, Pleased");
}
Agent.Play("Acknowledge");
Agent.Speak("Yes sir! " + CharacterID + " is right here!");
Agent.Play("Pleased")
Agent.Speak("What can I do for you?");
} else if(Button==4097) {
Agent.Visible?Agent.Hide():Agent.show();
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DblClick(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(Button==1 || Button==4097) {
Agent.StopAll();
if (!Agent.HasOtherClients) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
AgentLoad = false;
}
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Move(CharacterID, X, Y, Cause)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(Cause == 1) {
if(remote) {
Agent.get("state", "Moving, Speaking");
Agent.get("animation", "Confused, RestPose");
}
Agent.MoveTo(400, 300);
Agent.Play("Confused");
Agent.Speak("Don't move me OK?");
Agent.Play("RestPose");
}
</Script>
<Script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID, AgentACS;
var AgentLoad = false;
var remote = false;
function LoadAgent(NewAgent) {
if(AgentLoad) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
}
AgentID = NewAgent;
AgentACS = NewAgent + ".acs";
MSAgent.Connected = true;
try {
MSAgent.Characters.Load(AgentID, AgentACS);
} catch(e) {
AgentACS = "http://agent.microsoft.com/agent2/chars/" + NewAgent + "/" + NewAgent + ".acf";
remote = true;
MSAgent.Characters.Load(AgentID, AgentACS);
if(confirm("Cannot find the MSAgent charactor file on your hard disk! \nWould you like to download the MSAgent charactor file for the next show?"))
window.open("http://www.msagentring.org/download.asp?char="+NewAgent.toLowerCase(),"_blank","top=2000px");
}
AgentLoad = true;
Agent = MSAgent.Characters.Character(AgentID);
Agent.LanguageID = 0x0409;
if(remote) Agent.get("state", "Showing, Hiding");
Agent.MoveTo(400, 300);
Agent.Show();
return;
}
LoadAgent("Merlin");
</Script>
MSAgent Select :
<SELECT name="Agent_select" onchange="LoadAgent(this[this.selectedIndex].text)">
<OPTION>Merlin</OPTION>
<OPTION>Peedy</OPTION>
<OPTION>Genie</OPTION>
<OPTION>Robby</OPTION>
</SELECT>
是不是感觉交互性强了许多?我们来看一下事件处理的声明方法:
<Script Language="JavaScript" For="MSAgent_Object" Event="Event_Name()">
//code...
</Script>
熟悉一点 JS 编程的应该不会陌生这种声明方式,也就是对某一对象某一事件的单独处理的声明方法,但是如果是该成 MSAgent_Object.Event_Name = function() {//code...} 的事件处理声明是不可以的!(the only way to do this)
如果是采用网络调用的话,如果向用户通知相应的调用进度呢?
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<Script Language="JavaScript" For="MSAgent" Event="RequestStart(RequestObject)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
switch (RequestObject) {
case AgentLoadRequest :
window.status = "Loading MSAgent File From Internet For " + AgentID + " ...";
break;
case AgentStateRequest :
window.status = "Loading MSAgent State From Internet For " + AgentID + " ...";
break;
case AgentAnimationRequest :
window.status = "Loading MSAgent Animation From Internet For " + AgentID + " ...";
break;
default:
break;
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="RequestComplete(RequestObject)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
switch (RequestObject) {
case AgentLoadRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent File For " + AgentID + " Has Been Loaded Successfully !";
} else {
window.status = "Cannot Load MSAgent File For " + AgentID + " From " + AgentACS + " !";
}
break;
case AgentStateRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent State For " + AgentID + " Has Been Loaded Successfully !";
} else {
window.status = "Cannot Load MSAgent State For " + AgentID + " From " + AgentACS + " !";
}
break;
break;
case AgentAnimationRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent Animation For " + AgentID + " Has Been Loaded Successfully !";
} else {
window.status = "Cannot Load MSAgent Animation For " + AgentID + " From " + AgentACS + " !";
}
break;
break;
default:
window.status = "";
break;
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DragStart(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
cur_x = X - Agent.width/2;
cur_y = Y - Agent.height/2;
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DragComplete(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(remote) {
AgentStateRequest = Agent.get("state", "Moving, Speaking");
AgentAnimationRequest = Agent.get("animation", "Confused, RestPose");
}
Agent.MoveTo(cur_x, cur_y);
Agent.Play("Confused");
Agent.Speak("Don't move me OK?");
Agent.Play("RestPose");
</Script>
<Script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID, AgentACS;
var AgentLoad = false;
var remote = false;
var cur_x, cur_y;
var AgentLoadRequest, AgentStateRequest, AgentAnimationRequest;
function LoadAgent(NewAgent) {
if(AgentLoad) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
}
AgentID = NewAgent;
AgentACS = NewAgent + ".acs";
MSAgent.Connected = true;
try {
AgentLoadRequest = MSAgent.Characters.Load(AgentID, AgentACS);
} catch(e) {
AgentACS = "http://agent.microsoft.com/agent2/chars/" + NewAgent + "/" + NewAgent + ".acf";
remote = true;
AgentLoadRequest = MSAgent.Characters.Load(AgentID, AgentACS);
if(confirm("Cannot find the MSAgent charactor file on your hard disk! \nWould you like to download the MSAgent charactor file for the next show?"))
window.open("http://www.msagentring.org/download.asp?char="+NewAgent.toLowerCase(),"_blank","top=2000px");
}
AgentLoad = true;
Agent = MSAgent.Characters.Character(AgentID);
Agent.LanguageID = 0x0409;
if(remote) {
AgentStateRequest = Agent.get("state", "Showing, Thinking, Hiding");
AgentAnimationRequest = Agent.get("animation", "GetAttention, GetAttentionContinued, GetAttentionReturn");
}
Agent.MoveTo(400, 300);
Agent.Show();
Agent.Play("GetAttention");
Agent.Play("GetAttentionContinued");
Agent.Play("GetAttentionReturn");
Agent.speak("Hi, I am " + NewAgent + "!");
Agent.think("Oh so bad, I just wanna take a nap...");
return;
}
LoadAgent("Merlin");
</Script>
MSAgent Select :
<SELECT name="Agent_select" onchange="LoadAgent(this[this.selectedIndex].text)">
<OPTION>Merlin</OPTION>
<OPTION>Peedy</OPTION>
<OPTION>Genie</OPTION>
<OPTION>Robby</OPTION>
</SELECT>
注意到窗口底部状态栏的显示了吗?虽然无法获取具体的下载进度,但是至少也可以让浏览者知道角色的动作为什么会有停顿(这个停顿只在某动画第一次调用的时候出现,调用后该动画会被缓存)。
更多的事件说明请参看 msdn.microsoft.com/library/en-us/msagent/paface_2xet.asp 但是浏览器所调用的 MSAgeng 对象并不是所有的事件都支持。
七、我的菜单:
右键点击角色是不是会弹出一个菜单?什么,只有 Hide 一项?想不想定义一个个性的菜单呢?
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<Script Language="JavaScript" For="MSAgent" Event="Command(UserInput)">
switch(UserInput.Name) {
case "INTRO" :
Agent.Play("Explain");
Agent.Speak("My name is " + AgentID + ", I think I'm the best one!");
break;
case "AUTHOR":
Agent.Play("Announce");
Agent.Speak("Windy_sk <windy_sk@126.com> wrote the program, I think he's great! (^o^)");
break;
case "SAYTIME":
Agent.Play("Suggest");
Agent.Speak("It is now " + (new Date()) + "!");
break;
case "FLY":
Agent.MoveTo(Math.round(Math.random() * screen.width), Math.round(Math.random() * screen.height));
break;
case "STOP":
Agent.StopAll();
Agent.Play("RestPose");
break;
default:
break;
}
</Script>
<script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID, AgentACS;
var AgentLoad = false;
function LoadAgent(NewAgent) {
var remote = false;
if(AgentLoad) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
}
AgentID = NewAgent;
AgentACS = NewAgent + ".acs";
MSAgent.Connected = true;
try {
MSAgent.Characters.Load(AgentID, AgentACS);
window.status = "Local MSAgent load successfully!";
} catch(e) {
AgentACS = "http://agent.microsoft.com/agent2/chars/" + NewAgent + "/" + NewAgent + ".acf";
remote = true;
MSAgent.Characters.Load(AgentID, AgentACS);
window.status = "Local MSAgent load unsuccessfully, as a advice, you'd better to download the charactor file to your local disk!";
}
AgentLoad = true;
Agent = MSAgent.Characters.Character(AgentID);
Agent.LanguageID = 0x0409;
Agent.Commands.RemoveAll();
Agent.Commands.Visible = true;
Agent.Commands.Caption = "MSAgent's Menu - by windy_sk";
Agent.Commands.Add("INTRO", "Introduce Yourself", "Introduce yourself");
Agent.Commands.Add("AUTHOR", "Who Write The Program", "Who Write The Program");
Agent.Commands.Add("SAYTIME", "What Time Is It Now", "What Time Is It Now");
Agent.Commands.Add("FLY", "Can You Fly", "Can You Fly");
Agent.Commands.Add("STOP", "Stop All Actions", "Stop All Actions");
if(remote) {
Agent.get("state", "Showing, Hiding");
Agent.get("animation", "Explain, Announce, Suggest");
}
Agent.MoveTo(400, 300);
Agent.Show();
return;
}
LoadAgent("Merlin");
</script>
MSAgent Select :
<SELECT name="Agent_select" onchange="LoadAgent(this[this.selectedIndex].text)">
<OPTION>Merlin</OPTION>
<OPTION>Peedy</OPTION>
<OPTION>Genie</OPTION>
<OPTION>Robby</OPTION>
</SELECT>
个性菜单也是通过对象事件驱动的,这一点相信已经看懂了上一节的读者比较容易理解,相关网页请见 msdn.microsoft.com/library/en-us/msagent/pacontrol_8kfe.asp
Agent.Commands.Add 的三个属性分别为:内部索引标识、显示文字和语音表示,前两个参数比较容易理解,关键是第三个参数“语音表示”,对用户可以通过语音来控制 MSAgent !
你需要首先下载 MicroSoft 语音识别引擎 activex.microsoft.com/activex/controls/agent2/actcnc.exe (目前只支持美国英语),下面介绍一下语音参数的句法:
Agent.Commands.Add("SAYTIME", "What Time Is It Now", "What Time Is It Now" 中 "What Time Is It Now" 是它的语音表示,但是必须要完全读出这几个单词才可以识别吗?如果要是问时间的话,我可以说 What Time , Tell me the time 或者直接只说 time ,但是如何让程序识别这些话为统一目的呢? 可以这样写:[(What|Tell me the)] Time [is it] [Now] [please] ,熟悉一点正则的读者应该不难理解,[] 表示可选项, () 规定范围, | 表示逻辑或
单纯这样还不够,还要在 <Script Language="JavaScript" For="MSAgent" Event="Command(UserInput)"> 加上相应的声音处理:
程序代码:
<Script Language="JavaScript" For="MSAgent" Event="Command(UserInput)">
var BadConfidence = 10;
if (UserInput.Confidence <= -40){
alert("Bad Recognition!");
} else if ((UserInput.Alt1Name != "") && (Math.abs(Math.abs(UserInput.Alt1Confidence) - Math.abs(UserInput.Confidence)) < BadConfidence)) {
alert("Bad Confidence - too close to another command !");
} else if ((UserInput.Alt2Name != "") && (Math.abs(Math.abs(UserInput.Alt1Confidence) - Math.abs(UserInput.Confidence)) < BadConfidence)) {
alert("Bad Confidence - too close to another command !");
} else {
switch(UserInput.Name) {
case "ACO" :
MSAgent.PropertySheet.Visible = true;
break;
case "READ":
Agent_Show("Read");
Agent.Speak(show.value);
break;
case "SAYTIME":
Agent_Show("Suggest");
Agent.Speak("It is now " + (new Date()) + "!");
break;
case "INTRO" :
Agent_Show("Explain");
Agent.Speak("My name is " + AgentID + ", I think I'm the best one!");
break;
case "AUTHOR":
Agent_Show("Announce");
Agent.Speak("Windy_sk <windy_sk@126.com> wrote the program, I think he's great! (^o^)");
break;
case "FLY":
Agent.MoveTo(Math.round(Math.random() * screen.width - Agent.width), Math.round(Math.random() * screen.height - Agent.height));
break;
case "STOP":
Agent.StopAll();
Agent_Show("RestPose");
break;
default:
break;
}
}
</Script>
else 语句上面的部分是对用户的语音输入作判断,相关参数意义请见这里:http://msdn.microsoft.com/library/en-us/dnexpvb/html/usingmsagentcontrolevents.asp
有关 Command 对象的其他方法,请见 msdn.microsoft.com/library/en-us/dnexpvb/html/workingwithcommands.asp
八、归纳总结:
主要涉及到的基本方法都已经讲过了,是不是对 MSAgent 又有了一个新的认识?感觉现在写程序的话缺少的仅仅是创意了……
下面,我们就把上面所了解到的东西做一个归纳总结性质的实践,Charactors From Office 是从硬盘上搜索出的 *.acs 文件 copy 到 %windows%\MSAgent\Chars 目录下的角色文件,读者自己搜索添加吧,里面的功能有一些前文没有涉及到的,读者可以研究一下:
程序代码:
<style>
*{font-size: 12px}
</style>
<Object style="visibility:hidden" id="MSAgent" ClassID="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F" CodeBase="http://activex.microsoft.com/activex/controls/agent2/MSagent.exe#VERSION=2,0,0,0"></Object>
<Object style="visibility:hidden" id="L&HTruVoice" ClassID="CLSID:B8F2846E-CE36-11D0-AC83-00C04FD97575" CodeBase="http://activex.microsoft.com/activex/controls/agent2/tv_enua.exe#VERSION=6,0,0,0"></Object>
<Script Language="JavaScript" For="MSAgent" Event="RequestStart(RequestObject)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
switch (RequestObject) {
case AgentLoadRequest :
window.status = "Loading MSAgent File From Internet For " + AgentID + " ...";
break;
case AgentStateRequest :
window.status = "Loading MSAgent State From Internet For " + AgentID + " ...";
break;
case AgentAnimationRequest :
window.status = "Loading MSAgent Animation From Internet For " + AgentID + " ...";
break;
default:
break;
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="RequestComplete(RequestObject)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
switch (RequestObject) {
case AgentLoadRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent File For " + AgentID + " Has Been Loaded Successfully !";
if(confirm("Cannot find the MSAgent charactor file on your hard disk! \nWould you like to download the MSAgent charactor file for the next show?"))
window.open("http://www.msagentring.org/download.asp?char="+NewAgent.toLowerCase(),"_blank","top=2000px");
} else {
window.status = "Cannot Load MSAgent File For " + AgentID + " From " + AgentACS + " !";
alert("Cannot find MSAgent file from local disk or internet!");
AgentLoad = false;
}
break;
case AgentStateRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent State For " + AgentID + " Has Been Loaded Successfully !";
} else {
window.status = "Cannot Load MSAgent State For " + AgentID + " From " + AgentACS + " !";
}
break;
break;
case AgentAnimationRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent Animation For " + AgentID + " Has Been Loaded Successfully !";
} else {
window.status = "Cannot Load MSAgent Animation For " + AgentID + " From " + AgentACS + " !";
}
break;
break;
default:
window.status = "";
break;
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Click(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(Button==1 && Agent.Visible) {
Agent.Stop();
Agent_Show("Acknowledge", "Yes sir! " + CharacterID + " is right here!");
Agent_Show("Pleased", "What can I do for you?");
} else if(Button==4097) {
Agent.Visible?Agent.Hide():Agent.show();
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DblClick(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(Button==1 || Button==4097) {
Agent.StopAll();
if (!Agent.HasOtherClients) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
AgentLoad = false;
}
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Move(CharacterID, X, Y, Cause)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var rnd_words = new Array();
rnd_words.push("Ha, I am the king of screen!");
rnd_words.push("It's good day to fly!");
rnd_words.push("Ah, your boss is on your back!");
rnd_words.push("Oh, it's fruit time, do you want an apple?");
rnd_words.push("How do you think about me?");
rnd_words.push("Hey guy, have a rest!");
rnd_words.push("Pretty girl everywhere, single me over there...");
rnd_words.push("Hi, don't you think I like neo in Matrix?");
rnd_words.push("If you think it, you will make it!");
rnd_words.push("I am so lonely, together with me, come on!");
if(Cause==2) {
Agent_Show("random", rnd_words[GetRandomNum(0, rnd_words.length-1)]);
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DragStart(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
cur_x = X - Agent.width/2;
cur_y = Y - Agent.height/2;
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DragComplete(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
Agent.Stop();
Agent_Show("Confused", "Don't move me OK?", "RestPose");
Agent.MoveTo(cur_x, cur_y);
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Command(UserInput)">
var BadConfidence = 10;
if (UserInput.Confidence <= -40){
alert("Bad Recognition!");
} else if ((UserInput.Alt1Name != "") && (Math.abs(Math.abs(UserInput.Alt1Confidence) - Math.abs(UserInput.Confidence)) < BadConfidence)) {
alert("Bad Confidence - too close to another command !");
} else if ((UserInput.Alt2Name != "") && (Math.abs(Math.abs(UserInput.Alt1Confidence) - Math.abs(UserInput.Confidence)) < BadConfidence)) {
alert("Bad Confidence - too close to another command !");
} else {
switch(UserInput.Name) {
case "ACO" :
MSAgent.PropertySheet.Visible = true;
break;
case "READ":
Agent_Show("Read");
Agent.Speak(show.value);
break;
case "SAYTIME":
Agent_Show("Suggest");
Agent.Speak("It is now " + (new Date()) + "!");
break;
case "INTRO" :
Agent_Show("Explain");
Agent.Speak("My name is " + AgentID + ", I think I'm the best one!");
break;
case "AUTHOR":
Agent_Show("Announce");
Agent.Speak("Windy_sk <windy_sk@126.com> wrote the program, I think he's great! (^o^)");
break;
case "FLY":
Agent.MoveTo(Math.round(Math.random() * screen.width - Agent.width), Math.round(Math.random() * screen.height - Agent.height));
break;
case "STOP":
Agent.StopAll();
Agent_Show("RestPose");
break;
default:
break;
}
}
</Script>
<Script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
function reportError(msg,url,line) {
var str = "You have found an error as below: \n\n";
str += "Err: " + msg + " on line: " + line;
alert(str);
return true;
}
window.onerror = reportError;
var Agent = null;
var AgentID, AgentACS;
var AgentLoad = false;
var AgentLoadRequest, AgentStateRequest, AgentAnimationRequest;
var AgentStates = "GesturingDown, GesturingLeft, GesturingRight, GesturingUp, Hearing, Hiding, IdlingLevel1, IdlingLevel2, IdlingLevel3, Listening, MovingDown, MovingLeft, MovingRight, MovingUp, Showing, Speaking";
var AgentAnimations = ["Acknowledge", "Alert", "Announce", "Blink", "Confused", "Congratulate", "Congratulate_2", "Decline", "DoMagic1", "DoMagic2", "DontRecognize", "Explain", "GestureDown", "GestureLeft", "GestureRight", "GestureUp", "GetAttention", "GetAttentionContinued", "GetAttentionReturn", "Greet", "Hearing_1", "Hearing_2", "Hearing_3", "Hearing_4", "Hide", "Idle1_1", "Idle1_2", "Idle1_3", "Idle1_4", "Idle2_1", "Idle2_2", "Idle3_1", "Idle3_2", "LookDown", "LookLeft", "LookRight", "LookUp", "MoveDown", "MoveLeft", "MoveRight", "MoveUp", "Pleased", "Process", "Processing", "Read", "ReadContinued", "ReadReturn", "Reading", "RestPose", "Sad", "Search", "Searching", "Show", "StartListening", "StopListening", "Suggest", "Surprised", "Think", "Uncertain", "Wave", "Write", "WriteContinued", "WriteReturn", "Writing"];
var remote = false;
var cur_x = 400, cur_y = 300;
var MoveTimer = null;
function LoadAgent(NewAgent) {
if(AgentLoad) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
}
AgentID = NewAgent;
AgentACS = NewAgent + ".acs";
MSAgent.Connected = true;
try {
MSAgent.Characters.Load(AgentID, AgentACS);
} catch(e) {
AgentACS = "http://agent.microsoft.com/agent2/chars/" + NewAgent + "/" + NewAgent + ".acf";
remote = true;
AgentLoadRequest = MSAgent.Characters.Load(AgentID, AgentACS);
}
try {
AgentLoad = true;
Agent = MSAgent.Characters.Character(AgentID);
Agent.LanguageID = 0x0409;
Agent.Balloon.Style = 0x330000F;
Agent.Commands.RemoveAll();
Agent.Commands.Visible = true;
Agent.Commands.Caption = "MSAgent's Menu - by windy_sk";
Agent.Commands.Add("ACO", "Advanced Character Options", "Advanced Character Options");
Agent.Commands.Add("READ", "Read Text In Textarea", "Read Text In Textarea");
Agent.Commands.Add("INTRO", "Introduce Yourself", "Introduce yourself");
Agent.Commands.Add("AUTHOR", "Who Write The Program", "Who Write The Program");
Agent.Commands.Add("SAYTIME", "What Time Is It Now", "What Time Is It Now");
Agent.Commands.Add("FLY", "Can You Fly", "Can You Fly");
Agent.Commands.Add("STOP", "Stop All Actions", "Stop All Actions");
if(remote) {
AgentStateRequest = Agent.get("state", "Showing, Thinking");
AgentAnimationRequest = Agent.get("animation", "GetAttention, RestPose");
}
Agent.MoveTo(cur_x, cur_y);
Agent.Show();
try {
Agent.Play("GetAttention");
} catch(e) {
Agent.Play("RestPose");
}
Agent.speak("Hi, I am " + NewAgent + ", can I help you, sir?");
//Agent.think("Oh so bad, I just wanna take a nap...");
if(remote) AgentStateRequest = Agent.get("state", AgentStates);
} catch(e) {
for(var x in e) alert(x + " - " + e[x]);
AgentLoad = false;
}
return;
}
function GetRandomNum(Min,Max){
var Range = Max - Min;
var Rand = Math.random();
return(Min + Math.round(Rand * Range));
}
function Agent_Show() {
if(!AgentLoad) return;
var argv = Agent_Show.arguments;
var argc = argv.length;
if(!Agent.Visible) Agent.Show();
for(var i=0; i<argc; i+=2) {
if(argv[i] == "random") argv[i] = AgentAnimations[GetRandomNum(0, AgentAnimations.length-1)];
try {
if(remote) Agent.get("animation", argv[i]);
Agent.Play(argv[i]);
} catch(e) {
Agent.Play("RestPose");
}
if(typeof(argv[i+1]) != "undefined" && argv[i+1] != "") Agent.speak(argv[i+1]);
}
return;
}
function Agent_Show_All(mode) {
if(Agent==null || !AgentLoad) return;
if(!Agent.Visible) Agent.Show();
show.value = "Animation for " + AgentID;
for(var i=0; i<AgentAnimations.length; i++){
show.value += "\ntesting '" + AgentAnimations[i] + "' - ";
try {
if(remote) Agent.get("animation", AgentAnimations[i]);
Agent.Play(AgentAnimations[i]);
Agent.speak(AgentID + " can play '" + AgentAnimations[i] + "'!");
show.value += "OK!";
} catch(e) {
Agent.Play("RestPose");
Agent.speak(AgentID + " play '" + AgentAnimations[i] + "' failed !");
show.value += "Failed!";
}
if(!mode) Agent.Stop();
}
return;
}
function Agent_Move(){
if(!AgentLoad) return;
if(GetRandomNum(1, 10) > 6){
var Scr_width = window.screen.width - 100;
var Scr_Height = window.screen.height - 100;
Agent.MoveTo(GetRandomNum(0,Scr_width),GetRandomNum(0,Scr_Height));
}
MoveTimer = setTimeout("Agent_Move()",5000);
return;
}
window.onhelp = function() {
if(!AgentLoad) return;
if(Agent == null) {
LoadAgent(AgentID);
} else {
if(!Agent.Visible) Agent.Show();
Agent.speak("Can I help you, sir?");
}
return false;
}
LoadAgent("Merlin");
</Script>
Charactor Select :
<SELECT name="Agent_select" onchange="LoadAgent(this[this.selectedIndex].text)">
<Optgroup label="Offical Charactors">
<OPTION>Merlin</OPTION>
<OPTION>Peedy</OPTION>
<OPTION>Genie</OPTION>
<OPTION>Robby</OPTION>
</Optgroup>
<Optgroup label="Charactors from Office">
<OPTION>CLIPPIT</OPTION>
<OPTION>courtney</OPTION>
<OPTION>DOLPHIN</OPTION>
<OPTION>DOT</OPTION>
<OPTION>earl</OPTION>
<OPTION>F1</OPTION>
<OPTION>LOGO</OPTION>
<OPTION>MNATURE</OPTION>
<OPTION>MNKYKING</OPTION>
<OPTION>OFFCAT</OPTION>
<OPTION>qmark</OPTION>
<OPTION>ROCKY</OPTION>
<OPTION>rover</OPTION>
<OPTION>SAEKO</OPTION>
</Optgroup>
</SELECT>
<input type="checkbox" id="auto_move" onclick="this.checked?Agent_Move():clearTimeout(MoveTimer)"><label for="auto_move">Auto Move</label>
<br /><br />
<textarea id="show" style="width: 400px; height: 200px">
Hello everybody, I am Office Agent, I hope I am useful to you !
</textarea>
<br />
<input type="button" value="Test Animation" onclick="Agent_Show_All(show_animation.checked)">
<input type="checkbox" id="show_animation"><label for="show_animation">Show Animation</label>
算是个所有方法的大杂烩了,最后说明一下 Balloon 对象,其所有属性中只有 Style 可以更改,而官方所给的资料还不完全 msdn.microsoft.com/library/en-us/msagent/pacontrol_9gtm.asp ,还是自己慢慢挖掘吧……
到这里就算是告一段落吧,不想写了,总感觉看的越多就越不了解,真的开始有点佩服 MicroSoft 了,单这么个冰山一角就涉及到无数的枝节,本文虽然不算很彻底的研究,但是入门级已经是绰绰有余了……
资源:
StartPage: msdn.microsoft.com/library/en-us/msagent/agentstartpage_7gdh.asp
FAQ: msdn.microsoft.com/library/en-us/msagent/paface_3sit.asp
Methods: msdn.microsoft.com/library/en-us/msagent/paface_73c5.asp
Events: msdn.microsoft.com/library/en-us/msagent/paface_2xet.asp
Actions: msdn.microsoft.com/library/en-us/msagent/deschar_3pgy.asp
LanguageId: www.microsoft.com/globaldev/reference/oslocversion.mspx
Balloon: msdn.microsoft.com/library/en-us/msagent/pacontrol_9gtm.asp
Voice: msdn.microsoft.com/library/en-us/dnexpvb/html/usingmsagentcontrolevents.asp
Command: msdn.microsoft.com/library/en-us/dnexpvb/html/workingwithcommands.asp
Download: www.microsoft.com/msagent/downloads/user.asp
www.microsoft.com/msagent/downloads/developer.asp
www.msagentring.org/chars.htm
msagentworld.tripod.com/characters.htm
终结:
本文仅是通过我个人对 MSAgent 的理解,以及以前的操作实践写成的,难免有所缺憾,随时欢迎补充和更正!
有了点时间又作了一点修改,把 Play Speak MoveTo 都设定为通过自定义函数处理,方便控制,又优化了一些细节处理,其实这个东西用好了还是蛮有用处的,关键要看你的创意,例如 BS 系统的 online help 等……
几个提示:
1、利用 RequestComplete 事件可以做事件延时处理(用来处理 Agent 本身行为的排队特性和非 Agent 行为的立即执行特性的矛盾)
2、多个 Agent 可同时调用(只要不 unload),多个 Agent 之间的进程等待可以用 Wait 方法,如: Agent2.Wait(Agent1_Request) 是指 Agent1 的 Request 行为结束后Agent2 再开始下一步的行为!
3、利用 Agent 做函数转意(如 alert 等函数)
程序代码:
<style>
*{font-size: 12px}
</style>
<Object style="visibility:hidden" id="MSAgent" ClassID="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F" CodeBase="http://activex.microsoft.com/activex/controls/agent2/MSagent.exe#VERSION=2,0,0,0"></Object>
<Object style="visibility:hidden" id="L&HTruVoice" ClassID="CLSID:B8F2846E-CE36-11D0-AC83-00C04FD97575" CodeBase="http://activex.microsoft.com/activex/controls/agent2/tv_enua.exe#VERSION=6,0,0,0"></Object>
<Script Language="JavaScript" For="MSAgent" Event="RequestStart(RequestObject)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
switch (RequestObject) {
case AgentLoadRequest :
window.status = "Loading MSAgent File From Internet For " + AgentID + " ...";
break;
case AgentStateRequest :
window.status = "Loading MSAgent State From Internet For " + AgentID + " ...";
break;
case AgentAnimationRequest :
window.status = "Loading MSAgent Animation From Internet For " + AgentID + " ...";
break;
default:
break;
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="RequestComplete(RequestObject)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
switch (RequestObject) {
case AgentLoadRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent File For " + AgentID + " Has Been Loaded Successfully !";
if(confirm("Cannot find the MSAgent charactor file on your hard disk! \nWould you like to download the MSAgent charactor file for the next show?"))
window.open("http://www.msagentring.org/download.asp?char="+NewAgent.toLowerCase(),"_blank","top=2000px");
} else {
window.status = "Cannot Load MSAgent File For " + AgentID + " From " + AgentACS + " !";
alert("Cannot find MSAgent file from local disk or internet!");
AgentLoad = false;
}
break;
case AgentStateRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent State For " + AgentID + " Has Been Loaded Successfully !";
} else {
window.status = "Cannot Load MSAgent State For " + AgentID + " From " + AgentACS + " !";
}
break;
case AgentAnimationRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent Animation For " + AgentID + " Has Been Loaded Successfully !";
} else {
window.status = "Cannot Load MSAgent Animation For " + AgentID + " From " + AgentACS + " !";
}
break;
case AgentTemporaryRequest :
Agent_Check_Animation();
break;
default:
window.status = "";
break;
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Click(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(Button==1 && Agent.Visible) {
Agent.Stop();
Agent_Show("Acknowledge", "Yes sir! " + CharacterID + " is right here!");
Agent_Show("Pleased", "What can I do for you?");
} else if(Button==4097) {
Agent.Stop();
Agent.Visible?Agent.Hide():Agent.show();
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DblClick(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(Button==1 || Button==4097) {
Agent.StopAll();
if (!Agent.HasOtherClients) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
AgentLoad = false;
}
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Move(CharacterID, X, Y, Cause)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var rnd_words = new Array();
rnd_words.push("Ha, I am the king of screen!");
rnd_words.push("It's good day to fly!");
rnd_words.push("Ah, your boss is on your back!");
rnd_words.push("Oh, it's fruit time, do you want an apple?");
rnd_words.push("How do you think about me?");
rnd_words.push("Hey guy, have a rest!");
rnd_words.push("Pretty girl everywhere, single me over there...");
rnd_words.push("Hi, don't you think I like neo in Matrix?");
rnd_words.push("If you think it, you will make it!");
rnd_words.push("I am so lonely, together with me, come on!");
if(Cause==2) {
Agent_Show("random", rnd_words[GetRandomNum(0, rnd_words.length-1)]);
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DragStart(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
cur_x = X - Agent.width/2;
cur_y = Y - Agent.height/2;
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DragComplete(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
Agent.StopAll();
Agent_Show("Confused", "Don't move me OK?", "RestPose");
Agent_MoveTo(cur_x, cur_y, true);
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Idle(CharacterID, State)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(State) Agent_Show("random", "I am so lonely ...");;
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Command(UserInput)">
var BadConfidence = 10;
if (UserInput.Confidence <= -40){
alert("Bad Recognition!");
} else if ((UserInput.Alt1Name != "") && (Math.abs(Math.abs(UserInput.Alt1Confidence) - Math.abs(UserInput.Confidence)) < BadConfidence)) {
alert("Bad Confidence - too close to another command !");
} else if ((UserInput.Alt2Name != "") && (Math.abs(Math.abs(UserInput.Alt1Confidence) - Math.abs(UserInput.Confidence)) < BadConfidence)) {
alert("Bad Confidence - too close to another command !");
} else {
switch(UserInput.Name) {
case "ACO" :
MSAgent.PropertySheet.Visible = true;
break;
case "READ":
Agent_Read(show.value);
break;
case "SAYTIME":
Agent_Show("Suggest", "It is now " + (new Date()) + "!");
break;
case "INTRO" :
Agent_Show("Explain", "My name is " + AgentID + ", I think I'm the best one!");
break;
case "AUTHOR":
Agent_Show("Announce", "Windy_sk <windy_sk@126.com> wrote the program, I think he's great! (^o^)");
break;
case "FLY":
Agent_MoveTo(Math.round(Math.random() * screen.width - Agent.width), Math.round(Math.random() * screen.height - Agent.height));
break;
case "STOP":
Agent.StopAll();
Agent_Show("RestPose");
break;
default:
break;
}
}
</Script>
<Script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
function reportError(msg,url,line) {
var str = "You have found an error as below: \n\n";
str += "Err: " + msg + " on line: " + line;
alert(str);
return true;
}
window.onerror = reportError;
var Agent = null;
var AgentID, AgentACS;
var AgentLoad = false;
var AgentLoadRequest, AgentStateRequest, AgentAnimationRequest, AgentTemporaryRequest;
var AgentStates = "GesturingDown, GesturingLeft, GesturingRight, GesturingUp, Hearing, Hiding, IdlingLevel1, IdlingLevel2, IdlingLevel3, Listening, MovingDown, MovingLeft, MovingRight, MovingUp, Showing, Speaking";
var AgentAnimations = ["Acknowledge", "Alert", "Announce", "Blink", "Confused", "Congratulate", "Congratulate_2", "Decline", "DoMagic1", "DoMagic2", "DontRecognize", "Explain", "GestureDown", "GestureLeft", "GestureRight", "GestureUp", "GetAttention", "GetAttentionContinued", "GetAttentionReturn", "Greet", "Hide", "Idle1_1", "Idle1_2", "Idle1_3", "Idle1_4", "Idle2_1", "Idle2_2", "Idle3_1", "LookDown", "LookLeft", "LookRight", "LookUp", "MoveDown", "MoveLeft", "MoveRight", "MoveUp", "Pleased", "Process", "Read", "ReadContinued", "ReadReturn", "RestPose", "Sad", "Search", "Show", "StartListening", "StopListening", "Suggest", "Surprised", "Think", "Uncertain", "Wave", "Write", "WriteContinued", "WriteReturn"];
var AgentAnimations_loop = ["Hearing_1", "Hearing_2", "Hearing_3", "Hearing_4", "Idle3_2", "Processing", "Reading", "Searching", "Writing"];
var AgentAnimations_available = AgentAnimations;
var remote = false;
var cur_x = 400, cur_y = 300;
var MoveTimer = null;
function LoadAgent(NewAgent) {
if(AgentLoad) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
}
AgentID = NewAgent;
AgentACS = NewAgent + ".acs";
MSAgent.Connected = true;
try {
MSAgent.Characters.Load(AgentID, AgentACS);
} catch(e) {
AgentACS = "http://agent.microsoft.com/agent2/chars/" + NewAgent + "/" + NewAgent + ".acf";
remote = true;
AgentLoadRequest = MSAgent.Characters.Load(AgentID, AgentACS);
}
try {
AgentLoad = true;
Agent = MSAgent.Characters.Character(AgentID);
Agent.LanguageID = 0x0409;
Agent.Balloon.Style = 0x330000F;
Agent.Commands.RemoveAll();
Agent.Commands.Visible = true;
Agent.Commands.Caption = "MSAgent's Menu - by windy_sk";
Agent.Commands.Add("ACO", "Advanced Character Options", "Advanced Character Options");
Agent.Commands.Add("READ", "Read Text In Textarea", "Read Text In Textarea");
Agent.Commands.Add("INTRO", "Introduce Yourself", "Introduce yourself");
Agent.Commands.Add("AUTHOR", "Who Write The Program", "Who Write The Program");
Agent.Commands.Add("SAYTIME", "What Time Is It Now", "What Time Is It Now");
Agent.Commands.Add("FLY", "Can You Fly", "Can You Fly");
Agent.Commands.Add("STOP", "Stop All Actions", "Stop All Actions");
if(remote) {
AgentStateRequest = Agent.get("state", "Showing, Thinking");
AgentAnimationRequest = Agent.get("animation", "GetAttention, RestPose");
}
Agent.MoveTo(screen.width - 200, 100);
Agent.Show();
try {
Agent.Play("GetAttention");
} catch(e) {
Agent.Play("RestPose");
}
Agent.speak("Hi, I am " + NewAgent + ", can I help you, sir?");
AgentTemporaryRequest = Agent.Play("RestPose");
//Agent.think("Oh so bad, I just wanna take a nap...");
if(remote) AgentStateRequest = Agent.get("state", AgentStates);
} catch(e) {
for(x in e) alert(x + " - " + e[x]);
AgentLoad = false;
}
return;
}
function GetRandomNum(Min,Max){
var Range = Max - Min;
var Rand = Math.random();
return(Min + Math.round(Rand * Range));
}
function Agent_Read(text) {
if(!AgentLoad) return;
var txt_arr = text.split("\n");
Agent_Show("Read");
for(var i=0; i<txt_arr.length; i++) {
if(txt_arr[i] != "") Agent.Speak(txt_arr[i]);
}
Agent_Show("ReadContinued");
Agent.Speak("Over, Sir!");
Agent_Show("ReadReturn");
return;
}
function Agent_MoveTo(x, y, mode) {
if(!AgentLoad) return;
if(!/^\d+$/.test(x+y)) return;
if(!Agent.Visible || typeof(mode)=="undefined") {
Agent.MoveTo(x, y);
} else {
Agent.Hide();
Agent.MoveTo(x, y);
Agent.Show();
}
return;
}
function Agent_Show() {
if(!AgentLoad) return;
var argv = Agent_Show.arguments;
var argc = argv.length;
if(!Agent.Visible) Agent.Show();
for(var i=0; i<argc; i+=2) {
if(argv[i] == "random") argv[i] = AgentAnimations_available[GetRandomNum(0, AgentAnimations_available.length-1)];
try {
if(remote) Agent.get("animation", argv[i]);
Agent.Play(argv[i]);
} catch(e) {
Agent.Play("RestPose");
}
if(typeof(argv[i+1]) != "undefined" && argv[i+1] != "") Agent.speak(argv[i+1]);
}
return;
}
function Agent_Check_Animation() {
if(Agent==null || !AgentLoad) return;
if(!Agent.Visible) Agent.Show();
AgentAnimations_available = new Array();
for(var i=0; i<AgentAnimations.length; i++){
try {
if(remote) Agent.get("animation", AgentAnimations[i]);
Agent.Play(AgentAnimations[i]);
AgentAnimations_available.push(AgentAnimations[i]);
} catch(e){}
Agent.Stop();
}
return;
}
function Agent_Show_All() {
if(Agent==null || !AgentLoad) return;
if(!Agent.Visible) Agent.Show();
Agent.StopAll();
for(var i=0; i<AgentAnimations_available.length; i++){
try {
if(remote) Agent.get("animation", AgentAnimations_available[i]);
Agent.Play(AgentAnimations_available[i]);
Agent.speak(AgentID + " can play '" + AgentAnimations_available[i] + "'!");
} catch(e) {
Agent.Play("RestPose");
Agent.speak(AgentID + " play '" + AgentAnimations_available[i] + "' failed !");
}
}
return;
}
function Agent_Rnd_Move(){
if(!AgentLoad) return;
if(GetRandomNum(1, 10) > 6){
var Scr_width = window.screen.width - 100;
var Scr_Height = window.screen.height - 100;
Agent_MoveTo(GetRandomNum(0,Scr_width),GetRandomNum(0,Scr_Height));
}
MoveTimer = setTimeout("Agent_Rnd_Move()",5000);
return;
}
window.onhelp = function() {
if(!AgentLoad) return;
if(Agent == null) {
LoadAgent(AgentID);
} else {
if(!Agent.Visible) Agent.Show();
Agent.speak("Can I help you, sir?");
}
return false;
}
LoadAgent("Merlin");
var org_alert = window.alert;
window.alert = Agent_Read;
</Script>
Charactor Select :
<SELECT name="Agent_select" onchange="LoadAgent(this[this.selectedIndex].text)">
<Optgroup label="Offical Charactors">
<OPTION>Merlin</OPTION>
<OPTION>Peedy</OPTION>
<OPTION>Genie</OPTION>
<OPTION>Robby</OPTION>
</Optgroup>
<Optgroup label="Charactors from Office">
<OPTION>CLIPPIT</OPTION>
<OPTION>courtney</OPTION>
<OPTION>DOLPHIN</OPTION>
<OPTION>DOT</OPTION>
<OPTION>earl</OPTION>
<OPTION>F1</OPTION>
<OPTION>LOGO</OPTION>
<OPTION>MNATURE</OPTION>
<OPTION>MNKYKING</OPTION>
<OPTION>OFFCAT</OPTION>
<OPTION>qmark</OPTION>
<OPTION>ROCKY</OPTION>
<OPTION>rover</OPTION>
<OPTION>SAEKO</OPTION>
</Optgroup>
</SELECT>
<input type="checkbox" id="auto_move" onclick="this.checked?Agent_Rnd_Move():clearTimeout(MoveTimer)"><label for="auto_move">Auto Move</label>
<br /><br />
Speak Text: <br />
<textarea id="show" style="width: 400px; height: 70px">
Hello everybody,
I am Office Agent,
I think I may useful to you !
</textarea>
<br />
<br />
<input type="button" value="Read Textarea" onclick="Agent_Read(show.value)">
<input type="button" value="Test Animation" onclick="Agent_Show_All(); show.value = show.defaultValue + '\n' + AgentID + ' can play the following actions: \n' + AgentAnimations_available.join('\n');">
cnbruce的借花献佛:
程序代码:
<html>
<head>
<style>button{width:100;border:outset 2;}</style>
</head>
<body bgcolor=threedface scroll=auto>
<button onclick= Merlin.Play("RestPose") >复位
<button onclick= Merlin.Stop() >停止
<button onclick= Merlin.Play("Acknowledge") >点头
<button onclick= Merlin.Play("Surprised") >惊讶
<button onclick= Merlin.Play("GestureUp") >手势
<button onclick= Merlin.Play("Pleased") >满足
<button onclick= Merlin.Play("Alert") >警告
<button onclick= Merlin.Play("Announce") >宣布
<button onclick= Merlin.Play("Blink") >眨眼
<button onclick= Merlin.Play("Confused") >困惑
<button onclick= Merlin.Play("Congratulate") >恭喜1
<button onclick= Merlin.Play("Congratulate_2") >恭喜2
<button onclick= Merlin.Play("Decline") >拒绝
<button onclick= Merlin.Play("DoMagic1") >变魔术1
<button onclick= Merlin.Play("DoMagic2") >变魔术2
<button onclick= Merlin.Play("DontRecognize") >没听清
<button onclick= Merlin.Play("Explain") >说明
<button onclick= Merlin.Play("GetAttention") >敲一下
<button onclick= Merlin.Play("GetAttentionContinued") >不停敲
<button onclick= Merlin.Play("GetAttentionReturn") >不敲了
<button onclick= Merlin.Play("Greet") >问候
<button onclick= Merlin.Play("Hearing_1") >听1
<button onclick= Merlin.Play("Hearing_2") >听2
<button onclick= Merlin.Play("Hearing_3") >听3
<button onclick= Merlin.Play("Hearing_4") >听4
<button onclick= Merlin.Play("Idle1_1") >1-1
<button onclick= Merlin.Play("Idle1_2") >1-2
<button onclick= Merlin.Play("Idle1_3") >1-3
<button onclick= Merlin.Play("Idle1_4") >1-4
<button onclick= Merlin.Play("Idle2_1") >2-1
<button onclick= Merlin.Play("Idle2_2") >2-2
<button onclick= Merlin.Play("Idle3_1") >3-1
<button onclick= Merlin.Play("Idle3_2") >3-2
<button onclick= Merlin.Play("LookDown") >俯视
<button onclick= Merlin.Play("LookDownBlink") >俯视眨眼
<button onclick= Merlin.Play("LookDownReturn") >俯视眨眼返回
<button onclick= Merlin.Play("MoveUp") >上移
<button onclick= Merlin.Play("MoveDown") >下移
<button onclick= Merlin.Play("MoveLeft") >左移
<button onclick= Merlin.Play("MoveRight") >右移
<button onclick= Merlin.Play("Process") >熬汤
<button onclick= Merlin.Play("Processing") >熬汤
<button onclick= Merlin.Play("Read") >读
<button onclick= Merlin.Play("ReadReturn") >不读了
<button onclick= Merlin.Play("Reading") >正在读
<button onclick= Merlin.Play("ReadContinued") >不停读
<button onclick= Merlin.Play("Sad") >悲哀
<button onclick= Merlin.Play("Search") >查找
<button onclick= Merlin.Play("Searching") >正在查找
<button onclick= Merlin.Play("StartListening") >听
<button onclick= Merlin.Play("StopListening") >捂耳朵
<button onclick= Merlin.Play("Suggest") >暗示
<button onclick= Merlin.Play("Uncertain") >想飞
<button onclick= Merlin.Play("Wave") >挥手
<button onclick= Merlin.Play("Write") >写东西
<button onclick= Merlin.Play("WriteContinued") >不停写
<button onclick= Merlin.Play("WriteReturn") >不写了
<button onclick= Merlin.Think("fly") >想
<button onclick= doalert('something') >说
<script>
function doalert(text) {
Merlin.Speak(text);
}
</script>
<Object ID=agent ClassID=CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F></Object>
<script>
var MerlinID;
var MerlinACS;
agent.Connected=true;
MerlinLoaded=LoadLocalAgent(MerlinID,MerlinACS);
Merlin=agent.Characters.Character(MerlinID);
Merlin.Show();
function LoadLocalAgent(CharID,CharACS){
LoadReq=agent.Characters.Load(CharID,CharACS);
return(true);
}
</script>
</body>
</html>
可能 MSAgent 这个名字你不清楚,但如果提起 Office 助手我想在这个目前 MicroSoft 独霸天下的电脑世界应该鲜有人不知道,本文就是交给你如何在网页中调用这个在线尤物。
入题:
一、抛砖引玉
首先,我们先来看一下一个最简单的效果:
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID = "Merlin";
var AgentACS = "merlin.acs";
MSAgent.Connected = true;
MSAgent.Characters.Load(AgentID,AgentACS);
Agent = MSAgent.Characters.Character(AgentID);
Agent.Show();
</script>
看到没有,如果顺利的话,你的屏幕上会出现一个很 Q 的卡通魔法师。对,这就是传说中的 MSAgent !下面讲解一下各个部分的作用:
AgentID 内部索引字串,由用户定义;
AgentACS 所调用的角色文件,可以为浏览者本地或远程文件,后面会有单独的部分说明。
MSAgent.Connected 建立连接;
MSAgent.Characters.Load 读取角色;
MSAgent.Characters.Character 返回角色对象;
Agent.Show 显示角色;
好了,我现在已经把 MSAgent 带到你面前了。什么?什么东西都没看到?只有浏览器的报错!没关系,在后面的文章里,我也会告诉你如何才能看到他,当然,这个看到指的是所有浏览你网页的人!
二、伶牙俐齿
下面,我们就让他来做一点实际的东西 —— 说话!还是接续上例:
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID = "Merlin";
var AgentACS = "merlin.acs";
MSAgent.Connected = true;
MSAgent.Characters.Load(AgentID,AgentACS);
Agent = MSAgent.Characters.Character(AgentID);
Agent.LanguageID = 0x0409;
Agent.Show();
Agent.Speak("Hello Everybody, I am Merlin!");
Agent.Think("What shall I do the next?");
</script>
Merlin 说话了(如果要读出声音来的话,需要客户端在 MicroSoft 的网站上下载并安装相应的语音引擎)!这里涉及到这么几个新的东西:
Agent.LanguageID 声明语言种类,0x0409是英文的编号(有关语言编号请参考 www.microsoft.com/globaldev/reference/oslocversion.mspx ),目前如果没有这个声明,或声明为错误的语种,则语言只是一次性完全显示。
Agent.Speak() 和 Agent.Think() 是 MSAgent 的两个语言表达显示行为,只有显示图形的区别。
了解了这些功能,是不是正在陶醉呀?别急,还有更好的东西呢!
三、活灵活现
总是看着一个呆头呆脑的东西一动不动,即使是很 Q ,也会有感到多少的厌烦,下面我们就让他动起来。
这个例子由于调用的是网络文件,所以会慢一点,请耐心等待一下!
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID = "Merlin";
var AgentACS = "http://agent.microsoft.com/agent2/chars/merlin/merlin.acf";
var AgentStates = "Showing, Hiding, Speaking, Moving";
var AgentAnimations = "GetAttention, GetAttentionReturn, Congratulate, Acknowledge, Read, WriteContinued, WriteReturn, wave";
var AgentLoadRequest, AgentStateRequest, AgentAnimationRequest;
MSAgent.Connected = true;
AgentLoadRequest = MSAgent.Characters.Load(AgentID,AgentACS);
Agent = MSAgent.Characters.Character(AgentID);
Agent.LanguageID = 0x0409;
AgentStateRequest = Agent.get("state", AgentStates);
AgentAnimationRequest = Agent.get("animation", AgentAnimations);
Agent.Show();
Agent.MoveTo(400,300);
Agent.Play("GetAttention");
Agent.Play("GetAttentionReturn");
Agent.speak("Hi, may I have your attention, please?");
Agent.Play("Congratulate");
Agent.speak("So nice to meet you!");
Agent.Play("Think");
Agent.speak("How do think about me?");
Agent.Play("Acknowledge");
Agent.Speak("It's very cool, ya?");
Agent.Play("Read");
Agent.Play("WriteContinued");
Agent.Play("WriteReturn");
Agent.Speak("Oh, I have lots of things to do, see you !");
Agent.Play("wave");
Agent.Speak("Bye-bye!");
Agent.Hide();
</script>
看到没有?其实只要你善于调动它的积极性,MSAgent 也蛮活泼的!信息观察,不难发现,原来让 MSAgent 动起来,也不过就这么简单:
Agent.MoveTo(x, y) 是角色移动到指定的坐标;
Agent.Play(action) 命令角色做某个动作,动作列表见: msdn.microsoft.com/library/default.asp?url=/library/en-us/msagent/deschar_3pgy.asp (这里需要说明一下,不是所有的角色都支持这些动作的,处理方法后面会有说明!)
Agent.Hide() 隐藏角色(不是释放角色,通过 Agent.Show() 可以再次显示)
Agent.get(Request, list) 预载相关 MSAgent 动画数据,MSAgent人物数据文件支持单结构角色文件(.acs,角色数据与动画数据存于同一个文件),也支持分离结构角色文件(.acf,角色数据存于.acf中,动画数据存于.aca中)。基于本地硬盘和网络调用均可采用这两种模式,当调用网络 acf 文件时,由于角色数据与动画数据分别下载,所以需要预载相关动画数据,使用 acs 文件(一般没有本地 acf 文件的可能性),不需要预载。
AgentLoadRequest, AgentLoadRequest 和 AgentAnimationRequest 这三个参数本例并没有实际用到,返回应相关操作的状态对象(相当于 readystatus 属性),在调用网络 acf 文件时有比较实际的用途,这个会在后面说明!
四、改头换面
MSAgent = Merlin ? 错!MSAgent 是指一系列动画人物的总称,最常见的 office 中的那些活宝,各位应该都熟悉吧?先来看看下面的这个例子:
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID, AgentACS;
var AgentLoad = false;
function LoadAgent(NewAgent) {
if(AgentLoad) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
}
AgentID = NewAgent;
AgentACS = "http://agent.microsoft.com/agent2/chars/" + NewAgent + "/" + NewAgent + ".acf";
MSAgent.Connected = true;
MSAgent.Characters.Load(AgentID, AgentACS);
AgentLoad = true;
Agent = MSAgent.Characters.Character(AgentID);
Agent.get("state", "Showing, Hiding");
Agent.MoveTo(400, 300);
Agent.Show();
return;
}
LoadAgent("Merlin");
</script>
MSAgent Select :
<SELECT name="Agent_select" onchange="LoadAgent(this[this.selectedIndex].text)">
<OPTION>Merlin</OPTION>
<OPTION>Peedy</OPTION>
<OPTION>Genie</OPTION>
<OPTION>Robby</OPTION>
</SELECT>
看到没有? 原来 MSAgent 还有这么多可爱的造型呢!上面的例程中,我定义了一个读取角色的函数 LoadAgent ,通过这个函数更换角色,其中的大部分的功能在前面的章节中已经介绍了,这里仅仅说明一下,新的方法:
MSAgent.Characters.Unload() 卸载角色,其中 AgentID ,必须是 MSAgent.Characters.Load() 中声明过的
Agent.MoveTo() 这个方法上一节中介绍过,但是如果把它放在 Agent.Show() ,则相当于定义角色的出现位置
其实,MSAgent 绝对不仅仅是那么多,但是 MicroSoft 的官方网站上只提供了那么多……怎么办?可以从他的网站上连接角色,当然可可以从你的网站上呀!你可以在这里 www.microsoft.com/msagent/downloads/user.asp 下载官方角色以及语音引擎(可惜没有中文);当然,如果你有兴趣的话也可以开发一个属于自己的 Agent ,相关开发工具 www.microsoft.com/msagent/downloads/developer.asp ,网上也有很多高手做好的动画人物,读者可以搜索一下。
安装后角色文件存放在 %WINDOWS%\msagent\chars 目录下的 *.acs 文件,上传到服务器上,直接引用到那个路径就可以了!(你也可以在你的硬盘里搜索一下 *.acs 会有不小的收获呦)这里要说明一下,请自行更改程序中标明网络路径的相关语句,且注意扩展名是 .acs !
如果要让本机支持相应的 MSAgent ,也就是说不用网络调用,只要把 *.acs 文件 copy 到 %WINDOWS%\msagent\chars 目录就可以了,但如果是 *.exe 的安装文件,则会自动把角色文件放置到相应的路径下。
五、排难解错
能否显示 MSAgent 的关键在于是否安装了 MSAgent 的核心组件( Microsoft Agent core components - activex.microsoft.com/activex/controls/agent2/MSagent.exe ),但是如何让这一被动行为变为主动呢?可以用下面两种方法:
方法一:
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F" CodeBase="http://activex.microsoft.com/activex/controls/agent2/MSagent.exe#VERSION=2,0,0,0"></object>
特点:自动下载组件并安装,比较方便,但会下载的等待时间不会提示,在网速慢的时候会以为页免死掉,且不是很方便控制。
方法二:
程序代码:
<script language="javascript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
function Agent_load_error(){
alert("To make the MSAgent available, /nplease install Microsoft Agent core components first !");
window.open("http://activex.microsoft.com/activex/controls/agent2/MSagent.exe");
return;
}
</script>
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F" onerror="Agent_load_error()"></object>
特点:方便出错控制,用户控制下载,但是不能当时显示,需要安装后再次刷新页面。
使用哪种方法就属于见仁见智了,但是最不明智的方法就是两种方法一起上,实践证明 CodeBase 会先于 onerror 生效!
同理,如果想要角色发声,只要在控件声明中加上如下的 CodeBase 就可以了:
程序代码:
<Object style="visibility:hidden" id="L&HTruVoice" ClassID="CLSID:B8F2846E-CE36-11D0-AC83-00C04FD97575" CodeBase="http://activex.microsoft.com/activex/controls/agent2/tv_enua.exe#VERSION=6,0,0,0"></Object>
以上是 MicroSoft 的 lernout & Hauspie TruVoice 朗读引擎,我所引用的是美国英语的引擎文件,其他语种请见 www.microsoft.com/msagent/downloads/user.asp#tts ,可惜,还是没有中文引擎……
不管怎么说,调用本地角色也比网络角色速度上要快得多,但是你如何预知客户端是否安装了该角色呢?看看下面的例子:
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID, AgentACS;
var AgentLoad = false;
function LoadAgent(NewAgent) {
var remote = false;
if(AgentLoad) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
}
AgentID = NewAgent;
AgentACS = NewAgent + ".acs";
MSAgent.Connected = true;
try {
MSAgent.Characters.Load(AgentID, AgentACS);
agent_exist.innerText = "Local MSAgent load successfully!";
} catch(e) {
AgentACS = "http://agent.microsoft.com/agent2/chars/" + NewAgent + "/" + NewAgent + ".acf";
remote = true;
MSAgent.Characters.Load(AgentID, AgentACS);
agent_exist.innerText = "Local MSAgent load unsuccessfully, as a advice, you'd better to download the charactor file to your hard disk!";
}
AgentLoad = true;
Agent = MSAgent.Characters.Character(AgentID);
if(remote) Agent.get("state", "Showing, Hiding");
Agent.MoveTo(400, 300);
Agent.Show();
return;
}
window.onload = function(){LoadAgent("Merlin");};
</script>
MSAgent Select :
<SELECT name="Agent_select" onchange="LoadAgent(this[this.selectedIndex].text)">
<OPTION>Merlin</OPTION>
<OPTION>Peedy</OPTION>
<OPTION>Genie</OPTION>
<OPTION>Robby</OPTION>
</SELECT>
<br /><br />
Load Status: <span id="agent_exist"></span>
通过设置错误捕获,可以方便的找到调用 MSAgent 的最佳方式,当然,你还可以通过 DHTML 加上相应的角色下载链接,并指导用户将 *.acs 文件 copy 到相应目录(%WINDOWS%\msagent\chars)或直接安装 *.exe 的角色安装文件以方便下次浏览,本文仅仅是为你提供一个思路,具体实践还是自己发挥吧!
六、事件响应
像所有 OOP 一样,MSAgent 也设置有相应的事件响应,看看下面的例子,试试在角色或任务栏的图标上点击鼠标(单/双击),你也可以移动一下角色,看看它有什么反应:
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<Script Language="JavaScript" For="MSAgent" Event="Click(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(Button==1 && Agent.Visible) {
if(remote) {
Agent.get("state", "Speaking");
Agent.get("animation", "Acknowledge, Pleased");
}
Agent.Play("Acknowledge");
Agent.Speak("Yes sir! " + CharacterID + " is right here!");
Agent.Play("Pleased")
Agent.Speak("What can I do for you?");
} else if(Button==4097) {
Agent.Visible?Agent.Hide():Agent.show();
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DblClick(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(Button==1 || Button==4097) {
Agent.StopAll();
if (!Agent.HasOtherClients) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
AgentLoad = false;
}
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Move(CharacterID, X, Y, Cause)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(Cause == 1) {
if(remote) {
Agent.get("state", "Moving, Speaking");
Agent.get("animation", "Confused, RestPose");
}
Agent.MoveTo(400, 300);
Agent.Play("Confused");
Agent.Speak("Don't move me OK?");
Agent.Play("RestPose");
}
</Script>
<Script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID, AgentACS;
var AgentLoad = false;
var remote = false;
function LoadAgent(NewAgent) {
if(AgentLoad) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
}
AgentID = NewAgent;
AgentACS = NewAgent + ".acs";
MSAgent.Connected = true;
try {
MSAgent.Characters.Load(AgentID, AgentACS);
} catch(e) {
AgentACS = "http://agent.microsoft.com/agent2/chars/" + NewAgent + "/" + NewAgent + ".acf";
remote = true;
MSAgent.Characters.Load(AgentID, AgentACS);
if(confirm("Cannot find the MSAgent charactor file on your hard disk! \nWould you like to download the MSAgent charactor file for the next show?"))
window.open("http://www.msagentring.org/download.asp?char="+NewAgent.toLowerCase(),"_blank","top=2000px");
}
AgentLoad = true;
Agent = MSAgent.Characters.Character(AgentID);
Agent.LanguageID = 0x0409;
if(remote) Agent.get("state", "Showing, Hiding");
Agent.MoveTo(400, 300);
Agent.Show();
return;
}
LoadAgent("Merlin");
</Script>
MSAgent Select :
<SELECT name="Agent_select" onchange="LoadAgent(this[this.selectedIndex].text)">
<OPTION>Merlin</OPTION>
<OPTION>Peedy</OPTION>
<OPTION>Genie</OPTION>
<OPTION>Robby</OPTION>
</SELECT>
是不是感觉交互性强了许多?我们来看一下事件处理的声明方法:
<Script Language="JavaScript" For="MSAgent_Object" Event="Event_Name()">
//code...
</Script>
熟悉一点 JS 编程的应该不会陌生这种声明方式,也就是对某一对象某一事件的单独处理的声明方法,但是如果是该成 MSAgent_Object.Event_Name = function() {//code...} 的事件处理声明是不可以的!(the only way to do this)
如果是采用网络调用的话,如果向用户通知相应的调用进度呢?
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<Script Language="JavaScript" For="MSAgent" Event="RequestStart(RequestObject)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
switch (RequestObject) {
case AgentLoadRequest :
window.status = "Loading MSAgent File From Internet For " + AgentID + " ...";
break;
case AgentStateRequest :
window.status = "Loading MSAgent State From Internet For " + AgentID + " ...";
break;
case AgentAnimationRequest :
window.status = "Loading MSAgent Animation From Internet For " + AgentID + " ...";
break;
default:
break;
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="RequestComplete(RequestObject)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
switch (RequestObject) {
case AgentLoadRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent File For " + AgentID + " Has Been Loaded Successfully !";
} else {
window.status = "Cannot Load MSAgent File For " + AgentID + " From " + AgentACS + " !";
}
break;
case AgentStateRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent State For " + AgentID + " Has Been Loaded Successfully !";
} else {
window.status = "Cannot Load MSAgent State For " + AgentID + " From " + AgentACS + " !";
}
break;
break;
case AgentAnimationRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent Animation For " + AgentID + " Has Been Loaded Successfully !";
} else {
window.status = "Cannot Load MSAgent Animation For " + AgentID + " From " + AgentACS + " !";
}
break;
break;
default:
window.status = "";
break;
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DragStart(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
cur_x = X - Agent.width/2;
cur_y = Y - Agent.height/2;
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DragComplete(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(remote) {
AgentStateRequest = Agent.get("state", "Moving, Speaking");
AgentAnimationRequest = Agent.get("animation", "Confused, RestPose");
}
Agent.MoveTo(cur_x, cur_y);
Agent.Play("Confused");
Agent.Speak("Don't move me OK?");
Agent.Play("RestPose");
</Script>
<Script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID, AgentACS;
var AgentLoad = false;
var remote = false;
var cur_x, cur_y;
var AgentLoadRequest, AgentStateRequest, AgentAnimationRequest;
function LoadAgent(NewAgent) {
if(AgentLoad) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
}
AgentID = NewAgent;
AgentACS = NewAgent + ".acs";
MSAgent.Connected = true;
try {
AgentLoadRequest = MSAgent.Characters.Load(AgentID, AgentACS);
} catch(e) {
AgentACS = "http://agent.microsoft.com/agent2/chars/" + NewAgent + "/" + NewAgent + ".acf";
remote = true;
AgentLoadRequest = MSAgent.Characters.Load(AgentID, AgentACS);
if(confirm("Cannot find the MSAgent charactor file on your hard disk! \nWould you like to download the MSAgent charactor file for the next show?"))
window.open("http://www.msagentring.org/download.asp?char="+NewAgent.toLowerCase(),"_blank","top=2000px");
}
AgentLoad = true;
Agent = MSAgent.Characters.Character(AgentID);
Agent.LanguageID = 0x0409;
if(remote) {
AgentStateRequest = Agent.get("state", "Showing, Thinking, Hiding");
AgentAnimationRequest = Agent.get("animation", "GetAttention, GetAttentionContinued, GetAttentionReturn");
}
Agent.MoveTo(400, 300);
Agent.Show();
Agent.Play("GetAttention");
Agent.Play("GetAttentionContinued");
Agent.Play("GetAttentionReturn");
Agent.speak("Hi, I am " + NewAgent + "!");
Agent.think("Oh so bad, I just wanna take a nap...");
return;
}
LoadAgent("Merlin");
</Script>
MSAgent Select :
<SELECT name="Agent_select" onchange="LoadAgent(this[this.selectedIndex].text)">
<OPTION>Merlin</OPTION>
<OPTION>Peedy</OPTION>
<OPTION>Genie</OPTION>
<OPTION>Robby</OPTION>
</SELECT>
注意到窗口底部状态栏的显示了吗?虽然无法获取具体的下载进度,但是至少也可以让浏览者知道角色的动作为什么会有停顿(这个停顿只在某动画第一次调用的时候出现,调用后该动画会被缓存)。
更多的事件说明请参看 msdn.microsoft.com/library/en-us/msagent/paface_2xet.asp 但是浏览器所调用的 MSAgeng 对象并不是所有的事件都支持。
七、我的菜单:
右键点击角色是不是会弹出一个菜单?什么,只有 Hide 一项?想不想定义一个个性的菜单呢?
程序代码:
<object style="visibility:hidden" id="MSAgent" classid="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F"></object>
<Script Language="JavaScript" For="MSAgent" Event="Command(UserInput)">
switch(UserInput.Name) {
case "INTRO" :
Agent.Play("Explain");
Agent.Speak("My name is " + AgentID + ", I think I'm the best one!");
break;
case "AUTHOR":
Agent.Play("Announce");
Agent.Speak("Windy_sk <windy_sk@126.com> wrote the program, I think he's great! (^o^)");
break;
case "SAYTIME":
Agent.Play("Suggest");
Agent.Speak("It is now " + (new Date()) + "!");
break;
case "FLY":
Agent.MoveTo(Math.round(Math.random() * screen.width), Math.round(Math.random() * screen.height));
break;
case "STOP":
Agent.StopAll();
Agent.Play("RestPose");
break;
default:
break;
}
</Script>
<script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var Agent = null;
var AgentID, AgentACS;
var AgentLoad = false;
function LoadAgent(NewAgent) {
var remote = false;
if(AgentLoad) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
}
AgentID = NewAgent;
AgentACS = NewAgent + ".acs";
MSAgent.Connected = true;
try {
MSAgent.Characters.Load(AgentID, AgentACS);
window.status = "Local MSAgent load successfully!";
} catch(e) {
AgentACS = "http://agent.microsoft.com/agent2/chars/" + NewAgent + "/" + NewAgent + ".acf";
remote = true;
MSAgent.Characters.Load(AgentID, AgentACS);
window.status = "Local MSAgent load unsuccessfully, as a advice, you'd better to download the charactor file to your local disk!";
}
AgentLoad = true;
Agent = MSAgent.Characters.Character(AgentID);
Agent.LanguageID = 0x0409;
Agent.Commands.RemoveAll();
Agent.Commands.Visible = true;
Agent.Commands.Caption = "MSAgent's Menu - by windy_sk";
Agent.Commands.Add("INTRO", "Introduce Yourself", "Introduce yourself");
Agent.Commands.Add("AUTHOR", "Who Write The Program", "Who Write The Program");
Agent.Commands.Add("SAYTIME", "What Time Is It Now", "What Time Is It Now");
Agent.Commands.Add("FLY", "Can You Fly", "Can You Fly");
Agent.Commands.Add("STOP", "Stop All Actions", "Stop All Actions");
if(remote) {
Agent.get("state", "Showing, Hiding");
Agent.get("animation", "Explain, Announce, Suggest");
}
Agent.MoveTo(400, 300);
Agent.Show();
return;
}
LoadAgent("Merlin");
</script>
MSAgent Select :
<SELECT name="Agent_select" onchange="LoadAgent(this[this.selectedIndex].text)">
<OPTION>Merlin</OPTION>
<OPTION>Peedy</OPTION>
<OPTION>Genie</OPTION>
<OPTION>Robby</OPTION>
</SELECT>
个性菜单也是通过对象事件驱动的,这一点相信已经看懂了上一节的读者比较容易理解,相关网页请见 msdn.microsoft.com/library/en-us/msagent/pacontrol_8kfe.asp
Agent.Commands.Add 的三个属性分别为:内部索引标识、显示文字和语音表示,前两个参数比较容易理解,关键是第三个参数“语音表示”,对用户可以通过语音来控制 MSAgent !
你需要首先下载 MicroSoft 语音识别引擎 activex.microsoft.com/activex/controls/agent2/actcnc.exe (目前只支持美国英语),下面介绍一下语音参数的句法:
Agent.Commands.Add("SAYTIME", "What Time Is It Now", "What Time Is It Now" 中 "What Time Is It Now" 是它的语音表示,但是必须要完全读出这几个单词才可以识别吗?如果要是问时间的话,我可以说 What Time , Tell me the time 或者直接只说 time ,但是如何让程序识别这些话为统一目的呢? 可以这样写:[(What|Tell me the)] Time [is it] [Now] [please] ,熟悉一点正则的读者应该不难理解,[] 表示可选项, () 规定范围, | 表示逻辑或
单纯这样还不够,还要在 <Script Language="JavaScript" For="MSAgent" Event="Command(UserInput)"> 加上相应的声音处理:
程序代码:
<Script Language="JavaScript" For="MSAgent" Event="Command(UserInput)">
var BadConfidence = 10;
if (UserInput.Confidence <= -40){
alert("Bad Recognition!");
} else if ((UserInput.Alt1Name != "") && (Math.abs(Math.abs(UserInput.Alt1Confidence) - Math.abs(UserInput.Confidence)) < BadConfidence)) {
alert("Bad Confidence - too close to another command !");
} else if ((UserInput.Alt2Name != "") && (Math.abs(Math.abs(UserInput.Alt1Confidence) - Math.abs(UserInput.Confidence)) < BadConfidence)) {
alert("Bad Confidence - too close to another command !");
} else {
switch(UserInput.Name) {
case "ACO" :
MSAgent.PropertySheet.Visible = true;
break;
case "READ":
Agent_Show("Read");
Agent.Speak(show.value);
break;
case "SAYTIME":
Agent_Show("Suggest");
Agent.Speak("It is now " + (new Date()) + "!");
break;
case "INTRO" :
Agent_Show("Explain");
Agent.Speak("My name is " + AgentID + ", I think I'm the best one!");
break;
case "AUTHOR":
Agent_Show("Announce");
Agent.Speak("Windy_sk <windy_sk@126.com> wrote the program, I think he's great! (^o^)");
break;
case "FLY":
Agent.MoveTo(Math.round(Math.random() * screen.width - Agent.width), Math.round(Math.random() * screen.height - Agent.height));
break;
case "STOP":
Agent.StopAll();
Agent_Show("RestPose");
break;
default:
break;
}
}
</Script>
else 语句上面的部分是对用户的语音输入作判断,相关参数意义请见这里:http://msdn.microsoft.com/library/en-us/dnexpvb/html/usingmsagentcontrolevents.asp
有关 Command 对象的其他方法,请见 msdn.microsoft.com/library/en-us/dnexpvb/html/workingwithcommands.asp
八、归纳总结:
主要涉及到的基本方法都已经讲过了,是不是对 MSAgent 又有了一个新的认识?感觉现在写程序的话缺少的仅仅是创意了……
下面,我们就把上面所了解到的东西做一个归纳总结性质的实践,Charactors From Office 是从硬盘上搜索出的 *.acs 文件 copy 到 %windows%\MSAgent\Chars 目录下的角色文件,读者自己搜索添加吧,里面的功能有一些前文没有涉及到的,读者可以研究一下:
程序代码:
<style>
*{font-size: 12px}
</style>
<Object style="visibility:hidden" id="MSAgent" ClassID="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F" CodeBase="http://activex.microsoft.com/activex/controls/agent2/MSagent.exe#VERSION=2,0,0,0"></Object>
<Object style="visibility:hidden" id="L&HTruVoice" ClassID="CLSID:B8F2846E-CE36-11D0-AC83-00C04FD97575" CodeBase="http://activex.microsoft.com/activex/controls/agent2/tv_enua.exe#VERSION=6,0,0,0"></Object>
<Script Language="JavaScript" For="MSAgent" Event="RequestStart(RequestObject)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
switch (RequestObject) {
case AgentLoadRequest :
window.status = "Loading MSAgent File From Internet For " + AgentID + " ...";
break;
case AgentStateRequest :
window.status = "Loading MSAgent State From Internet For " + AgentID + " ...";
break;
case AgentAnimationRequest :
window.status = "Loading MSAgent Animation From Internet For " + AgentID + " ...";
break;
default:
break;
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="RequestComplete(RequestObject)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
switch (RequestObject) {
case AgentLoadRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent File For " + AgentID + " Has Been Loaded Successfully !";
if(confirm("Cannot find the MSAgent charactor file on your hard disk! \nWould you like to download the MSAgent charactor file for the next show?"))
window.open("http://www.msagentring.org/download.asp?char="+NewAgent.toLowerCase(),"_blank","top=2000px");
} else {
window.status = "Cannot Load MSAgent File For " + AgentID + " From " + AgentACS + " !";
alert("Cannot find MSAgent file from local disk or internet!");
AgentLoad = false;
}
break;
case AgentStateRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent State For " + AgentID + " Has Been Loaded Successfully !";
} else {
window.status = "Cannot Load MSAgent State For " + AgentID + " From " + AgentACS + " !";
}
break;
break;
case AgentAnimationRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent Animation For " + AgentID + " Has Been Loaded Successfully !";
} else {
window.status = "Cannot Load MSAgent Animation For " + AgentID + " From " + AgentACS + " !";
}
break;
break;
default:
window.status = "";
break;
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Click(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(Button==1 && Agent.Visible) {
Agent.Stop();
Agent_Show("Acknowledge", "Yes sir! " + CharacterID + " is right here!");
Agent_Show("Pleased", "What can I do for you?");
} else if(Button==4097) {
Agent.Visible?Agent.Hide():Agent.show();
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DblClick(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(Button==1 || Button==4097) {
Agent.StopAll();
if (!Agent.HasOtherClients) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
AgentLoad = false;
}
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Move(CharacterID, X, Y, Cause)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var rnd_words = new Array();
rnd_words.push("Ha, I am the king of screen!");
rnd_words.push("It's good day to fly!");
rnd_words.push("Ah, your boss is on your back!");
rnd_words.push("Oh, it's fruit time, do you want an apple?");
rnd_words.push("How do you think about me?");
rnd_words.push("Hey guy, have a rest!");
rnd_words.push("Pretty girl everywhere, single me over there...");
rnd_words.push("Hi, don't you think I like neo in Matrix?");
rnd_words.push("If you think it, you will make it!");
rnd_words.push("I am so lonely, together with me, come on!");
if(Cause==2) {
Agent_Show("random", rnd_words[GetRandomNum(0, rnd_words.length-1)]);
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DragStart(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
cur_x = X - Agent.width/2;
cur_y = Y - Agent.height/2;
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DragComplete(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
Agent.Stop();
Agent_Show("Confused", "Don't move me OK?", "RestPose");
Agent.MoveTo(cur_x, cur_y);
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Command(UserInput)">
var BadConfidence = 10;
if (UserInput.Confidence <= -40){
alert("Bad Recognition!");
} else if ((UserInput.Alt1Name != "") && (Math.abs(Math.abs(UserInput.Alt1Confidence) - Math.abs(UserInput.Confidence)) < BadConfidence)) {
alert("Bad Confidence - too close to another command !");
} else if ((UserInput.Alt2Name != "") && (Math.abs(Math.abs(UserInput.Alt1Confidence) - Math.abs(UserInput.Confidence)) < BadConfidence)) {
alert("Bad Confidence - too close to another command !");
} else {
switch(UserInput.Name) {
case "ACO" :
MSAgent.PropertySheet.Visible = true;
break;
case "READ":
Agent_Show("Read");
Agent.Speak(show.value);
break;
case "SAYTIME":
Agent_Show("Suggest");
Agent.Speak("It is now " + (new Date()) + "!");
break;
case "INTRO" :
Agent_Show("Explain");
Agent.Speak("My name is " + AgentID + ", I think I'm the best one!");
break;
case "AUTHOR":
Agent_Show("Announce");
Agent.Speak("Windy_sk <windy_sk@126.com> wrote the program, I think he's great! (^o^)");
break;
case "FLY":
Agent.MoveTo(Math.round(Math.random() * screen.width - Agent.width), Math.round(Math.random() * screen.height - Agent.height));
break;
case "STOP":
Agent.StopAll();
Agent_Show("RestPose");
break;
default:
break;
}
}
</Script>
<Script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
function reportError(msg,url,line) {
var str = "You have found an error as below: \n\n";
str += "Err: " + msg + " on line: " + line;
alert(str);
return true;
}
window.onerror = reportError;
var Agent = null;
var AgentID, AgentACS;
var AgentLoad = false;
var AgentLoadRequest, AgentStateRequest, AgentAnimationRequest;
var AgentStates = "GesturingDown, GesturingLeft, GesturingRight, GesturingUp, Hearing, Hiding, IdlingLevel1, IdlingLevel2, IdlingLevel3, Listening, MovingDown, MovingLeft, MovingRight, MovingUp, Showing, Speaking";
var AgentAnimations = ["Acknowledge", "Alert", "Announce", "Blink", "Confused", "Congratulate", "Congratulate_2", "Decline", "DoMagic1", "DoMagic2", "DontRecognize", "Explain", "GestureDown", "GestureLeft", "GestureRight", "GestureUp", "GetAttention", "GetAttentionContinued", "GetAttentionReturn", "Greet", "Hearing_1", "Hearing_2", "Hearing_3", "Hearing_4", "Hide", "Idle1_1", "Idle1_2", "Idle1_3", "Idle1_4", "Idle2_1", "Idle2_2", "Idle3_1", "Idle3_2", "LookDown", "LookLeft", "LookRight", "LookUp", "MoveDown", "MoveLeft", "MoveRight", "MoveUp", "Pleased", "Process", "Processing", "Read", "ReadContinued", "ReadReturn", "Reading", "RestPose", "Sad", "Search", "Searching", "Show", "StartListening", "StopListening", "Suggest", "Surprised", "Think", "Uncertain", "Wave", "Write", "WriteContinued", "WriteReturn", "Writing"];
var remote = false;
var cur_x = 400, cur_y = 300;
var MoveTimer = null;
function LoadAgent(NewAgent) {
if(AgentLoad) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
}
AgentID = NewAgent;
AgentACS = NewAgent + ".acs";
MSAgent.Connected = true;
try {
MSAgent.Characters.Load(AgentID, AgentACS);
} catch(e) {
AgentACS = "http://agent.microsoft.com/agent2/chars/" + NewAgent + "/" + NewAgent + ".acf";
remote = true;
AgentLoadRequest = MSAgent.Characters.Load(AgentID, AgentACS);
}
try {
AgentLoad = true;
Agent = MSAgent.Characters.Character(AgentID);
Agent.LanguageID = 0x0409;
Agent.Balloon.Style = 0x330000F;
Agent.Commands.RemoveAll();
Agent.Commands.Visible = true;
Agent.Commands.Caption = "MSAgent's Menu - by windy_sk";
Agent.Commands.Add("ACO", "Advanced Character Options", "Advanced Character Options");
Agent.Commands.Add("READ", "Read Text In Textarea", "Read Text In Textarea");
Agent.Commands.Add("INTRO", "Introduce Yourself", "Introduce yourself");
Agent.Commands.Add("AUTHOR", "Who Write The Program", "Who Write The Program");
Agent.Commands.Add("SAYTIME", "What Time Is It Now", "What Time Is It Now");
Agent.Commands.Add("FLY", "Can You Fly", "Can You Fly");
Agent.Commands.Add("STOP", "Stop All Actions", "Stop All Actions");
if(remote) {
AgentStateRequest = Agent.get("state", "Showing, Thinking");
AgentAnimationRequest = Agent.get("animation", "GetAttention, RestPose");
}
Agent.MoveTo(cur_x, cur_y);
Agent.Show();
try {
Agent.Play("GetAttention");
} catch(e) {
Agent.Play("RestPose");
}
Agent.speak("Hi, I am " + NewAgent + ", can I help you, sir?");
//Agent.think("Oh so bad, I just wanna take a nap...");
if(remote) AgentStateRequest = Agent.get("state", AgentStates);
} catch(e) {
for(var x in e) alert(x + " - " + e[x]);
AgentLoad = false;
}
return;
}
function GetRandomNum(Min,Max){
var Range = Max - Min;
var Rand = Math.random();
return(Min + Math.round(Rand * Range));
}
function Agent_Show() {
if(!AgentLoad) return;
var argv = Agent_Show.arguments;
var argc = argv.length;
if(!Agent.Visible) Agent.Show();
for(var i=0; i<argc; i+=2) {
if(argv[i] == "random") argv[i] = AgentAnimations[GetRandomNum(0, AgentAnimations.length-1)];
try {
if(remote) Agent.get("animation", argv[i]);
Agent.Play(argv[i]);
} catch(e) {
Agent.Play("RestPose");
}
if(typeof(argv[i+1]) != "undefined" && argv[i+1] != "") Agent.speak(argv[i+1]);
}
return;
}
function Agent_Show_All(mode) {
if(Agent==null || !AgentLoad) return;
if(!Agent.Visible) Agent.Show();
show.value = "Animation for " + AgentID;
for(var i=0; i<AgentAnimations.length; i++){
show.value += "\ntesting '" + AgentAnimations[i] + "' - ";
try {
if(remote) Agent.get("animation", AgentAnimations[i]);
Agent.Play(AgentAnimations[i]);
Agent.speak(AgentID + " can play '" + AgentAnimations[i] + "'!");
show.value += "OK!";
} catch(e) {
Agent.Play("RestPose");
Agent.speak(AgentID + " play '" + AgentAnimations[i] + "' failed !");
show.value += "Failed!";
}
if(!mode) Agent.Stop();
}
return;
}
function Agent_Move(){
if(!AgentLoad) return;
if(GetRandomNum(1, 10) > 6){
var Scr_width = window.screen.width - 100;
var Scr_Height = window.screen.height - 100;
Agent.MoveTo(GetRandomNum(0,Scr_width),GetRandomNum(0,Scr_Height));
}
MoveTimer = setTimeout("Agent_Move()",5000);
return;
}
window.onhelp = function() {
if(!AgentLoad) return;
if(Agent == null) {
LoadAgent(AgentID);
} else {
if(!Agent.Visible) Agent.Show();
Agent.speak("Can I help you, sir?");
}
return false;
}
LoadAgent("Merlin");
</Script>
Charactor Select :
<SELECT name="Agent_select" onchange="LoadAgent(this[this.selectedIndex].text)">
<Optgroup label="Offical Charactors">
<OPTION>Merlin</OPTION>
<OPTION>Peedy</OPTION>
<OPTION>Genie</OPTION>
<OPTION>Robby</OPTION>
</Optgroup>
<Optgroup label="Charactors from Office">
<OPTION>CLIPPIT</OPTION>
<OPTION>courtney</OPTION>
<OPTION>DOLPHIN</OPTION>
<OPTION>DOT</OPTION>
<OPTION>earl</OPTION>
<OPTION>F1</OPTION>
<OPTION>LOGO</OPTION>
<OPTION>MNATURE</OPTION>
<OPTION>MNKYKING</OPTION>
<OPTION>OFFCAT</OPTION>
<OPTION>qmark</OPTION>
<OPTION>ROCKY</OPTION>
<OPTION>rover</OPTION>
<OPTION>SAEKO</OPTION>
</Optgroup>
</SELECT>
<input type="checkbox" id="auto_move" onclick="this.checked?Agent_Move():clearTimeout(MoveTimer)"><label for="auto_move">Auto Move</label>
<br /><br />
<textarea id="show" style="width: 400px; height: 200px">
Hello everybody, I am Office Agent, I hope I am useful to you !
</textarea>
<br />
<input type="button" value="Test Animation" onclick="Agent_Show_All(show_animation.checked)">
<input type="checkbox" id="show_animation"><label for="show_animation">Show Animation</label>
算是个所有方法的大杂烩了,最后说明一下 Balloon 对象,其所有属性中只有 Style 可以更改,而官方所给的资料还不完全 msdn.microsoft.com/library/en-us/msagent/pacontrol_9gtm.asp ,还是自己慢慢挖掘吧……
到这里就算是告一段落吧,不想写了,总感觉看的越多就越不了解,真的开始有点佩服 MicroSoft 了,单这么个冰山一角就涉及到无数的枝节,本文虽然不算很彻底的研究,但是入门级已经是绰绰有余了……
资源:
StartPage: msdn.microsoft.com/library/en-us/msagent/agentstartpage_7gdh.asp
FAQ: msdn.microsoft.com/library/en-us/msagent/paface_3sit.asp
Methods: msdn.microsoft.com/library/en-us/msagent/paface_73c5.asp
Events: msdn.microsoft.com/library/en-us/msagent/paface_2xet.asp
Actions: msdn.microsoft.com/library/en-us/msagent/deschar_3pgy.asp
LanguageId: www.microsoft.com/globaldev/reference/oslocversion.mspx
Balloon: msdn.microsoft.com/library/en-us/msagent/pacontrol_9gtm.asp
Voice: msdn.microsoft.com/library/en-us/dnexpvb/html/usingmsagentcontrolevents.asp
Command: msdn.microsoft.com/library/en-us/dnexpvb/html/workingwithcommands.asp
Download: www.microsoft.com/msagent/downloads/user.asp
www.microsoft.com/msagent/downloads/developer.asp
www.msagentring.org/chars.htm
msagentworld.tripod.com/characters.htm
终结:
本文仅是通过我个人对 MSAgent 的理解,以及以前的操作实践写成的,难免有所缺憾,随时欢迎补充和更正!
有了点时间又作了一点修改,把 Play Speak MoveTo 都设定为通过自定义函数处理,方便控制,又优化了一些细节处理,其实这个东西用好了还是蛮有用处的,关键要看你的创意,例如 BS 系统的 online help 等……
几个提示:
1、利用 RequestComplete 事件可以做事件延时处理(用来处理 Agent 本身行为的排队特性和非 Agent 行为的立即执行特性的矛盾)
2、多个 Agent 可同时调用(只要不 unload),多个 Agent 之间的进程等待可以用 Wait 方法,如: Agent2.Wait(Agent1_Request) 是指 Agent1 的 Request 行为结束后Agent2 再开始下一步的行为!
3、利用 Agent 做函数转意(如 alert 等函数)
程序代码:
<style>
*{font-size: 12px}
</style>
<Object style="visibility:hidden" id="MSAgent" ClassID="CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F" CodeBase="http://activex.microsoft.com/activex/controls/agent2/MSagent.exe#VERSION=2,0,0,0"></Object>
<Object style="visibility:hidden" id="L&HTruVoice" ClassID="CLSID:B8F2846E-CE36-11D0-AC83-00C04FD97575" CodeBase="http://activex.microsoft.com/activex/controls/agent2/tv_enua.exe#VERSION=6,0,0,0"></Object>
<Script Language="JavaScript" For="MSAgent" Event="RequestStart(RequestObject)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
switch (RequestObject) {
case AgentLoadRequest :
window.status = "Loading MSAgent File From Internet For " + AgentID + " ...";
break;
case AgentStateRequest :
window.status = "Loading MSAgent State From Internet For " + AgentID + " ...";
break;
case AgentAnimationRequest :
window.status = "Loading MSAgent Animation From Internet For " + AgentID + " ...";
break;
default:
break;
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="RequestComplete(RequestObject)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
switch (RequestObject) {
case AgentLoadRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent File For " + AgentID + " Has Been Loaded Successfully !";
if(confirm("Cannot find the MSAgent charactor file on your hard disk! \nWould you like to download the MSAgent charactor file for the next show?"))
window.open("http://www.msagentring.org/download.asp?char="+NewAgent.toLowerCase(),"_blank","top=2000px");
} else {
window.status = "Cannot Load MSAgent File For " + AgentID + " From " + AgentACS + " !";
alert("Cannot find MSAgent file from local disk or internet!");
AgentLoad = false;
}
break;
case AgentStateRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent State For " + AgentID + " Has Been Loaded Successfully !";
} else {
window.status = "Cannot Load MSAgent State For " + AgentID + " From " + AgentACS + " !";
}
break;
case AgentAnimationRequest :
if(RequestObject.Status == 0) {
window.status = "MSAgent Animation For " + AgentID + " Has Been Loaded Successfully !";
} else {
window.status = "Cannot Load MSAgent Animation For " + AgentID + " From " + AgentACS + " !";
}
break;
case AgentTemporaryRequest :
Agent_Check_Animation();
break;
default:
window.status = "";
break;
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Click(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(Button==1 && Agent.Visible) {
Agent.Stop();
Agent_Show("Acknowledge", "Yes sir! " + CharacterID + " is right here!");
Agent_Show("Pleased", "What can I do for you?");
} else if(Button==4097) {
Agent.Stop();
Agent.Visible?Agent.Hide():Agent.show();
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DblClick(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(Button==1 || Button==4097) {
Agent.StopAll();
if (!Agent.HasOtherClients) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
AgentLoad = false;
}
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Move(CharacterID, X, Y, Cause)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
var rnd_words = new Array();
rnd_words.push("Ha, I am the king of screen!");
rnd_words.push("It's good day to fly!");
rnd_words.push("Ah, your boss is on your back!");
rnd_words.push("Oh, it's fruit time, do you want an apple?");
rnd_words.push("How do you think about me?");
rnd_words.push("Hey guy, have a rest!");
rnd_words.push("Pretty girl everywhere, single me over there...");
rnd_words.push("Hi, don't you think I like neo in Matrix?");
rnd_words.push("If you think it, you will make it!");
rnd_words.push("I am so lonely, together with me, come on!");
if(Cause==2) {
Agent_Show("random", rnd_words[GetRandomNum(0, rnd_words.length-1)]);
}
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DragStart(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
cur_x = X - Agent.width/2;
cur_y = Y - Agent.height/2;
</Script>
<Script Language="JavaScript" For="MSAgent" Event="DragComplete(CharacterID, Button, Shift, X, Y)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
Agent.StopAll();
Agent_Show("Confused", "Don't move me OK?", "RestPose");
Agent_MoveTo(cur_x, cur_y, true);
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Idle(CharacterID, State)">
//Coded by Windy_sk <windy_sk@126.com> 20040214
if(State) Agent_Show("random", "I am so lonely ...");;
</Script>
<Script Language="JavaScript" For="MSAgent" Event="Command(UserInput)">
var BadConfidence = 10;
if (UserInput.Confidence <= -40){
alert("Bad Recognition!");
} else if ((UserInput.Alt1Name != "") && (Math.abs(Math.abs(UserInput.Alt1Confidence) - Math.abs(UserInput.Confidence)) < BadConfidence)) {
alert("Bad Confidence - too close to another command !");
} else if ((UserInput.Alt2Name != "") && (Math.abs(Math.abs(UserInput.Alt1Confidence) - Math.abs(UserInput.Confidence)) < BadConfidence)) {
alert("Bad Confidence - too close to another command !");
} else {
switch(UserInput.Name) {
case "ACO" :
MSAgent.PropertySheet.Visible = true;
break;
case "READ":
Agent_Read(show.value);
break;
case "SAYTIME":
Agent_Show("Suggest", "It is now " + (new Date()) + "!");
break;
case "INTRO" :
Agent_Show("Explain", "My name is " + AgentID + ", I think I'm the best one!");
break;
case "AUTHOR":
Agent_Show("Announce", "Windy_sk <windy_sk@126.com> wrote the program, I think he's great! (^o^)");
break;
case "FLY":
Agent_MoveTo(Math.round(Math.random() * screen.width - Agent.width), Math.round(Math.random() * screen.height - Agent.height));
break;
case "STOP":
Agent.StopAll();
Agent_Show("RestPose");
break;
default:
break;
}
}
</Script>
<Script language="JavaScript">
//Coded by Windy_sk <windy_sk@126.com> 20040214
function reportError(msg,url,line) {
var str = "You have found an error as below: \n\n";
str += "Err: " + msg + " on line: " + line;
alert(str);
return true;
}
window.onerror = reportError;
var Agent = null;
var AgentID, AgentACS;
var AgentLoad = false;
var AgentLoadRequest, AgentStateRequest, AgentAnimationRequest, AgentTemporaryRequest;
var AgentStates = "GesturingDown, GesturingLeft, GesturingRight, GesturingUp, Hearing, Hiding, IdlingLevel1, IdlingLevel2, IdlingLevel3, Listening, MovingDown, MovingLeft, MovingRight, MovingUp, Showing, Speaking";
var AgentAnimations = ["Acknowledge", "Alert", "Announce", "Blink", "Confused", "Congratulate", "Congratulate_2", "Decline", "DoMagic1", "DoMagic2", "DontRecognize", "Explain", "GestureDown", "GestureLeft", "GestureRight", "GestureUp", "GetAttention", "GetAttentionContinued", "GetAttentionReturn", "Greet", "Hide", "Idle1_1", "Idle1_2", "Idle1_3", "Idle1_4", "Idle2_1", "Idle2_2", "Idle3_1", "LookDown", "LookLeft", "LookRight", "LookUp", "MoveDown", "MoveLeft", "MoveRight", "MoveUp", "Pleased", "Process", "Read", "ReadContinued", "ReadReturn", "RestPose", "Sad", "Search", "Show", "StartListening", "StopListening", "Suggest", "Surprised", "Think", "Uncertain", "Wave", "Write", "WriteContinued", "WriteReturn"];
var AgentAnimations_loop = ["Hearing_1", "Hearing_2", "Hearing_3", "Hearing_4", "Idle3_2", "Processing", "Reading", "Searching", "Writing"];
var AgentAnimations_available = AgentAnimations;
var remote = false;
var cur_x = 400, cur_y = 300;
var MoveTimer = null;
function LoadAgent(NewAgent) {
if(AgentLoad) {
MSAgent.Characters.Unload(AgentID);
MSAgent.Connected = false;
Agent = null;
}
AgentID = NewAgent;
AgentACS = NewAgent + ".acs";
MSAgent.Connected = true;
try {
MSAgent.Characters.Load(AgentID, AgentACS);
} catch(e) {
AgentACS = "http://agent.microsoft.com/agent2/chars/" + NewAgent + "/" + NewAgent + ".acf";
remote = true;
AgentLoadRequest = MSAgent.Characters.Load(AgentID, AgentACS);
}
try {
AgentLoad = true;
Agent = MSAgent.Characters.Character(AgentID);
Agent.LanguageID = 0x0409;
Agent.Balloon.Style = 0x330000F;
Agent.Commands.RemoveAll();
Agent.Commands.Visible = true;
Agent.Commands.Caption = "MSAgent's Menu - by windy_sk";
Agent.Commands.Add("ACO", "Advanced Character Options", "Advanced Character Options");
Agent.Commands.Add("READ", "Read Text In Textarea", "Read Text In Textarea");
Agent.Commands.Add("INTRO", "Introduce Yourself", "Introduce yourself");
Agent.Commands.Add("AUTHOR", "Who Write The Program", "Who Write The Program");
Agent.Commands.Add("SAYTIME", "What Time Is It Now", "What Time Is It Now");
Agent.Commands.Add("FLY", "Can You Fly", "Can You Fly");
Agent.Commands.Add("STOP", "Stop All Actions", "Stop All Actions");
if(remote) {
AgentStateRequest = Agent.get("state", "Showing, Thinking");
AgentAnimationRequest = Agent.get("animation", "GetAttention, RestPose");
}
Agent.MoveTo(screen.width - 200, 100);
Agent.Show();
try {
Agent.Play("GetAttention");
} catch(e) {
Agent.Play("RestPose");
}
Agent.speak("Hi, I am " + NewAgent + ", can I help you, sir?");
AgentTemporaryRequest = Agent.Play("RestPose");
//Agent.think("Oh so bad, I just wanna take a nap...");
if(remote) AgentStateRequest = Agent.get("state", AgentStates);
} catch(e) {
for(x in e) alert(x + " - " + e[x]);
AgentLoad = false;
}
return;
}
function GetRandomNum(Min,Max){
var Range = Max - Min;
var Rand = Math.random();
return(Min + Math.round(Rand * Range));
}
function Agent_Read(text) {
if(!AgentLoad) return;
var txt_arr = text.split("\n");
Agent_Show("Read");
for(var i=0; i<txt_arr.length; i++) {
if(txt_arr[i] != "") Agent.Speak(txt_arr[i]);
}
Agent_Show("ReadContinued");
Agent.Speak("Over, Sir!");
Agent_Show("ReadReturn");
return;
}
function Agent_MoveTo(x, y, mode) {
if(!AgentLoad) return;
if(!/^\d+$/.test(x+y)) return;
if(!Agent.Visible || typeof(mode)=="undefined") {
Agent.MoveTo(x, y);
} else {
Agent.Hide();
Agent.MoveTo(x, y);
Agent.Show();
}
return;
}
function Agent_Show() {
if(!AgentLoad) return;
var argv = Agent_Show.arguments;
var argc = argv.length;
if(!Agent.Visible) Agent.Show();
for(var i=0; i<argc; i+=2) {
if(argv[i] == "random") argv[i] = AgentAnimations_available[GetRandomNum(0, AgentAnimations_available.length-1)];
try {
if(remote) Agent.get("animation", argv[i]);
Agent.Play(argv[i]);
} catch(e) {
Agent.Play("RestPose");
}
if(typeof(argv[i+1]) != "undefined" && argv[i+1] != "") Agent.speak(argv[i+1]);
}
return;
}
function Agent_Check_Animation() {
if(Agent==null || !AgentLoad) return;
if(!Agent.Visible) Agent.Show();
AgentAnimations_available = new Array();
for(var i=0; i<AgentAnimations.length; i++){
try {
if(remote) Agent.get("animation", AgentAnimations[i]);
Agent.Play(AgentAnimations[i]);
AgentAnimations_available.push(AgentAnimations[i]);
} catch(e){}
Agent.Stop();
}
return;
}
function Agent_Show_All() {
if(Agent==null || !AgentLoad) return;
if(!Agent.Visible) Agent.Show();
Agent.StopAll();
for(var i=0; i<AgentAnimations_available.length; i++){
try {
if(remote) Agent.get("animation", AgentAnimations_available[i]);
Agent.Play(AgentAnimations_available[i]);
Agent.speak(AgentID + " can play '" + AgentAnimations_available[i] + "'!");
} catch(e) {
Agent.Play("RestPose");
Agent.speak(AgentID + " play '" + AgentAnimations_available[i] + "' failed !");
}
}
return;
}
function Agent_Rnd_Move(){
if(!AgentLoad) return;
if(GetRandomNum(1, 10) > 6){
var Scr_width = window.screen.width - 100;
var Scr_Height = window.screen.height - 100;
Agent_MoveTo(GetRandomNum(0,Scr_width),GetRandomNum(0,Scr_Height));
}
MoveTimer = setTimeout("Agent_Rnd_Move()",5000);
return;
}
window.onhelp = function() {
if(!AgentLoad) return;
if(Agent == null) {
LoadAgent(AgentID);
} else {
if(!Agent.Visible) Agent.Show();
Agent.speak("Can I help you, sir?");
}
return false;
}
LoadAgent("Merlin");
var org_alert = window.alert;
window.alert = Agent_Read;
</Script>
Charactor Select :
<SELECT name="Agent_select" onchange="LoadAgent(this[this.selectedIndex].text)">
<Optgroup label="Offical Charactors">
<OPTION>Merlin</OPTION>
<OPTION>Peedy</OPTION>
<OPTION>Genie</OPTION>
<OPTION>Robby</OPTION>
</Optgroup>
<Optgroup label="Charactors from Office">
<OPTION>CLIPPIT</OPTION>
<OPTION>courtney</OPTION>
<OPTION>DOLPHIN</OPTION>
<OPTION>DOT</OPTION>
<OPTION>earl</OPTION>
<OPTION>F1</OPTION>
<OPTION>LOGO</OPTION>
<OPTION>MNATURE</OPTION>
<OPTION>MNKYKING</OPTION>
<OPTION>OFFCAT</OPTION>
<OPTION>qmark</OPTION>
<OPTION>ROCKY</OPTION>
<OPTION>rover</OPTION>
<OPTION>SAEKO</OPTION>
</Optgroup>
</SELECT>
<input type="checkbox" id="auto_move" onclick="this.checked?Agent_Rnd_Move():clearTimeout(MoveTimer)"><label for="auto_move">Auto Move</label>
<br /><br />
Speak Text: <br />
<textarea id="show" style="width: 400px; height: 70px">
Hello everybody,
I am Office Agent,
I think I may useful to you !
</textarea>
<br />
<br />
<input type="button" value="Read Textarea" onclick="Agent_Read(show.value)">
<input type="button" value="Test Animation" onclick="Agent_Show_All(); show.value = show.defaultValue + '\n' + AgentID + ' can play the following actions: \n' + AgentAnimations_available.join('\n');">
cnbruce的借花献佛:
程序代码:
<html>
<head>
<style>button{width:100;border:outset 2;}</style>
</head>
<body bgcolor=threedface scroll=auto>
<button onclick= Merlin.Play("RestPose") >复位
<button onclick= Merlin.Stop() >停止
<button onclick= Merlin.Play("Acknowledge") >点头
<button onclick= Merlin.Play("Surprised") >惊讶
<button onclick= Merlin.Play("GestureUp") >手势
<button onclick= Merlin.Play("Pleased") >满足
<button onclick= Merlin.Play("Alert") >警告
<button onclick= Merlin.Play("Announce") >宣布
<button onclick= Merlin.Play("Blink") >眨眼
<button onclick= Merlin.Play("Confused") >困惑
<button onclick= Merlin.Play("Congratulate") >恭喜1
<button onclick= Merlin.Play("Congratulate_2") >恭喜2
<button onclick= Merlin.Play("Decline") >拒绝
<button onclick= Merlin.Play("DoMagic1") >变魔术1
<button onclick= Merlin.Play("DoMagic2") >变魔术2
<button onclick= Merlin.Play("DontRecognize") >没听清
<button onclick= Merlin.Play("Explain") >说明
<button onclick= Merlin.Play("GetAttention") >敲一下
<button onclick= Merlin.Play("GetAttentionContinued") >不停敲
<button onclick= Merlin.Play("GetAttentionReturn") >不敲了
<button onclick= Merlin.Play("Greet") >问候
<button onclick= Merlin.Play("Hearing_1") >听1
<button onclick= Merlin.Play("Hearing_2") >听2
<button onclick= Merlin.Play("Hearing_3") >听3
<button onclick= Merlin.Play("Hearing_4") >听4
<button onclick= Merlin.Play("Idle1_1") >1-1
<button onclick= Merlin.Play("Idle1_2") >1-2
<button onclick= Merlin.Play("Idle1_3") >1-3
<button onclick= Merlin.Play("Idle1_4") >1-4
<button onclick= Merlin.Play("Idle2_1") >2-1
<button onclick= Merlin.Play("Idle2_2") >2-2
<button onclick= Merlin.Play("Idle3_1") >3-1
<button onclick= Merlin.Play("Idle3_2") >3-2
<button onclick= Merlin.Play("LookDown") >俯视
<button onclick= Merlin.Play("LookDownBlink") >俯视眨眼
<button onclick= Merlin.Play("LookDownReturn") >俯视眨眼返回
<button onclick= Merlin.Play("MoveUp") >上移
<button onclick= Merlin.Play("MoveDown") >下移
<button onclick= Merlin.Play("MoveLeft") >左移
<button onclick= Merlin.Play("MoveRight") >右移
<button onclick= Merlin.Play("Process") >熬汤
<button onclick= Merlin.Play("Processing") >熬汤
<button onclick= Merlin.Play("Read") >读
<button onclick= Merlin.Play("ReadReturn") >不读了
<button onclick= Merlin.Play("Reading") >正在读
<button onclick= Merlin.Play("ReadContinued") >不停读
<button onclick= Merlin.Play("Sad") >悲哀
<button onclick= Merlin.Play("Search") >查找
<button onclick= Merlin.Play("Searching") >正在查找
<button onclick= Merlin.Play("StartListening") >听
<button onclick= Merlin.Play("StopListening") >捂耳朵
<button onclick= Merlin.Play("Suggest") >暗示
<button onclick= Merlin.Play("Uncertain") >想飞
<button onclick= Merlin.Play("Wave") >挥手
<button onclick= Merlin.Play("Write") >写东西
<button onclick= Merlin.Play("WriteContinued") >不停写
<button onclick= Merlin.Play("WriteReturn") >不写了
<button onclick= Merlin.Think("fly") >想
<button onclick= doalert('something') >说
<script>
function doalert(text) {
Merlin.Speak(text);
}
</script>
<Object ID=agent ClassID=CLSID:D45FD31B-5C6E-11D1-9EC1-00C04FD7081F></Object>
<script>
var MerlinID;
var MerlinACS;
agent.Connected=true;
MerlinLoaded=LoadLocalAgent(MerlinID,MerlinACS);
Merlin=agent.Characters.Character(MerlinID);
Merlin.Show();
function LoadLocalAgent(CharID,CharACS){
LoadReq=agent.Characters.Load(CharID,CharACS);
return(true);
}
</script>
</body>
</html>