|
楼主 |
发表于 2012-2-13 21:09:50
|
显示全部楼层
4.5 函数的数据存储及函数间的数据传输
数据存储,一般来说使用变量即可,多个连续的数据,则采用数组。更为复杂的数据也可以采用多维数组存储,相比J下8192个元素上限的数组系统,Galaxy的数组无疑强大很多,但是仍然有个致命的缺陷,那就是数组无法动态声明,即我们必须在编写脚本时确定一个函数的大小。
如我们需要将某个区域内的全部单位放入一个单位数组(不是单位组,是一个数组,变量类型为单位),那么我们要将这个数组的大小设置为多少呢?因为区域内的单位数量不确定,所以我们很有可能因超出数组范围而导致bug产生。当然你也可以使用一个很大的整数来声明数组,如“int[9999]这种”。但这会占用过多内存,导致游戏过慢。
那么,解决方案是什么呢?
解决方案是DataTable。DataTable是数据表(zhCN下SE的翻译,对应的数据集文件指bank)的名称。它很类似WE中的HashTable(简称HT)或GameCache(简称GC)。不过DataTable采用的Key是一个字符串,并非HT的两个整数或GC的两个字符串。相比之下,DataTable的执行效率相当的高,完全不像GC那样缓慢。
因此,解决数组大小问题的方法就是用DataTable替代数组使用。
代码 4-12 DataTable相关函数
[codes=galaxy]
//--------------------------------------------------------------------------------------------------
// Data Table
// - Data tables provide named storage for any script type.
// Table access may be either global or thread-local.
//--------------------------------------------------------------------------------------------------
// Types
const int c_dataTypeUnknown = -1;
const int c_dataTypeAbilCmd = 0;
const int c_dataTypeActor = 1;
const int c_dataTypeActorScope = 2;
const int c_dataTypeAIFilter = 3;
const int c_dataTypeBank = 4;
const int c_dataTypeBool = 5;
const int c_dataTypeByte = 6;
const int c_dataTypeCameraInfo = 7;
const int c_dataTypeCinematic = 8;
const int c_dataTypeColor = 9;
const int c_dataTypeControl = 10;
const int c_dataTypeConversation = 11;
const int c_dataTypeDialog = 12;
const int c_dataTypeDoodad = 13;
const int c_dataTypeFixed = 14;
const int c_dataTypeInt = 15;
const int c_dataTypeMarker = 16;
const int c_dataTypeObjective = 17;
const int c_dataTypeOrder = 18;
const int c_dataTypePing = 19;
const int c_dataTypePlanet = 20;
const int c_dataTypePlayerGroup = 21;
const int c_dataTypePoint = 22;
const int c_dataTypePortrait = 23;
const int c_dataTypeRegion = 24;
const int c_dataTypeReply = 25;
const int c_dataTypeRevealer = 26;
const int c_dataTypeSound = 27;
const int c_dataTypeSoundLink = 28;
const int c_dataTypeString = 29;
const int c_dataTypeText = 30;
const int c_dataTypeTimer = 31;
const int c_dataTypeTransmission = 32;
const int c_dataTypeTransmissionSource = 33;
const int c_dataTypeTrigger = 34;
const int c_dataTypeUnit = 35;
const int c_dataTypeUnitFilter = 36;
const int c_dataTypeUnitGroup = 37;
const int c_dataTypeUnitRef = 38;
const int c_dataTypeWave = 39;
const int c_dataTypeWaveInfo = 40;
const int c_dataTypeWaveTarget = 41;
// General functionality
native void DataTableClear (bool global);
native int DataTableValueCount (bool global);
native string DataTableValueName (bool global, int index);
native bool DataTableValueExists (bool global, string name);
native int DataTableValueType (bool global, string name);
native void DataTableValueRemove (bool global, string name);
// Type-specific value set/get
// - c_dataTypeAbilCmd
native void DataTableSetAbilCmd (bool global, string name, abilcmd val);
native abilcmd DataTableGetAbilCmd (bool global, string name);
// - c_dataTypeActor
native void DataTableSetActor (bool global, string name, actor val);
native actor DataTableGetActor (bool global, string name);
// - c_dataTypeActorScope
native void DataTableSetActorScope (bool global, string name, actorscope val);
native actorscope DataTableGetActorScope (bool global, string name);
// - c_dataTypeAIFilter
native void DataTableSetAIFilter (bool global, string name, aifilter val);
native aifilter DataTableGetAIFilter (bool global, string name);
// - c_dataTypeBank
native void DataTableSetBank (bool global, string name, bank val);
native bank DataTableGetBank (bool global, string name);
// - c_dataTypeBool
native void DataTableSetBool (bool global, string name, bool val);
native bool DataTableGetBool (bool global, string name);
// - c_dataTypeByte
native void DataTableSetByte (bool global, string name, byte val);
native byte DataTableGetByte (bool global, string name);
// - c_dataTypeCameraInfo
native void DataTableSetCameraInfo (bool global, string name, camerainfo val);
native camerainfo DataTableGetCameraInfo (bool global, string name);
// - c_dataTypeCinematic
native void DataTableSetCinematic (bool global, string name, int val);
native int DataTableGetCinematic (bool global, string name);
// - c_dataTypeColor
native void DataTableSetColor (bool global, string name, color val);
native color DataTableGetColor (bool global, string name);
// - c_dataTypeControl
native void DataTableSetControl (bool global, string name, int val);
native int DataTableGetControl (bool global, string name);
// - c_dataTypeConversation
native void DataTableSetConversation (bool global, string name, int val);
native int DataTableGetConversation (bool global, string name);
// - c_dataTypeDialog
native void DataTableSetDialog (bool global, string name, int val);
native int DataTableGetDialog (bool global, string name);
// - c_dataTypeDoodad
native void DataTableSetDoodad (bool global, string name, doodad val);
native doodad DataTableGetDoodad (bool global, string name);
// - c_dataTypeFixed
native void DataTableSetFixed (bool global, string name, fixed val);
native fixed DataTableGetFixed (bool global, string name);
// - c_dataTypeInt
native void DataTableSetInt (bool global, string name, int val);
native int DataTableGetInt (bool global, string name);
// - c_dataTypeMarker
native void DataTableSetMarker (bool global, string name, marker val);
native marker DataTableGetMarker (bool global, string name);
// - c_dataTypeObjective
native void DataTableSetObjective (bool global, string name, int val);
native int DataTableGetObjective (bool global, string name);
// - c_dataTypeOrder
native void DataTableSetOrder (bool global, string name, order val);
native order DataTableGetOrder (bool global, string name);
// - c_dataTypePing
native void DataTableSetPing (bool global, string name, int val);
native int DataTableGetPing (bool global, string name);
// - c_dataTypePlanet
native void DataTableSetPlanet (bool global, string name, int val);
native int DataTableGetPlanet (bool global, string name);
// - c_dataTypePlayerGroup
native void DataTableSetPlayerGroup (bool global, string name, playergroup val);
native playergroup DataTableGetPlayerGroup (bool global, string name);
// - c_dataTypePoint
native void DataTableSetPoint (bool global, string name, point val);
native point DataTableGetPoint (bool global, string name);
// - c_dataTypePortrait
native void DataTableSetPortrait (bool global, string name, int val);
native int DataTableGetPortrait (bool global, string name);
// - c_dataTypeRegion
native void DataTableSetRegion (bool global, string name, region val);
native region DataTableGetRegion (bool global, string name);
// - c_dataTypeReply
native void DataTableSetReply (bool global, string name, int val);
native int DataTableGetReply (bool global, string name);
// - c_dataTypeRevealer
native void DataTableSetRevealer (bool global, string name, revealer val);
native revealer DataTableGetRevealer (bool global, string name);
// - c_dataTypeSound
native void DataTableSetSound (bool global, string name, sound val);
native sound DataTableGetSound (bool global, string name);
// - c_dataTypeSoundLink
native void DataTableSetSoundLink (bool global, string name, soundlink val);
native soundlink DataTableGetSoundLink (bool global, string name);
// - c_dataTypeString
native void DataTableSetString (bool global, string name, string val);
native string DataTableGetString (bool global, string name);
// - c_dataTypeText
native void DataTableSetText (bool global, string name, text val);
native text DataTableGetText (bool global, string name);
// - c_dataTypeTimer
native void DataTableSetTimer (bool global, string name, timer val);
native timer DataTableGetTimer (bool global, string name);
// - c_dataTypeTransmission
native void DataTableSetTransmission (bool global, string name, int val);
native int DataTableGetTransmission (bool global, string name);
// - c_dataTypeTransmissionSource
native void DataTableSetTransmissionSource (bool global, string name, transmissionsource val);
native transmissionsource DataTableGetTransmissionSource (bool global, string name);
// - c_dataTypeTrigger
native void DataTableSetTrigger (bool global, string name, trigger val);
native trigger DataTableGetTrigger (bool global, string name);
// - c_dataTypeUnit
native void DataTableSetUnit (bool global, string name, unit val);
native unit DataTableGetUnit (bool global, string name);
// - c_dataTypeUnitFilter
native void DataTableSetUnitFilter (bool global, string name, unitfilter val);
native unitfilter DataTableGetUnitFilter (bool global, string name);
// - c_dataTypeUnitGroup
native void DataTableSetUnitGroup (bool global, string name, unitgroup val);
native unitgroup DataTableGetUnitGroup (bool global, string name);
// - c_dataTypeUnitRef
native void DataTableSetUnitRef (bool global, string name, unitref val);
native unitref DataTableGetUnitRef (bool global, string name);
// - c_dataTypeWave
native void DataTableSetWave (bool global, string name, wave val);
native wave DataTableGetWave (bool global, string name);
// - c_dataTypeWaveInfo
native void DataTableSetWaveInfo (bool global, string name, waveinfo val);
native waveinfo DataTableGetWaveInfo (bool global, string name);
// - c_dataTypeWaveTarget
native void DataTableSetWaveTarget (bool global, string name, wavetarget val);
native wavetarget DataTableGetWaveTarget (bool global, string name);
[/codes]
对应每一个变量类型,都有两个函数。分别为:
1、存储数据。
native void DataTableSet变量类型标识符 (bool global, string name, 对应变量类型 对应变量类型的存储值);
2、读取数据。
native void DataTableGet变量类型标识符 (bool global, string name);
除此之外,还有六个通用函数:
// General functionality
native void DataTableClear (bool global);
native int DataTableValueCount (bool global);
native string DataTableValueName (bool global, int index);
native bool DataTableValueExists (bool global, string
name);
native int DataTableValueType (bool global, string
name);
native void DataTableValueRemove (bool global, string
name);
作用分别为:清理全部数据(分局域和全局范围);存储总值计数;根据存储的顺序序号获取对应的Key;判断对应Key的值是否存在,对应Key存储的变量类型;删除Key对应的值。
这里的参数global是控制这个DataTable存储数据的有效范围的,类似全局变量与局域变量。
如果我们需要使用一个数组名为I的整数数组,我们可以这样使用
代码 4-12 用DataTable实现数组
[codes=galaxy]
//Const
const string libGAWH_gv_cf_ArraySystemFirstName = "ArraySystem:";
//Function
void libGAWH_cf_ArraySystemSetInt(string lp_ArrayName, int lp_Index, int lp_ArrayData)
{
DataTableSetInt(true, libGAWH_gv_cf_ArraySystemFirstName + lp_ArrayName + IntToString(lp_Index), lp_ArrayData);
}
int libGAWH_cf_ArraySystemGetInt(string lp_ArrayName, int lp_Index)
{
return DataTableGetInt(true, libGAWH_gv_cf_ArraySystemFirstName + lp_ArrayName + IntToString(lp_Index));
}
[/codes]
实际上用这样的函数来处理有点多此一举。直接使用DataTable函数处理也许更好些。
数据存储可以这样解决。下面就是数据传输。
函数间的数据传输,实际上并不难。简单来说,需要传入某函数的数据作为参数即可,需要返回到调用函数的,用返回值即可。
那么,会有什么问题?
问题很多,如函数的多值返回。
所谓多值返回,就是指一个函数返回一个以上的值。而因为函数的return语句只能带一个值,而函数本身会在执行到return语句处退出,所以使用返回值我们只能返回一个值。
当然,聪明的你会想出用复合变量来返回多个值的办法,如用point返回两个fixed。这确实是不错的想法,但是实际中应用范围太窄。
那么用结构体?不幸的是,结构体不能作为函数返回类型。另外,Galaxy也不支持数组作为参数——不是数组元素,而是一个数组本身作为参数——除非我们写一堆参数,然后把数组元素逐一作为实际参数调用。这样的话,仍然是不方便。
那么解决方案是什么?依旧是DataTable,将需要返回的值存储到DataTable中,然后返回DataTable的Key(string变量类型的参数name)即可。然后在调用函数中使用Key与数据序号即可。
Handle值存储结构:
Galaxy下并没有Handle这一类型变量。Handle是WAR3的脚本语言中使用的一种综合变量类型。当然,我们没必要理解它是什么,我们只要知道它的存储方式即可,在实际应用中,我们会用到。
当然这种数据的存储结构也许有其正是名称。这里我暂时称其为Handle存储结构。
这种存储方式说来也简单,它只是一种可循环使用Index(序号)分配方式,具体规则如下:
1、有一个记录使用Index最大值的变量,从0开始递增,在一次游戏过程中,不减少或重置。
2、有一个记录释放(不在使用的)Index值的数组(栈结构),此数组内Index值无序,每当释放一个Index时入栈。
3、当从系统获取一个Index时,优先判断释放Index数组(栈)是否为空(可用元素数量是否为0)。若非空,读取数组最后一个Index值,并将数组元素数量记录减一(相当于出栈);若为空,给出记录使用Index最大值的变量的值,并将此值加一。
关于栈,这里做下说明:
基本概念
栈,是硬件。主要作用表现为一种数据结构,是只能在某一端插入和删除的特殊线性表。它按照后进先出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。
栈是允许在同一端进行插入和删除操作的特殊线性表。允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom);栈底固定,而栈顶浮动;栈中元素个数为零时称为空栈。插入一般称为进栈(PUSH),删除则称为退栈(POP)。栈也称为后进先出表。
栈可以用来在函数调用的时候存储断点,做递归时要用到栈!
以上定义是在经典计算机科学中的解释。
在计算机系统中,栈则是一个具有以上属性的动态内存区域。程序可以将数据压入栈中,也可以将数据从栈顶弹出。在i386机器中,栈顶由称为esp的寄存器进行定位。压栈的操作使得栈顶的地址减小,弹出的操作使得栈顶的地址增大。
栈在程序的运行中有着举足轻重的作用。最重要的是栈保存了一个函数调用时所需要的维护信息,这常常称之为堆栈帧或者活动记录。堆栈帧一般包含如下几方面的信息:
1. 函数的返回地址和参数
2. 临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量。
栈的模型
基本算法
1.进栈(PUSH)算法
①若TOP≥n时,则给出溢出信息,作出错处理(进栈前首先检查栈是否已满,满则溢出;不满则作②);
②置TOP=TOP+1(栈指针加1,指向进栈地址);
③S(TOP)=X,结束(X为新进栈的元素);
2.退栈(POP)算法
①若TOP≤0,则给出下溢信息,作出错处理(退栈前先检查是否已为空栈, 空则下溢;不空则作②);
②X=S(TOP),(退栈后的元素赋给X):
③TOP=TOP-1,结束(栈指针减1,指向栈顶)。
——度娘
Handle存储结构的实例代码这里也给出,大家自己参照规则分析吧,就不做解说了。
代码 4-13 Handle存储结构
[codes=galaxy]
//IndexGetSystem
//Const
const string libGAWH_gv_is_NameIndexSystemFirstName = "IndexSystem:";
const string libGAWH_gv_is_NameIndexSystemDeleteNum = ":DeleteNum:";
const string libGAWH_gv_is_NameIndexSystemDeleteIndex = ":DeleteIndex:";
const string libGAWH_gv_is_NameIndexSystemMaxNum = ":Max:";
const string libGAWH_gv_is_NameIndexSystemLastIndex = ":LastIndex:";
//Functions
int libGAWH_is_IndexSystemGetIndex(string lp_IndexName)
{
int lv_DeleteNum = DataTableGetInt(true, libGAWH_gv_is_NameIndexSystemFirstName + lp_IndexName + libGAWH_gv_is_NameIndexSystemDeleteNum);
int lv_MaxNum = 0;
int lv_LastIndex = 0;
if (lv_DeleteNum == 0)
{
lv_MaxNum = DataTableGetInt(true, libGAWH_gv_is_NameIndexSystemFirstName + lp_IndexName + libGAWH_gv_is_NameIndexSystemMaxNum);
DataTableSetInt(true, libGAWH_gv_is_NameIndexSystemFirstName + lp_IndexName + libGAWH_gv_is_NameIndexSystemMaxNum, lv_MaxNum + 1);
DataTableSetInt(true, libGAWH_gv_is_NameIndexSystemFirstName + lp_IndexName + libGAWH_gv_is_NameIndexSystemLastIndex, lv_MaxNum);
return lv_MaxNum;
}
else
{
lv_DeleteNum =lv_DeleteNum - 1;
DataTableSetInt(true, libGAWH_gv_is_NameIndexSystemFirstName + lp_IndexName + libGAWH_gv_is_NameIndexSystemDeleteNum, lv_DeleteNum);
lv_LastIndex = DataTableGetInt(true, libGAWH_gv_is_NameIndexSystemFirstName + lp_IndexName + libGAWH_gv_is_NameIndexSystemDeleteIndex + IntToString(lv_DeleteNum));
DataTableSetInt(true, libGAWH_gv_is_NameIndexSystemFirstName + lp_IndexName + libGAWH_gv_is_NameIndexSystemLastIndex, lv_LastIndex);
return lv_LastIndex;
}
}
void libGAWH_is_IndexSystemDeleteIndex(string lp_IndexName, int lp_Index)
{
int lv_DeleteNum = DataTableGetInt(true, libGAWH_gv_is_NameIndexSystemFirstName + lp_IndexName + libGAWH_gv_is_NameIndexSystemDeleteNum);
DataTableSetInt(true, libGAWH_gv_is_NameIndexSystemFirstName + lp_IndexName + libGAWH_gv_is_NameIndexSystemDeleteNum, lv_DeleteNum + 1);
DataTableSetInt(true, libGAWH_gv_is_NameIndexSystemFirstName + lp_IndexName + libGAWH_gv_is_NameIndexSystemDeleteIndex + IntToString(lv_DeleteNum), lp_Index);
}
[/codes]
至此,Galaxy的基础知识讲解完毕。想必大家对于整个Galaxy有了大体了解。很有可能你看到这里还是什么都不会,那么请先记住大体的语法结构,变量类别即可,从下一章开始,请打开SC2,我们准备开始实际动手了。 |
|