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;去根据串名动态的创建对象.


本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/ybt631/archive/2007/07/17/1694348.aspx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值