游戏脚本管理 (一)

游戏脚本管理 ()

前言:

在自己制作了单机泡泡堂的游戏之后,感觉应该加入游戏脚本的支持,通过一段时间学习,我将学的一些步骤和经验包括代码写了下来.
 


一、实现以指令为基础的游戏脚本语言

  现在说的是理论方法,你马上可以实现一种以指令为基础的语言。首先设计一组简单的指令,用于显示文本,并加入简单的循环。最终用MessageBox对话框显示出来。

设计语言第一个步骤,建立自己的指令,为了更直观我建立一个指令表,列表如下:

文本控制指令表

命令

参数

描述

PrintString

string

输出字符串

PrintStringLoop

string,count

根据count指定输出次数

NewLine

None

增加一个空行

WaitForKeyPress

None

等待按键

二、编写一个脚本


首先确认你认为所需要的功能,目前它就是上表列的4条指令。它最好为一个标准的文本文件。

PrintString "这是一种以指令为基础的语言"
PrintString "
也是一个简单的脚本代码"
Newline
PrintString "
但它相当的简单"
Newline
PrintStringLoop "
将被输出4次" 4
Newline
PrintString "
等下将执行等待按键操作"
WaitForKeyPress
 

三、编写TScript

这段代码相当简单,主要体现于分解字符串的操作,根据不同的指令来执行不同的代码。

unit uScripting;

interface

uses
  Windows
, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms;

const

 //四个指令的常量定义
  COMMAND_PRINTSTRING
= 'PrintString';
  COMMAND_NEWLINE  
= 'Newline';
  COMMAND_PRINTSTRINGLOOP
= 'PrintStringLoop';
  COMMAND_WAITFORKEYPRESS
= 'WaitForKeyPress';

type
  TScript
= class
 
private
    FCommandList
: TStrings;  //保存脚本
    procedure GetCommand
(Index: integer; var strCommand: string);  //获取一个命令
    procedure GetStrParam
(Index: integer; var strParam: string);  //获取一个字符串参数
    procedure GetIntParam
(Index: integer; var intParam: integer);  //获取一个整形参数
 
public
   
constructor Create;
    destructor Destroy
; override;
    procedure LoadScript
(AFile: string);  //装入脚本
    procedure UnLoadScript
;  //清空脚本
    procedure RunScript
();  //运行脚本
  end
;

implementation

{ TScript }

constructor TScript.Create;
begin
  FCommandList
:= TStringList.Create;
end
;

destructor TScript
.Destroy;
begin
  FCommandList
.Clear;
  FCommandList
.Free;
  inherited Destroy
;
end
;

procedure TScript
.GetCommand(Index: integer; var strCommand: string);
begin
 
if Pos(#32, Trim(FCommandList.Strings[Index])) <> 0 then
    strCommand
:= Trim(Copy(Trim(FCommandList.Strings[Index]), 1, Pos(#32,
      Trim
(FCommandList.Strings[Index]))))
 
else
    strCommand
:= Trim(FCommandList.Strings[Index]);
end
;

procedure TScript
.GetIntParam(Index: integer;
 
var intParam: integer);
var
  cCurrChar        
: string;
  g_iCurrScriptLineChar
: Integer;
begin

  g_iCurrScriptLineChar
:= Pos('"', FCommandList.Strings[Index]) + 1;
  g_iCurrScriptLineChar
:= Pos('"', Copy(FCommandList.Strings[Index],
    g_iCurrScriptLineChar
+ 1, length(FCommandList.Strings[Index]))) +
    g_iCurrScriptLineChar
+ 1;
  intParam
:= 0;

 
while (g_iCurrScriptLineChar <= Length(FCommandList.Strings[Index])) do
  begin
    cCurrChar
:= copy(FCommandList.Strings[Index], g_iCurrScriptLineChar, 1);
   
if (cCurrChar = '#') or (cCurrChar = #13) or (cCurrChar = #10) then
     
break;
   
if (cCurrChar[1] in ['0'..'9']) then
      intParam
:= StrToInt(IntToStr(intParam) + cCurrChar);
    inc
(g_iCurrScriptLineChar, 1);
  end
;

end
;

procedure TScript
.GetStrParam(Index: integer;
 
var strParam: string);
var
  cCurrChar        
: string;
  g_iCurrScriptLineChar
: Integer;
begin

  g_iCurrScriptLineChar
:= Pos('"', FCommandList.Strings[Index]) + 1;
  strParam
:= '';

 
while (g_iCurrScriptLineChar < Length(FCommandList.Strings[Index])) do
  begin
    cCurrChar
:= copy(FCommandList.Strings[Index], g_iCurrScriptLineChar, 1);
   
if (cCurrChar = '"') or (cCurrChar = #13) or (cCurrChar = #10) then
     
break;
    strParam
:= strParam + cCurrChar;
    inc
(g_iCurrScriptLineChar, 1);
  end
;

end
;

procedure TScript
.LoadScript(AFile: string);
begin
 
if FileExists(AFile) then
    FCommandList
.LoadFromFile(AFile)
 
else
    raise Exception
.Create('无效的脚本文件');
end
;

procedure TScript
.RunScript;
var
  strCommand       
: string;
  strParam         
: string;
  intParam         
: integer;
  i                
: Integer;
  iCurr            
: integer;
  sResult          
: string;
begin
 
if FCommandList.Count < 0 then
    Exit
;
  sResult
:= '';

 
for i := 0 to FCommandList.Count - 1 do
  begin
    GetCommand
(i, strCommand);
   
if Uppercase(strCommand) = Uppercase(COMMAND_PRINTSTRING) then  //检查指令是否匹配
    begin
      GetStrParam
(i, strParam);  //获取字符串参数
      sResult
:= sResult + strParam + #13#10;  //保存结果
    end
   
else if UpperCase(strCommand) = UpperCase(COMMAND_PRINTSTRINGLOOP) then
    begin
      GetStrParam
(i, strParam);
      GetIntParam
(i, intParam);  //获取整形参数

     
for iCurr := 0 to intParam - 1 do
      begin
        sResult
:= sResult + strParam + #13#10;  //循环输出次数
      end
;
    end
   
else if UpperCase(strCommand) = UpperCase(COMMAND_NEWLINE) then
    begin
      sResult
:= sResult + #13#10;
    end
   
else if UpperCase(strCommand) = UpperCase(COMMAND_WAITFORKEYPRESS) then
    begin
     
Application.Title := '等待按键';
     
while true do
      begin
       
Application.ProcessMessages;
       
if GetInputState() then
         
break;
      end
;
     
Application.Title := '按键完成'
    end
   
else
    begin
      sResult
:= sResult + '无效指令!' + #13#10;
    end
;

  end
;

 
Application.MessageBox(PAnsiChar(sResult), '运行结果', 0);

end
;

procedure TScript
.UnLoadScript;
begin
  FCommandList
.Clear;
end
;

end
.

 

这里是测试代码。

procedure TGameMain.Button1Click(Sender: TObject); //请在form中放入一个button 后粘贴代码到单击事件中
var
FScript : TScript;
begin
FScript := TScript.Create;
FScript.LoadScript('E:/projects/GameEngine/Scripts/Test.src');  //
修改为你保存脚本的路径
(Sender as TButton).Enabled := FALSE;
FScript.RunScript;  //
等待按键时只需要单击一下form即可继续运行。
(Sender as TButton).Enabled := TRUE;
FScript.Free;
end;

这里是关于上面代码的图解说明:

 

PrintString

NewLine

WaitForKeyPress

RunScript()

 

Text Console

 阅读完上述的内容后,下一回将讲解如何解释向这样的脚本指令:

DrawBitmap "gfx/copyright.bmp"
PlaySound "sound/ambient.wav"
Pause 3000
PlaySound "sound/wipe.wav"
FoldCloseEffectY
DrawBitmap "gfx/ynh_presents.bmp"
PlaySound "sound/ambient.wav"
Pause 3000
PlaySound "sound/wipe.wav"
FoldCloseEffectX
DrawBitmap "gfx/title.bmp"
PlaySound "sound/title.wav"
WaitForKeyPress
PlaySound "sound/wipe.wav"
FoldCloseEffectY
Exit

 

再见!2004年11月

 

  • 0
    点赞
  • 0
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论

打赏作者

S.F.

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值