Torque Script入门教程

 
      
一.            基本语法不同
1.    字符串的比较.                                                                 
C++中可以通过重载运算符实现比较,Torque Script则直接用$=和!$=进行比较,或者通过脚本内置函数strcmp进行比较.
 
2.    变量表示
脚本中没有类型(实际上都是c++的字符串),即无须声明即可使用,并且变量的命名并不区分大小写.即%var1和%vaR1是一个变量.
变量有3种写法,分别是%前缀表示局部变量,只能在局部使用.$前缀表示全局变量,可以在任何地方使用.还有一种没有前缀的,类似于全局变量的使用,实际上在引用该变量的时候也可以加引号来表示.如下例子中的 myClientConnection,跟” myClientConnection”是一回事.
 
new GameConnection (myClientConnection);
       if ( $JoinGameAddress !$= "" )
        myClientConnection . connect ( $JoinGameAddress );
    // 等同于 ”myClientConnection” . connect ( $JoinGameAddress );
       else
myClientConnection . connectLocal();
这个例子 new 了一个 GameConnection 对象,然后调用他的方法 connect 连接到服务器 .
 
还有一种 标记字符串 ,如下例子可以说明它与一般字符串的不同之处 .
              $testN = 'nihao' ; //TGE 会给标记符号和它的唯一标示数字
echo ( $testN );
$testN = StripMLControlChars ( $testN );
// 这里可以去掉标记符号 .
echo ( $testN );
          后面我们也会看到它的应用
3.字符串相加
Script中字符串相加用@, 例如:%myName@”你好”
 
 
 
 
二.脚本中的面向对象支持
这里主要通过OO的三个基本要素阐述脚本对于OO的支持程度.
1.    封装:
脚本支持在内置对象基础上添加成员变量和函数.但是并不支持自定义类
类似c++中 class myClass{};之类的声明是不存在的.
如下例中,AiPlayer的成员变量path和函数spawn(相对于c++中的类静态函数)
和followPath(类成员函数)
function AIPlayer :: spawn( %name , %spawnPoint )
{
        // Create the demo player object
        %player = new AiPlayer () {
                    dataBlock = DemoPlayer;
                   path = "" ;
              };
%player.followPath( "MissionGroup/Paths/Path1" , - 1 );
        MissionCleanup . add( %player );
        %player . setShapeName( %name );
         %player . setTransform( %spawnPoint );
         return %player ;
}
 
function AIPlayer :: followPath( %this , %path , %node )
{
           // Start the player following a path
         %this . stopThread( 0 );
        if ( ! isObject ( %path )) {
                %this . path = "" ;
                return ;
           }
        if ( %node > %path . getCount() - 1 )
            %this . targetNode = %path . getCount() - 1 ;
        else
            %this . targetNode = %node ;
        if ( %this . path $= %path )
            this . moveToNode( %this . currentNode);
       else {
            %this . path = %path ;
            %this . moveToNode( 0 );
        }
}
 
脚本中有一个特殊的关键字 ,datablock, 它类似与 c++ 中的 struct, 当脚本被加载之后,
就会为该数据块分配内存 , client 连接到服务器的时候,所有的 datablock 都被发送到客户端 .
2.   继承:
 
脚本通过 activatePackage deactivatePackage 实现了类似继承的机制 .
最先加载的 package 作为父类接口 . 随后加载的作为其子类.以此类推 .
在调用时,首先调用最底层的 package. 具体例子可以在 demo 工程中搜索 activatePackage.
当一个被加载的脚本中,一个函数有多个实现时,会调用离最后被加载的那个函数实现 .
 
3.   多态
脚本并不支持于c++多态类似的语法和功能.
三.脚本重要函数和类介绍:
1. commandToServer和commandToClient函数
服务器和客户端通信的接口.其中前者是向服务器发包,后者是向客户端发.
如下例子:
commandToClient(%client, ‘sendMsg’, %text);
客户端负责接收clientCmdSendMsg(%text);
服务器端需要在前端加标示符serverCmd.
或者
commandToClient(%client, ‘sendMsg’, “%1说:%2”, %userName, %msg);
类似于c中的sprintf语法.
2.exec(filename)
编译,执行函数,给变量赋值,加载程序包和数据块.
 
 
 
3.GameConnection类
游戏连接类,UDP发包.类成员函数可以参考 开发大全书上的介绍.这里说一下它的脚本回调函数(通过引擎里面的Con::executef去调用).
C结尾的表示用于客户端回调,其他用于服务器回调
onConnectionTimedOut //C
onConnectionAccepted //C
onConnect
onConnectRequestTimedOut
onConnectionDropped //C
onConnectRequestRejected
onConnectRequest
onConnectionError //C
onDrop
initialControlSet //C
onDataBlocksDone
 
书写回调的一般格式如下 :
function GameConnection :: onConnectionTimedOut( %this )
{
   // Called when an established connection times out
   disconnectedCleanup();
   MessageBoxOK( "TIMED OUT" , "The server connection has timed out." );
}
具体回调函数的参数,可以在引擎代码中进行查询.
 
四.脚本基本实现原理
相关的宏定义:
DECLARE_CONOBJECT(myClass);     脚本类定义
IMPLEMENT_CONOBJECT(myClass); 脚本类声明
ConsoleMethod                                          脚本类方法定义.
 
ConsoleFunction                                        脚本全局函数定义
这里简单介绍一下c++实现脚本的二个重要方式:
1.   根据函数名调用c++中的函数:
关键宏:
#define ConsoleFunction(name,returnType,minArgs,maxArgs,usage1)                         /
      static returnType c##name(SimObject *, S32, const char **argv);                     /static ConsoleConstructor g##name##obj(NULL,#name,c##name,usage1,minArgs,maxArgs); /
      static returnType c##name(SimObject *, S32 argc, const char **argv)
所有的函数都被简化成 returnValue scriptFun(SimObject *obj,int argc, char* argv[]);
根据不同的函数值定义不同的函数指针.主要以下5个函数指针的定义:
typedef const char * (*StringCallback)(SimObject *obj, S32 argc, const char *argv[]);
typedef S32            (*IntCallback)(SimObject *obj, S32 argc, const char *argv[]);
typedef F32          (*FloatCallback)(SimObject *obj, S32 argc, const char *argv[]);
typedef void          (*VoidCallback)(SimObject *obj, S32 argc, const char *argv[]);
typedef bool          (*BoolCallback)(SimObject *obj, S32 argc, const char *argv[]);
如果定义的是脚本全局函数,第一个参数为NULL.
 
ConsoleConstructor::first会把所有的对象通过一个链表串起来.根据函数名字找到相对应的函数指针,调用即可.
2.   根据类名new相应的类,跟mfc的机制类似.
关键宏:
 
#define IMPLEMENT_CONOBJECT(className)                                                            /
   AbstractClassRep* className::getClassRep() const { return &className::dynClassRep; }           /
   AbstractClassRep* className::getStaticClassRep() { return &dynClassRep; }                      /
   AbstractClassRep* className::getParentStaticClassRep() { return Parent::getStaticClassRep(); } /
   ConcreteClassRep<className> className::dynClassRep(#className, 0, -1, 0, className::getParentStaticClassRep())
这个宏建立了一个类的层次.通过在构造函数中建立类之链表.
链表头定义如下:
AbstractClassRep *                  AbstractClassRep::classLinkList = NULL;
动态创建只需要一个个匹配,相等则调用create函数..
virtual AbstractClassRep* getClassRep() const得到该类的所有信息,比如类id,类名和子类,父类的AbstractClassRep等.
通过构造ConcreteClassRep<T>类实现AbstractClassRep之相关接口.
通过virtual ConsoleObject*      create      () const = 0;去根据串名动态的创建对象.
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值