获取Agent角色的动作列表
在VC++中获取Agent角色的动作列表
2001-08-24· ·Adding··yesky
Microsoft Agent是一个能在应用程序用户界面中显示指定的人物造型的ActiveX控件,其动画人物最显著的特点就是造型美观,它一般有两部分:一是精灵本身,另一部分是被称作Balloon的语言提示部分,它能在精灵上方显示出Agent所说的话。Microsoft已经为最新的Agent 2.0提供了4种标准人物造型,它们是Genie、Merlin、Robby、Peedy,下载地址是:http://msdn.microsoft.com/workshop/imedia/agent/agentdl.asp,并公开这些角色的动作列表。这样,在网页或应用程序中使用Play方法就摆出各种不同的姿势,如听、看、读、写等。
但如果能直接从角色文件ACS中获取相应的动作列表就可将Office 2000光盘中所有的"Office助手"角色为己所用!岂不快哉!
ACS是一种单结构角色文件,它将角色数据与动画数据存放在一个文件中,故每个ACS文件都比较大。
ACS文件中,角色动作列表数据是处在角色数据与动画数据之间的某个位置处,该位置的地址是在文件开头第0C字节开始用4个字节来表示的。例如DOT.ACS文件中,角色动作列表数据地址为0007F86D。
将文件指针移至该地址处,角色动作名称就可以看到了。一开始的4个字节表示动作个数,随后是各个动作的相关数据。动作数据中,头4个字节表示动作名称的字符个数,随后便是各个字符数据,注意ACS文件是用双字节来表示一个字符,再往后是2个字节的保留数据、角色数据地址(4个字节)以及角色数据字节数(4个字节)。
上述结构可用图1来表示(以DOT.ACS为例)。
知道了ACS文件中动作列表数据所在的位置,就可用下列Visual C++代码将其读出:
CFile agentFile(m_strFileName,CFile::modeRead| CFile::typeBinary );
unsigned long lAdress, lActNum, lCharNum, i, j;
int ch;
agentFile.Seek(12L,CFile::begin);
agentFile.Read(&lAdress,4);
agentFile.Seek(lAdress,CFile::begin);
agentFile.Read(&lActNum,4);
CString str,strChar;
for (i=0; i str.Empty();
agentFile.Read(&lCharNum,4);
for (j=0; j agentFile.Read(&ch,2);
strChar.Format(_T("%c"),(char)ch);
str = str + strChar;
}
m_listAct.AddString(str);
agentFile.Seek(10L,CFile::current);
}
agentFile.Close();
这样就可在应用程序中加入Agent角色动作列表读取功能,并依照Agent所提供的Play方法将播放这些动作,图2就是一个的例子。
--------------------------------------
shappy:Delphi中的实现。
procedure TForm1.Button9Click(Sender: TObject);
var
c:array[0..3] of char;
plw:PLongWord;
baseAdd:longword;
actCnt,len,i,j:integer;
actName:string;
begin
ListBox1.Clear;
fStream1:=TFileStream.Create( _path+'PEEDY.ACS',fmOpenRead);
fStream1.Position:=$c;
plw:=@(c[0]);
fStream1.Read(c,4);
baseAdd:=plw^+4;
fStream1.Position:=plw^;
fStream1.Read(c,4);
actCnt:=plw^; //action count
for i:=0 to actCnt-1 do begin
fStream1.Read(c,4);
len:=plw^; //action name length
actName:='';
for j:=0 to len-1 do begin
fStream1.Read(c,2);
actName:=actName+c[0];
end;
ListBox1.Items.add(actName);
fStream1.Position:=fStream1.Position+10;
end;
fStream1.free;