脚本的出现至少给游戏开发带来了两个好处:数据存储的灵活性和逻辑处理的可配置性。“粘合剂”很准确地描述了脚本的作用,一大堆组件接口通过脚本组织形成了具有一定逻辑的应用。
一、作为配置文件
与一般的配置文件不同,由于脚本具有可执行性,所以当脚本作为配置文件时,我们通常并不会主动去读取配置项,而是让脚本自己来执行配置。例如,以Lua为例来配置分辨率、屏幕效果、音效。
-- configure.lua
GameOpt =
{
Resolution = { x = 1024 , y = 768 } ,
PostEffect = { bloom = true , shadow = true , dof = false } ,
Sound = { audio = true , music = false} ,
}
Game:SetResolution(GameOpt.Resolution.x , GameOpt.Resolution.y)
Game:EnableBloom(PostEffect.bloom)
…
Game:EnableMusic(Sound.music)
当脚本系统执行该配置文件后,便完成了所有配置。
二、界面逻辑控制
WOW使用XML+Lua架构实现游戏界面系统,此方法灵活强大但也非常危险,必须小心处理导出给脚本使用的接口。
<!--StatsFrame.xml-->
<Script file="StatsFrame.lua"/>
<Frame name="StatsFrame" setAllPoints="true" frameStrata="DIALOG" hidden="true" parent="UIParent">
<Layers>
<Layer level="ARTWORK">
<FontString name="StatsFrameText" inherits="NumberFontNormal" justifyH="RIGHT" justifyV="BOTTOM">
<Anchors>
<Anchor point="BOTTOMRIGHT">
<Offset>
<AbsDimension x="-16" y="192"/>
</Offset>
</Anchor>
</Anchors>
</FontString>
</Layer>
</Layers>
<Scripts>
<OnLoad>
StatsFrame_OnLoad();
</OnLoad>
<OnUpdate>
StatsFrame_OnUpdate(arg1);
</OnUpdate>
</Scripts>
</Frame>
</Ui>
-- StatsFrame.lua
STATSFRAME_UPDATE_TIME = 0.5;
function ToggleStats()
if ( StatsFrame:IsShown() ) then
StatsFrame:Hide();
else
StatsFrame:Show();
end
end
function StatsFrame_OnLoad()
this.updateTime = 0;
end
function StatsFrame_OnUpdate(elapsed)
local updateTime = this.updateTime - elapsed;
if ( updateTime <= 0 ) then
updateTime = STATSFRAME_UPDATE_TIME;
StatsFrameText:SetText(GetDebugStats());
end
this.updateTime = updateTime;
end
三、游戏逻辑控制
如何让战斗表现更丰富、如何让场景更智能?只要导出足够的接口给脚本使用,他就能实现那些曾经让你头疼的需求。
-- 当xxx Boss进入视野时,改变天气为下雪,并播放战斗音效
function BossEnterView(id)
if(xxx == id) then
Game:ChangeWeather(SNOW)
Game:PlayBattleMusic(id)
end
end
C++中调用脚本的代码片段:
/// load script when enter map
...
char szBuff[MAX_BUFF_SIZE];
snprintf(szBuff , MAX_BUFF_SIZE , "BossEnterView(%d)" , bossid);
/// execute function in script
ScriptSys.ExecuteString(szBuff);