烂泥兽吧 关注:6贴子:188
  • 6回复贴,共1
Vjass入门
目录:
1.什么是Vjass
2.Vjass编辑器
3.随意的全局变量声明
4.debug关键字
5.execute
6.库的使用
6.1库里的全局变量
6.2库里的函数
6.3库里的公有成员与私有成员
6.4引用其他库
7.结构的使用
7.1声明一个结构
7.2结构里的全局变量
7.3结构里的函数与变量
7.4结构里的公有成员与私有成员
7.5结构的构造函数
7.6结构的析构函数
7.7结构与数组
7.8结构里的静态成员
7.9全局结构变量的使用
7.10结构的底层信息
8.使用外部文件
1.什么是Vjass
Vjass是一个扩展了的Jass语言,在继承Jass语言所有特性的同时,又添加了很多的功能,这些功能下面都会有介绍.不过,我们要知道,Warcraft只认Jass语言,是不认Vjass的,所以,最终Vjass还是会被翻译成Jass保存到地图中,所以,Jass做不到的,Vjass一样不能做到,而Vjass所做的,就是让工作简单化,这也正是我们学习Vjass的目的所在.
2. Vjass编辑器
普通的WE是不能使用Vjass的.Vjass的语法检查器是Pjass,把Vjass翻译成Jass的工具是JassHelper.如果我们要使用Vjass,我们可以选择JassNewGenPack或是WeHelper.
其中JassNewGenPack可以到这个页面下载:
http://www.wc3campaigns.net/showthread.php?t=90999


IP属地:山西1楼2016-02-16 20:09回复
    3.随意的Globals声明
    我们知道,普通的WE只能通过变量表来声明全局变量,这在修改使用上有很大的不方便之处.在Vjass里,就不必受这种限制了.可以在任意地方,当然,函数的内部除外,来声明全局变量.
    比如下面的代码就是可以的:
    jass: Copy code
    function func_A takes nothing returns nothing
    set temp_timer=CreateTimer()
    endfunction
    globals
    timer temp_timer
    endglobals
    注意到,变量temp_timer居然可以先使用,后声明,这是没有一点错误的.实际上,Vjass在翻译成Jass时会把所有的全局变量的声明移到脚本文件的最前端.


    IP属地:山西2楼2016-02-16 20:11
    回复
      4.debug关键字
      debug关键字出现在一行代码的前端,当地图以Debug模式保存时,这一行代码运行,否则不运行.
      在JassNewGenPack中,JassHelper菜单下有一个选项,叫DebugMode.如果这个选项被选中,地图将以Debug模式保存.
      请看下面的例子:
      jass: Copy code
      globals
      boolean debug_mode=false
      endglobals
      function TestMode takes nothing returns nothing
      debug set debug_mode=true
      if debug_mode==true then
      call BJDebugMsg("In Debug Mode")
      else
      call BJDebugMsg("In Norme Mode")
      endif
      endfunction
      当上面的函数运行时,如果地图是以DebugMode保存,就会输出:In Debug Mode. 不然,就会输出:In Norme Mode


      IP属地:山西3楼2016-02-16 20:11
      回复
        5.execute
        我们知道ExecuteFunc有很多好处,比如另启线程,可以调用后面定义函数等.不足之处是不能有参数.而execute是一个加强版的ExecuteFunc,可以带参数,可以调用后面的函数.如果仅想调用一个后面的函数,而不开启新的线程,那么可以使用evaluate(), evaluate的使用方法和execute一样,只不过evaluate有一个缺点,就是通过evaluate调用的函数里面,不能使用GetTriggingTrigger这个函数.
        实际上,Vjass把函数名都进行了重翻译,而ExecuteFunc这个函数的参数是一个字符串,很多时候,函数名因为被改动了,导致这个函数的调用失败,因此,Execute函数在Vjass里不推荐使用.
        代之的是execute和evaluate
        execute的使用方法是 function_name.execute(args)
        jass: Copy code
        function test takes nothing returns nothing
        local unit u=GetTriggerUnit()
        local effect f=AddSpecialEffectTarget("Abilities\\Spells\\Undead\\Cripple\\CrippleTarget.mdl",u,"chest")
        call DestroyEffectAfter.execute(f,3.0)
        set u=null
        set f=null
        endfunction
        function DestroyEffectAfter takes effect fx, real t returns nothing
        call TriggerSleepAction(t)
        call DestroyEffect(fx)
        endfunction


        IP属地:山西4楼2016-02-16 20:12
        回复
          6.库的使用
          在学习的过程中,你很可能自己写过了一些认为有用的函数,以后做图的时候,都是直接导入.导入时为了方便调用,一般都是放在Jass脚本的前端.不过,有时呢,你也想使用其他人的函数集,那么,这个函数集也有必要放在地图的前端.然而,如果你们两个人的函数集有冲突呢?或者说,来回把函数复制粘贴到脚本前端这件工作也是很麻烦的.这时,我们有了库的概念.库就是写好的一堆有用的函数或是变量集合,为做图简化工作的.可以把整个Blizzard.j看成一个库.无论库出现在何处,脚本的前端,中间,或是末尾,库里的函数都可以在任意地方被调用.
          库的声明是这样的:
          jass: Copy code
          library library_name
          //这里可以放变量,或是函数
          endlibrary
          6.1库里的全局变量
          库的里面是可以有全局变量的.例如:
          jass: Copy code
          library zhuzhu
          globals
          integer index=0
          endglobals
          endlibrary
          6.2库里的函数
          库的主要功能就是放函数与变量了.
          jass: Copy code
          library zhuzhu
          globals
          integer index=0
          endglobals
          function SayHello takes nothing returns nothing
          set index=index+1
          call BJDebugMsg("Hello")
          endfunction
          function Test takes noting returns nothing
          call SayHello()
          endfunction
          endlibrary
          function Test2 takes noting returns nothing
          call SayHello()
          endfunction
          上面,Test在库的里面调用了SayHello函数,Test2在库的外面调用了SayHello函数,这都没有错.
          6.3库里的公有成员和私有成员
          公有成员和私有成员的划分才是库存在的意义.上面讲到,两个人写的代码,可能存在一个同名函数,如果使用Jass,那么我们可能要把这个函数改成不同名,之后改写整个代码.然而,对于Vjass,只需把函数声明在不同的库里,这样,同名函数也不会冲突了.
          库里面的函数或是变量,都可以设置为私有的,私有的部分对于库的外面是不可见的,私有的部分也不会与外面的函数或是变量冲突.
          jass: Copy code
          library zhuzhu
          globals
          private integer index=0
          endglobals
          private function SayHello takes nothing returns nothing
          set index=index+1
          call BJDebugMsg("Hello")
          endfunction
          function Test takes noting returns nothing
          call SayHello()
          endfunction
          endlibrary
          function Test2 takes noting returns nothing
          call SayHello()
          endfunction
          如果编译上面的代码,就会出错.因为Test2函数在库zhuzhu的外面,而Test2却调用了zhuzhu的私有函数SayHello,因此出错.而库里面的函数Test则可以调用SayHello.
          private的好处有二点,一个是避免冲突,一个是保护代码(有的时候,一些函数被不懂的人乱调用,会出错的).
          如何避免冲突呢?我们知道,H2I函数是很常见的,很多人都会用得到.那么我们使用了两个人的代码文件,里面都有H2I,就会冲突.解决办法是把两个人的文件放在两个库里.
          如下:
          jass: Copy code
          library zhuzhu
          private function H2I takes handle h returns integer
          return h
          return 0
          endfunction
          endlibrary
          library titangate
          private function H2I takes handle h returns integer
          return h
          return 0
          endfunction
          endlibrary
          这样,两个H2I放在两个不同的库里面,就不会冲突了.
          6.4引用其他库
          上面讲到,脚本文件的任意地方都可以使用任意库里的函数,无论在函数声明前,还是声明后.但是,有一点例外的是,在一个库里面,是不能使用另一个库里的函数的.
          如果想用,那么要引用这个库.引用使用needs关键字.
          jass: Copy code
          library appale
          //some codes here
          endlibrary
          library zhuzhu needs appale
          //some codes here
          endlibrary
          这样,库zhuzhu里面就可以调用apple里面的函数了.


          IP属地:山西5楼2016-02-16 20:12
          回复
            7.结构的使用
            结构可以说一个数据与操作这些数据的函数结合体吧.比如,我们可以把"单位"看成一个结构.这个结构里面有最大生命值,当前生命值,最大魔法值,当前魔法值,坐标,移动速度等等的数据,还有设置生命,设置魔法,设置坐标,设置所属玩家等等函数.结构也正是Vjass的最强大的所在,因为结构为Vjass带来了面象对象设计.
            先举一个例子来让我们见识一下结构吧:
            jass: Copy code
            struct pair
            integer x
            integer y
            endstruct
            function testpairs takes nothing returns nothing
            local pair A=pair.create()
            set A.x=5
            set A.x=8
            call BJDebugMsg(I2S(A.x)+" : "+I2S(A.y))
            call pair.destroy(A)
            endfunction
            7.1声明一个结构
            结构的声明用struct关键字.
            jass: Copy code
            struct struct_name
            //some codes here
            endstruct
            7.2结构里的全局变量
            结构里面是不可以放全局变量的,但是library里是可以的.library里也可以是全局数组.
            jass: Copy code
            //错误
            struct zhuzhu
            globals
            boolean IsDead=false
            integer array error
            endglobals
            endstruct
            // 正确写法
            library zhuzhu
            globals
            boolean IsDead=false
            integer array no_error
            endglobals
            endlibrary
            7.3结构里的函数与变量
            结构里可以有各种各样的变量,甚至是一个结构类型.
            jass: Copy code
            struct apple
            real height
            boolean is_red
            endstruct
            struct zhuzhu
            apple red_apple
            integer age
            integer array error //这一行错误,结构里不可以有数组类型
            endstruct
            可以看到,zhuzhu里面有两个变量,一个叫red_apple,是apple类型的.一个叫age,是integer类型的.我们还注意到,结构里面的变量前面不用加local修饰.
            不过,虽然结构里的全局变量可以有数组类型,结构里的一般变量是不允许数组类型的.
            结构里的函数一般叫方法,而不叫函数.用method关键字来声明.
            jass: Copy code
            struct apple
            real height
            boolean is_red
            endstruct
            struct zhuzhu
            apple temp
            integer age
            method eat_apple takes apple temp returns nothing
            if this.temp!=0 then
            call BJDebugMsg("I've got a one")
            else
            call BJDebugMsg("Eat apples good for health")
            endmethod
            endstruct
            //some codes
            zhuzhu hldzhuzhu=zhuzhu.create()
            call hldzhuzhu.eat_apple()
            上面的代码中,我们先是声明了一个结构,叫做apple.之后又声明了一个结构,叫zhuzhu. zhuzhu里面有一个方法,叫eat_apple.这个方法里面,我们看到一个新的关键字:this.
            this是一个指针,指向当前结构. this.temp就是指这个结构里的temp.如果不加this,那么就是指参数里面的那个temp.
            最后面两行是如何创建一个结构实例和使用结构里的方法的.
            就像:local timer t=CreateTimer()一样,结构也是要用一个特殊的方法来创建的.这个方法就是create,下面会讲到它,这里只需记住.
            使用一个结构的方法,
            用的是:结构实例名.结构方法名
            而不是:结构名.结构方法名
            所以,上面是:hldzhuzhu.eat_apple()
            而不是zhuzhu.eat_apple(),就像你不能叫人去吃苹果,而必须说,张三,你去吃苹果,也就是必须指定某一个人
            zhuzhu.create()特殊,下面讲.
            7.4结构里的公有成员与私有成员
            结构和上面所讲的库一样,也是有公有成员与私有成员的.默认的成员是公有的,加上private就变成私有的了,私有成员不能在外面被调用,私有变量也不能在外面被使用.
            jass: Copy code
            struct zhuzhu
            private integer age
            private method set_age taeks integer age returns boolean
            if age>0 then
            set this.age=age
            return true
            else
            return false
            endif
            endmethod
            method new_year_come takes nothing returns nothing
            call this.set_age(this.age+1)
            endmethod
            endstruct
            //some codes here
            local zhuzhu hldzhuzhu=zhuzhu.create()
            call hldzhuzhu.new_year_come() //正确,公有方法可以访问
            call hldzhuzhu.set_age(19) //错误,私有方法不能访问
            set hldzhuzhu.age=19 //错误,私有变量不能访问
            7.5结构的构造函数
            上面我们看到了一个奇怪的create函数,这个函数没有声明,就直接用了,而且不是通过"结构实例名.结构方法名"调用,而是通过"结构名.结构方法名"调用.这个函数就是构造函数,调用这个函数,才会生成一个结构实例,正如调用CreateTimer才会生成一个Timer一样.在一个结构里如果没有这个函数,系统会自动生成它.当然,我们可以自己写这个函数.不过,这个create函数的创建要符合下面的原则:
            a.函数是一个static method
            b.返回值是结构名
            c.第一句要调用allocate函数
            比如:
            jass: Copy code
            struct zhuzhu
            private age
            static method create takes integer age returns zhuzhu
            //底层方法,返回一个zhuzhu实例
            local zhuzhu temp=zhuzhu.allocate()
            set temp.age=age //设置变量
            return temp
            endmethod
            endstruct
            //some codes here
            local zhuzhu hldzhuzhu=zhuzhu.create(19)
            create函数可以有参数,但是,create函数里面不可以使用this.
            实际上,调用create时,结构实例还没有生成呢,变量也没有初始化,直到create调用完全,结构实例才得以生成,这时,this才有意义.
            有时,结构里面还有结构,那么构造函数要对内层结构调用构造函数
            jass: Copy code
            struct apple
            real height
            boolean is_red
            endstruct
            struct zhuzhu
            apple an_apple
            integer age
            static method create takes integer age returns zhuzhu
            local zhuzhu temp=zhuzhu.allocate()//底层方法,返回一个zhuzhu实例
            set temp.age=age //设置变量
            set temp.an_apple=apple.create() //这里调用了apple的默认无参构造函数
            return temp
            endmethod
            endstruct


            IP属地:山西6楼2016-02-16 20:16
            回复
              7.6结构的析构函数
              结构实例是占存储空间的(不是内存,而是Vjass数组空间),所以,不用的结构实例一定要记得销毁.销毁一个结构实例用destroy方法.
              jass: Copy code
              struct apple
              real height
              boolean is_red
              endstruct
              struct zhuzhu
              apple an_apple
              integer age
              static method create takes integer age returns zhuzhu
              local zhuzhu temp=zhuzhu.allocate()//底层方法,返回一个zhuzhu实例
              set temp.age=age //设置变量
              set temp.an_apple=apple.create() //这里调用了apple的默认无参构造函数
              return temp
              endmethod
              endstruct
              //some codes here
              local zhuzhu hldzhuzhu=zhuzhu.create(19)
              //some codes here
              call hldzhuzhu.destroy()
              上面的call hldzhuzhu.destroy()就销毁了hldzhuzhu这个变量.但是,我们要看到,zhuzhu内部还有一个结构变量,叫apple,这个apple如何销毁呢?
              可以在call hldzhuzhu.destroy()前加上这么一行:
              call hldzhuzhu.an_apple.destroy()
              但是,每一次销毁一个结构实例都这么加上一行,难免有忘记的.于是,我们可以用onDestroy方法. onDestroy方法在运行destroy方法前自动运行.这个方法可以叫析构函数.函数原型是:
              method onDestroy takes nothing returns nothing
              举例:
              jass: Copy code
              struct apple
              real height
              boolean is_red
              endstruct
              struct zhuzhu
              apple an_apple
              integer age
              static method create takes integer age returns zhuzhu
              local zhuzhu temp=zhuzhu.allocate()//底层方法,返回一个zhuzhu实例
              set temp.age=age //设置变量
              set temp.an_apple=apple.create() //这里调用了apple的默认无参构造函数
              return temp
              endmethod
              method onDestroy takes nothing returns nothing //析构函数
              call this.an_apple.destroy()
              endmethod
              endstruct
              7.7结构与数组
              其实,结构最终是以数组的方法存储的,用数组而不用缓存,大大提高了效率.但是,数组一个明显的不足就是数量限制,数组的容量仅有8192. 不过,这也足够使用了,但是,生成没用的结构实例而不销毁,还是容易达到这个上限的.结构在数组中是一个整数,因而,可以把结构传给任何需要整数的函数. 检查一个handle类型是否为空用null.而检查一个结构是否为空为0. 比如:
              if xxx==0 then //这里,xxx是一个结构实例
              //some codes
              endif
              由于技术上的原因,结构里的普通变量不可以是数组类型,不过结构里的全局变量可以是数组类型的.
              7.8结构里的静态成员
              结构里的成员有两类,一种是没有经过结构初始化就能使用的,一种是经过结构初始化后才能使用的.那种没经过初始化就能使用的叫做静态成员.
              简单的举个例子,构造函数就是静态成员.因为只有能过构造函数才能成生一个结构实例,也就是说,构造函数调用完成时,结构才初始化完毕.而析构函数一定不是静态的,因为还没有初始化,你析构谁呀?
              静态函数或是静态变量统称静态成员..
              静态成员这个结构的所有实例所共享的,而非静态成员则是每一个实例都有自己的数据.
              静态函数里面不可以使用this,也就是不能使用这个实例里面的非静态成员了.
              举个例子吧.
              jass: Copy code
              struct zhuzhu
              private static string country
              static method SetCountry takes string arg returns nothing
              set zhuzhu.country=arg
              endmethod
              endstruct
              //some codes here
              call zhuzhu.SetCountry("China")
              这里,我们没有创建zhuzhu的实例,就可以调用SetCountry函数了.
              想一想,上面我们是不是通过创建local zhuzhu hldzhuzhu=zhuzhu.create()后,再通过hldzhuzhu调用函数的?这里可以通过zhuzhu调用,说明函数是静态的.
              7.9全局结构变量的使用
              可以定义全局的结构变量.不过,全局的结构变量不能初始化.
              jass: Copy code
              globals
              zhuzhu hldzhuzhu //可以
              zhuzhu hldzhuzhu2=zhuzhu.create(19) //不可以
              integer xxx=9 //可以把xxx初始化为9
              endglobals
              7.10结构的底层信息
              library里面的公有函数,在翻译成Jass时是library_name+function_name
              比如:
              jass: Copy code
              library haha
              function hehe takes nothing returns nothing
              //some codes here
              endfunction
              endlibrary
              这时的函数hehe最后会变为:
              function haha_hehe takes nothing returns nothing
              //some codes here
              endfunction
              因此,要想用ExecuteFunc要这样写了:
              call ExecuteFunc("haha_hehe")
              而不是:
              call ExecuteFunc("hehe")
              8.使用外部文件
              比如,你写了一大堆函数,放在一个文件叫zhuzhu.j里面,以后做地图时,想把这个文件搬到你的地图里来,只需把这个文件放在NewGenPack的Jass文件夹里,在你想使用这个文件的触发器页面最前面加上一行字:
              //! import "zhuzhu.j"
              这样,就把整个文件导入了.


              IP属地:山西8楼2016-02-16 20:18
              回复