GameMaker8.0 :新手教程 Part 16 -字符串处理-

分类栏目:gamemaker教程

742

GameMaker8.0 :新手教程 Part 16 -字符串处理-

1、字符串

我们曾经提到过,字符串指的是以双引号包裹的一种常量。形如"Punishment this world!","153.66","tan(pi/2) is invalid"等都是字符串。
在GM8.0中,使用单引号和双引号都被视作字符串,即,'abc'和"abc"是等效的。但是在大部分编程语言中,字符串都是用双引号来表示字符串。因为在通常意义下,单引号指的是字符而不是字符串。字符就是单个字形或符号,如'A','!','5'等都是字符。因此,为了规范,在本教程中,字符串一律使用双引号。
注意:GMS2已停用单引号字符串,使用单引号字符串会报错。

在双引号中使用单引号,是不会被视作字符串标记符号的。如:"I'm a man"中出现了单引号,但是字符串会把这个单引号也视为普通的字符,而不是当成字符串的标记符号。
由于GM把双引号视为字符标记符号,所以如果你想要字符串里带上双引号,可以使用+ chr(34) +代替,例如:
"As the saying goes :" + chr(34) + "Where there is a will, there is a way." + chr(34)
另外,字符中有一个特殊的标记符号'#',它代表换行,比如:"First#Second",当使用show_message或者后面讲到的其他输出函数时,读取到#就会自动换行,但是'#'本身不会被输出。如果你想要直接输出'#',那么要使用'#'来代替,它代表正常输出#而不是作为换行符号来使用。例如"First#Second"输出的是"First#Second"。

2、ASCII与Unicode

我们在第十章的时候讲过,电脑以二进制运行,所以实质上只能储存整数数据,电脑要储存别的类型的数据就必须先把它转换为整数。
ASCII就是一种将字符转换为整数的一种编码方式。
GameMaker8.0 :新手教程 Part 16 -字符串处理-
注意,ASCII的实际范围是0到127,但是只有32到126输出的是能看到的字符(也就是上图所示的部分),0到31与127被称为控制符,即这些编号的字符代表的是一种功能,而不是输出一个可见的字符。制作GM游戏基本上不用考虑控制符,故不讲,有兴趣可以自行百度。

你可能注意到,这个表上并没有中文。ASCII是众多的编码方式的一种,它提出的较早,当时只有欧美国家用得起电脑,所以并未考虑其他语言的字符。而即使是现在,ASCII也是一种使用频率非常高的编码方式。
中文的编码最早使用GB2321,后来改成GB18030,但是这两套编码方式只用于中国,外国的电脑是无法识别这种编码方式的,只会显示乱码。同样的,每个国家都为自己的语言文字设计了一套编码方式,这导致了不同国家之间网络交流困难。
为了解决这种一个国家一种编码的问题,Unicode应运而生,这是一种几乎把全世界所有可能用到的字符都考虑进去的一种编码方式,所以进入21世纪之后,大部分国家(包括中国)开始陆陆续续地使用与推广Unicode,方便了不同国家之间的网络交流。如果你想了解Unicode的字符与整数的对应关系,可以在Unicode®字符百科中查询。

现在回到GM8,事实上它只支持ASCII。你可能注意到GM8的代码框中可以输入中文,但这全是汉化组的功劳,如果你使用的是原装的GM8,写入中文只能得到乱码。
如果使用show_message()输出一段中文字符串,那么实际输出什么就和系统有关了。大部分情况下中国的电脑会正常地显示中文。
但是在日本,很多电脑仍然使用shift-JIS编码,这就导致很多日本制作的GM8的游戏,在中国玩会显示乱码,如下图:
GameMaker8.0 :新手教程 Part 16 -字符串处理-
但是如果把系统转换到日本地区,就能正常显示了:
GameMaker8.0 :新手教程 Part 16 -字符串处理-
所以使用中文需慎重,最好使用世界通用语言英语。为什么使用英语不会产生乱码问题呢?因为后期诞生的编码方式,基本上都向ASCII致敬,即前127位保持和ASCII完全一样,往后面再加自己的字符。这样,不管系统使用什么编码方式,都能正常读取英文字符。

3、字符串的处理

本节位于GML汉化文档第18页。
chr(val) :返回实数val对应的ASCII字符的字符串。注意返回的是字符串,比如chr(65)返回的不是字符'a'而是字符串"a",虽然在GM8中没有区别,但是最好还是注意一下。chr()的返回值可以用于字符串的相加,比如像第一节举的例子那样,用chr(34)来输出双引号。
ord(str) :返回字符串中第一个字符的ASCII码。这个函数的参数在GM8中在官方例子中常使用单引号,即ord('A')这种形式,但是GMS2废除了单引号,只能使用ord("A")。个人习惯写单引号字符形式,因为这样更明了(因为我主修C++)。
在按键检测中,keyboard_check系列函数,为了方便使用,将字母按键和ASCII码互相匹配,所以可以用ord()来代表字母按键。同样的,你也可以用ASCII码来表示按键,比如按键A对应65,所以你可以用keyboard_check(65)来检测A键。
real(str) :返回字符串中的真实数值。注意这个函数与上一个函数的区别,ord('1')返回的是字符'1'的ASCII码49,而real("1")则返回1。real是在字符串中寻找数值,比如real("-356")返回-356。注意,real()函数的参数必须是一个只包含有效数值的字符串,这个字符串可以有负号,小数点,以及E和e(代表10的多少次幂),例如real("-26.32e3")返回-26320。注意,符号'^'是位运算符不是幂函数符,不被视作有效数字的一部分。
string(val) :与real()相反,把真实数值转换为字符串。注意,参数会自动进行运算,比如string(5+6)返回"11"而不是"5+6"。
string_format(val, tot, dec) :同样是把真实数值转换为字符串,但是可以自己控制格式。tot是total的缩写,指数据的位置,dec是decimal的缩写,指小数点后的位数。
tot参数可能不好理解,举个例子,string_format(1234.56, 12, 5),返回字符串"  1234.56000",注意前面有两个空格,两个空格加上数字本身的字符数(小数点也算一个),刚好是12个字符,这就是参数tot的意义。
注意:tot只有在大于数据的字符数时才会生效,例如,string_format(123.456789, 3, 3),返回字符串"123.457",此时的tot参数毫无意义。
string_length(str) :返回字符串中字符的个数。
string_pos(substr, str) :返回字符串str中子字符串substr的位置。如string_pos("ab", "abcd")返回1。如果不存在,则返回0。
string_copy(str, index, count) :返回字符串str从第index个字符开始长度为count的字符串。例如:string_copy("123456", 2, 3)返回"234"。
string_char_at(str,index) :返回字符串str第index个字符。
string_delete(str, index, count) :返回字符串str从第index个字符开始删除长度为count的字符串后剩下的字符串。注意,字符串str本身不会被改变。例如:string_delete("abcdef", 3, 2)返回"abef"。

艾玛,我懒得一个个地讲了,后面的函数基本上都没啥难的,还是直接来看官方文档吧:
string_insert(substr,str,index) 返回在位置 index 处添加子串 substr 后的 字符串 str。
string_replace(str,substr,newstr) 返回字符串 str 的一份拷贝,为字符串中 子串 substr 第一次出现的地方开始被字符串 newstr 替换后的内容。
string_replace_all(str,substr,newstr) 返回字符串 str 的一份拷贝,为字符串中 子串 substr 所有出现的地方开始被字符串 newstr 替换后的内容。
string_count(substr,str) 返回子串 substr 在字符串 str中出现的次数。
string_lower(str) 返回小写格式的字符串 str。
string_upper(str) 返回大写格式的字符串 str。
string_repeat(str,count) 返回由 count 个字符串 str 组成的新 字符串 str。
string_letters(str) 返回只包含字母的字符串 str。
string_digits(str) 返回只包含数字的字符串 str。
string_lettersdigits(str) 返回包含字母和数字的字符串 str。
以下为处理系统粘贴板内容的相关函数。
clipboard_has_text() 返回粘贴板中是否存在任何文本。
clipboard_get_text() 返回当前粘贴板内文本内容。
clipboard_set_text(str) 将字符串 str 送入粘贴板。

4、execute_string(str)

GM8专属函数,GMS2已删除
作用是将字符串作为代码执行。
例如:execute_string("a = 5;");就会执行代码a = 5;。
如果只是直接填一个字符串作为参数,那么用这个函数是没有意义的。但是记住string是可以相加的,也可以通过函数来编辑,这就令execute_string变得十分有趣。

例如,你要设计一个可以更换风格的游戏,于是你准备了三套spr,分别对应命名,比如sprGrass1,sprGrass2,sprGrass3来代表三种风格中草的spr,那么你就可以通过execute_string()快速的更换画风:
(假设global.style变量用来储存画风的编号)
with(all)
{
var spr;
spr = string_delete(sprite_get_name(sprite_index), string_length(sprite_get_name(sprite_index)), 1) + string(global.style);
execute_string("sprite_index = " + spr + ";");
}
这个函数总是能起到一些奇奇怪怪的作用,当你卡壳的时候,说不定使用execute_string会带来新的思路。

扩展:带参数的execute_string
事实上,execute_string的真正形态是execute_string(str, arg0, arg1, arg2 ...);
这是一种将字符串str作为脚本来执行的一种方法。
例如:
execute_string("sprite_index = argument0;", sprBall);
在执行代码sprite_index = argument0;时,会将sprBall作为argument0的参数传递给字符串,最终执行代码sprite_index = sprBall;。