序言
这个教程假设你已经比较熟练地使用Trigger并有一定的逻辑基础和程序设计基础, Knowning engish is preferable
首先问个问题: 为什么要学JASS?
先看下面的例子:
以下例子可以实现在单位死亡的位置显示5秒的死亡信息(漂浮文字)后并清除死亡信息吗?
例子:
Events:
A unit dies
Conditions:
Actions:
-Floating Text - Create floating text at ((position of (Triggering Unit))
with the message (("A "+(name of (Triggering Unit))) + " dies") with size 20 , red 100, green 100, blue 0, alpha 100.
-Wait 5.00 seconds
-Destroy (last created floating text)
象以上例子, 如果不使用用局部变量, 将无法准确销毁临时漂浮文字. 因为在等待5秒后(-Wait 5.00 seconds), 最近创建的漂浮文字(last created floating text)可能已经不是原来的那个了!)
要达到目的, 必须对JASS有些了解. 教程将对此TRIGGER作进一步的分析.
第一章 变量篇
学新的程序设计语言, 要先学它的变量类型.
首先提醒大家: Jass2是区分大小写的, 如ABcd和ABCD是不一样的.
Jass2 变量类型
变量相当于物件的储存箱子, JASS2很多的变量类型只是个指针(变量地址).
使用变量前必须要首先声明变量类型和变量名称.
看个简单的例子:
local string my1stvar //声明1个字符型局部变量, 起名为my1stvar
set my1stvar = "GreedWind" //把"GreedWind"赋值给变量my1stvar
以后的程序中就可以直接引用/重新赋值my1stvar
变量(除了数组变量)可以在声明语句中初始化, 上面可以简化成:
local string my1stvar = "GreedWind" //声明字符型局部变量my1stvar并赋值为"GreedWind"
JASS2有哪些变量类型呢?
我们用WORLD EDITOR和Jass2变量类型做对照便一目了然了
WORLD EDITOR和JASS变量类型对照表: World Editor 变量名 Jass变量类型
Boolean boolean 布尔型(用于真/假判断)
Destructible destructable 可破坏物
Dialog dialog 对话
Dialog Button button 按钮
Floating Text texttag 漂浮文字
Integer integer 数值
Item item 物品
Leaderboard leaderboard 排行榜
Player player 玩家
Player Group force 玩家组
Point location 位置(点)
Real real 真值型数字
Region rect 地区
Special Effect effect 特效
String string 字符串
Terrain Deformation terraindeformation 地形
Timer timer 计时器
Timer Window timerdialog 计时器窗口
Unit unit 单位
Unit Group group 单位组
Player Score playerscore 积分(1.13版新类型)
World Editor中的Order(命令) , Ability(技能) , Unit Type(单位类型), Destructible type(可破坏物类型) 和 Item type(物品类型) 在JASS中对应的变量类型实际上是integer。
可以用单引号'Xxxx'(Xxxx为在World Editor用View as raw data(以行数据查看)中看到的代码)表示这些类型的值
Jass基本变量
类型
integer
integer(数值)是的范围在 -2147483648 和 2147483647 之间的整数, 不能有小数位
在Jass中Integer的几中特殊形式:
1.'xxxx' 单引号加字符形式,该形式为256进制整数,每个字符代表其AscII码值,区分大小写,一般用来表示单位、物品、技能等代码。比如对战单位里剑圣的代码是 'Obla'(在物编中按Ctrl+D可以看到)
2.0xxx 8进制数字,首位为0表示8进制数字
3.0Xaa 16进制数字,以0x开头的表示16进制数字
real
real是范围很大的32字节数字, 可以有小数位, 123456.33就是real
小数点前或后是0的话,可以省略这个0;比如0.34=.34 4.0=4. 0.0可以写成0.或.0,但不能都省略
boolean
boolean的值只有true(真)和false(假), 多用于条件判断语句
if (条件==true)
then
(符合条件做某事)
else
(不符合条件就做另一件事)
endif
string
string是字符串变量, 可以是null(空值). 注意Jass的字符串是大小写区分的, 赋值时用双引号 "" 引用
handle
handle句柄, 可以是null(空值). 是用于指向Warcraft III定义的数据结构的指针. 比如上表中的location/player等除了integer/real/boean/string外的的变量实际上就是handle类型的子变量
code
code(程序代码), 可以是null(空值). 函数可以有code类型的传递参数, 表示该函数必须要有其他函数作为参数, 如:
function RunFunctionForAllPlayers takes code theFunction returns nothing
我们可以这样调用函数: call RunFunctionForAllPlayers(function someFunction) //先运行someFunction
也可以: call RunFunctionForAllPlayers(null) //不运行其他函数
用户定义变量类型
正如上面所说, 上表中location/player等除了integer/real/boean/string外的类型实际上就是handle类型的子类型, 这些变量就是用户类型变量, 实际就是一个数据结构的指针.
数组
是指一组同类型的有序列的变量. 数组中包含的元素可以用[n]来指明(n 表示第n + 1个元素, 从 0 算起).
以上所说的变量类型中除了code类型, 其他类型的变量都可以定义数组变量, 如
locate integer array dropitems
set dropitems[0] = 'Xxxx'
......
set dropitems[18] = 'Xbbb'
dropitems[18]指dropitems中第19个变量.
注意:
1) 数组所有元素初始值是"空", 比如integer类型的数组初始值为0, handle类型初始值的为null
2) 数组不能直接再次初始化, 只能数组按元素赋值, 如:
locate string array playername = "Greedwind" //数组非法赋值
parameter数据类型locate string array playername //数组元素只能逐个赋值
set playername[1] = "Greedwind"
set playername[2] = "Greedwind's girlfriend"
unit array myUnits
unit array yourUnits
...
set myUnits = yourUnits // 非法
set myUnits[0] = yourUnits[10] // 合法
3) 数组在函数间不能互相传递. 即是不能把数组作为函数参数, 而且函数也
不能返回数组类型的变量.
4) 数组元素域在 0 和JASS_MAX_ARRAY_SIZE = 8192 之间, 即是最多有JASS_MAX_ARRAY_SIZE + 1 个元素. JASS_MAX_ARRAY_SIZE是在common.j中定义的常数
1)什么是全局变量和局部变量, 怎样声明和使用变量?
首先要了解, 从作用范围来区分, 变量有全局变量和局部变量.
全局变量作用于Jass程序的全部分, 即是如果全局变量abc在某个函数中改变了值, 这个值也将影响其他引用了abc变量的函数.
全局变量声明格式:
globals
变量类型 变量名称 = 初始值 //有初始化的全局变量
变量类型 变量名称 //无初始化的全局变量
变量类型 array 变量名称 //数组全局变量, 不能再次初始化赋值
...
endglobals
局部变量只作用于函数内部, 即是如果在函数内部定义了局部变量abc, abc的值只影响该函数内部, 不影响全局变量abc的值.
局部变量声明格式:
local 变量类型 变量名称 = 初始值 //有初始化的局部变量
local 变量类型 变量名称 //无初始化的局部变量
local 变量类型 array 变量名称 //数组局部变量, 不能再次初始化赋值
注意:
1) 不论是全局变量还是局部变量, 必须在程序开始部分首先声明.
即是全局变量声明总是在程序文件的最前端,
而局部变量声明总是在函数的最前面.
2) 在Trigger Editor用变量管理器(Ctrl + B)中定义的变量都是全局变量
3) 在Trigger Editor的循环GUI语句 For Loop (Integer A)和For Loop (Integer B)中的(Integer A)(Integer B)都是全局变量
实例:
globals
integer abc = 5188
endglobals
.......
function myfunc1 takes nothing returns nothing
local integer abc
set abc = 1233
endfunction
function myfunc1 takes nothing returns nothing
local integer myint
set myint = abc
set abc = 0
endfunction
如果按顺序调用函数myfunc1 和 myfunc1, 那么在函数myfunc2中的myint的值是多少呢, abc最终值又是多少?
答案是: int = 5188, abc 最终值为 0
2)怎样在Trigger Editor(GUI)中使用局部变量?
(有关在Trigger Editor(GUI)中使用局部变量详细方法请参看我的签名中的链接 - 3c的内存泄漏)
GUI中不能直接引用局部变量,但是我们可以使用全局变量作为中介
首先声明定义变量类型。声明定义变量类型的语句只能放在TIGGER的开头,不然会出现编译错误
声明定义变量类型:
要用:Custom Script - Action
语法:
Custom Script: local <;变量类型> <;变量名>
变量类型请参看WORLD EDITOR和JASS变量类型对应表
例如:
--单位变量
Custom Script: local unit u
--单位组变量
Custom Script: local group g
然后将它们赋值给临时全局变量就可以在GUI里调用该值了,注意
全局变量要加前缀"udg_"
Custom Script: set udg_TempUnit=u
局部变量的使用:
在变量表(Control + B)中先定义好同类型临时变量(不要加前缀udg_)的变量,该变量可以在多个触发里重复利用
(在变量表中定义此变量是为了方便TIGGER EDITOR引用该变量。)
以下例子实现了在单位死亡的位置显示5秒的死亡信息(漂浮文字)
(象这种例子, 如果不使用用局部变量, 将无法准确销毁临时漂浮文字(-Destroy (diesmessage)). 因为在等待5秒后(-Wait 5.00 seconds), 最近创建的漂浮文字(last created floating text)可能已经不是原来的那个了 )
例子:
Events:
A unit dies
Conditions:
Actions:
-Custom Script: local texttag diesmessage
-Custom Script: set udg_TempTextTag = diesmessage //注意要添加"udg_"前缀
-Floating Text - Create floating text at ((position of (Triggering Unit))
with the message ((A+(name of (Triggering Unit))) + "dies") with size 20 , red 100, green 100, blue 0, alpha 100.
-Set TempTextTag= (last created floating text)
-Wait 5.00 seconds
-Custom Script: set udg_TempTextTag = diesmessage
-Destroy (TempTextTag)
注意:不要利用同名覆盖的方法在GUI中使用局部变量!(即以udg_开头的局部变量与已定义全局变量名字相同)
该方法在触发内该类同名变量数量>=2时会出现严重Bug!
[box=#FFF00] Jass基础教程 第二章 语法篇
本章主要介绍Jass的语句和语法.
所有程序语言都是由特定的语句按语法规则组成, 基本和人类的自然语言没什么两样. 只是程序语言要有严谨的逻辑和语法, 而人类的语言可以是模糊不清不知所云的--就象我现在写的可以离题千里却蕴涵禅机, 让你费解一样.
1) 赋值语句: set
在第一章中我们已经接触过很多 set 语句了, 就是把 = 号右边的值赋个左边的变量
语法格式:
set 变量 = 值(表达式) // (A)
set 数组变量[index] = 值(表达式) // (B)
(A)是非数组变量的赋值语句.
(B)数组变量的赋值语句, 其中[]中的index是指第index + 1个数组元素, index必须是integer类型的非负整数(可以是 0 )
右边表达式的数据类型必须和左边的变量类型一致, 意思是说不能这样: set 人类 = 猪
2) 调用函数: call
用于调用函数. 当使用 call MyFunction(), 则运行了函数MyFunction
语法格式:
call 函数名(参数1, 参数2, ...., 参数n)
()号内的的用逗号(,)分割开的参数表. 如果被调用的函数要求输入参数, 则 call 语句中必须包含被调用函数要求输入参数类型相同数据类型或用空值.
这句另人费解的话用人类的模糊语言来说就是:
我(被调用的函数)要爱情(参数)才可以工作, 你(call 过程)就
不要给我面包(传递的参数)
这个是用Jass写的要爱情和面包但什么也不做而且还不高兴的空函数:
function isHappy takes unit whichunit, item needbread returns boolean
return false //函数返回值为"假"
endfunction
这个是用Jass写的总是高兴傻笑的空函数:
function IamAlwaysHappy takes nothing returns boolean
return true //函数返回值为(真)
endfunction
在函数中isHappy()要求传递2个参数, 参数数据类型分别是unit和item
而函数IamAlwaysHappy()没有要求传递任何参数, 就不要多此一举给它爱情和面包了
假设girl是unit类型变量, bread是item类型变量. 我们可这样调用:
call isHappy(girl, bread) //给了爱情又给面包, 真是贴心人啊
call isHappy(null, bread) //不给爱情只给面包, 不要饿死他
call isHappy(girl, null) //给爱情不给面包, 为了爱情故, 我把面包抛
call isHappy(null, null) //两者皆不给, 反正给了也返回"假"值
call IamAlwaysHappy() //IamAlwaysHappy()没有要求任何参数
//把PickaGirl()返回的值(unit类型或null)作为参数
call isHappy(PickaGirl(), null)
以下非法调用
call isHappy() //非法调用
call isHappy(girl) //非法调用
call IamAlwaysHappy(girl) //非法爱情(不要给我二奶)
3) 条件分支: if then else
此语句效果就是: 如果条件成立, 那么做某事, 否则做另一件事
语法格式:
if 条件表达式1 then
语句
语句
...
elseif 条件表达式2 then
语句
语句
...
elseif 条件表达式3 then
...
else
语句
语句
...
endif
其中条件表达式必须是布尔型(boolean)的值(真true和假false).
这是某人的论坛签名JASS版, 他企盼着当他进入论坛时就....
事件:单位进入论坛时
if GetTriggerUnit() == 他 then
call CreateNUnitsAtLoc( 1, GetUnitTypeId(美女),
GetOwningPlayer(GetTriggerUnit()),
GetUnitLoc(GetTriggeringUnit()), bj_UNIT_FACING )
else
endif
4) 循环语句 loop 和循环退出语句 exitwhen
loop 是执行循环的语句, exitwhen 则是控制循环退出的条件
语法格式:
loop
exitwhen 条件表达式 //(A)在循环语句执行前检查循环条件
....
endloop
或
loop
....
exitwhen 条件表达式 //(B)在循环语句执行后检查循环条件
endloop
同样的, 条件表达式必须布尔型的值
(A)和(B)的差别相当于先买票再猴戏和看玩猴戏再給钱
loop 语句
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论