使用quick-x开发游戏有两年时间了,quick-x是cocos2d-Lua的一个豪华升级版的框架,使用Lua编程。相比于C++,lua的开发确实快速便捷了许多,下文只是lua这门语言的一个基础知识点,没有涵盖整个Lua的内容,但是作为对lua入门的初步了解还是可以的,由于内容精简了不少,所以语言上可能会有点跳跃,但是问题不大。

  要了解一门语言,首先要了解的是语言的标识符、保留字、常量和变量,命名规范和注释以及数据类型等。然后是运算符、控制流语句和一些常用的函数方法之类的东西。最后再涉及面向对象的内容等等。

一、标识符(命名规范)

  按照上面的顺序,我们首先来看下Lua的标识符和保留字的内容吧。标识符就是语言给变量、常量、方法(函数)、对象和类等指定的名字。每一门语言都有自己的一套命名规范,虽然有些语言的命名规范略有差异,但是基本上是一致的,这也算是行业的一些潜规则吧。

  Lua的标识符有以下几点要求:

  1、严格区分大小写,即person和Person是不同的标识符。

  2、在字符组成上,Lua同样满足可以由下划线、字母和数字组成,并且首字符不能是数字的要求。除此之外,Lua标识符还支持美元符号组成,即“$num_111”这样的标识符是合法的。

  3、不能使用关键字(保留字)作为标识符。

  所谓的关键字(保留字)是在语言中具有特殊意义的符号,每一门语言都会定义一些具有某些特殊含义的保留字,下面我们罗列下Lua的主要关键字:

  1、语言基础:nil、local、function、type。

  2、逻辑判断:and、or、not、true、false。

  3、流程控制:return、break。

  4、分之语句:if、then、else、elsif、end。

  5、循环语句:do、while、for、in、repeat、until。

  在C、C#、Java等语言中,常量只能在声明的时候初始化,之后就不能更改它的值。然而对Lua这种动态脚本语言而言,它并没有常量与变量之分,两个其实是一样的,都是变量,都可以在初始化后随意修改它的值。我们在声明常量的时候通常使用全大写字符组成,不同单词之间以下划线分隔。如:

Y_NAME = “clarence” 

  Lua中声明一个变量是在标识符前面加上local关键字来声明一个局部变量,不加local关键字的就是全局变量了。变量的命名方式是首字符小写,采用驼峰命名法。如:
  

local myName = “clarence”
name = “zengbinsi”

  每个语言都有每个语言的命名规范,虽然不是强制要求的东西,但是一个好的命名风格会让你的代码更加美观和易于维护。Lua基本上和其他语言一致,除了上面提到的常量与变量的命名规范之外,在类名上,Lua一般采用首字符大写的驼峰命名法,而对象的命名法和变量的一致。另外,方法函数一般采用动词开头,首字母小写,后面每个单词首字母大写的驼峰命名法进行命名。
  

二、代码注释

  在Lua中,代码注释主要分两种:单行注释(- - 注释内容)和多行注释(- - [[ 可换行注释内容 ]] - -)。如:
  

- -  单行注释
     local num = 621  - - 声明一个变量num,并赋值。
     - - [[ 这里是多行注释 print(“Hello World!”) ]] - -

三、数据类型

  Lua和Javascript一样同属于动态语言,所以它的类型是在赋值的时候才确定下来的,并且后期重新赋值的时候会再次确定新的类型。Lua主要的数据类型有:数值类型(number)、布尔类型(boolean)、字符串类型(string)、函数类型(function)、线程(thread)、表类型(table)、自定义类型(userdata)和空值(nil)。

  数值类型可以保存实数,包括整数和小数,整数包括十进制和十六进制,十六进制的整数是以“0x”开头的一串数字序列。

  布尔类型的值只有两种:true和false,用于表示“真”和“假”。

  字符串类型是由0个或者多个被双引号(“”)或者(’’)包裹的字符序列。

  函数类型,Lua里面的函数类型也是第一类值,所谓的第一类值的意思就是函数和我们普遍认识的字符串、数字之类的类型是一样的,可以保存在一个变量里面,可以重新赋值,也可以当成函数的实参传递到其他函数内部等等。

  线程类型可以同时执行多个(多线程),每个线程会开辟独立的栈区、局部变量等。

  表类型类似于其它语言的数组或者字典类型,但是它比数组或者字典类型更加强大,它是使用大括号({})表示的,创建表类型的代码如下:
  

- - 数组形式      local nums = {2,1,5,6,}
     - - 字典形式      local diction = {key1 = 9,key2 = 8,key3 = 4,key4 = “Y”,key5 = “z”,key6 = ’n’,}

  自定义类型,Lua是用C语言开发出来的一门轻量级的编程语言,连编译器都是用C编写的。Lua可以通过自定义类型与C语言进行交互,可以将任意的C语言类型存储到Lua的自定义类型的变量中,以此来完成交互逻辑代码。

  Lua里面提供了一个内置函数type(),用于返回指定变量和数值的类型,如:
  

print(type(489116)) - - 输出:number。
    print(type(“ax”)) - - 输出:string。
    print(type({“z”,name = ‘x’,7 = “x”,})) - - 输出:table。

四、基础数据类型转换(string和number)

  谈数据类型,就难免要说到数据类型转换。lua提供了tostring()函数用来将布尔类型和数值类型转换成字符串类型,提供tonumber()函数来将非数值类型的变量转换成数值类型,如果无法进行转换则返回nil。如:

  1、转成字符串类型。
  

print(tostring(true))         - -  输出“trueprint(tostring(215.61))     - -  输出“215.61print(tostring(1984))         - -  输出“1984

  2、转成数值类型。
  

print(tonumber(“953.555”))     - -  输出953.555
     print(tonumber(“732.0”))     - -  输出732
     print(tonumber(true))         - -  输出nil
     print(tonumber(“abc123”))     - -  输出nil
     print(tonumber({1,“2”,}))     - -  输出nil

  另外,tonumber()函数可以接收两个参数,第一个参数是要转换的值,第二个参数是转换后的进制基数,默认为十进制。

五、运算符(算术、关系和逻辑运算符)

  在语言中,进行科学计算的符号称为“运算符”,运算符和常量或者变量可以组成表达式。Lua中的运算符也分为:算术运算符、关系运算符和逻辑运算符三种。

  算数运算符包括:加(+)、减(-)、乘()、除(/)、取余(%)和幂(^)。这个幂运算符在其他语言里面并不常见,或者说根本没有。但是在数学里面,例如要求2的3次幂,只需要写“2 ^ 3”即可,其他语言要写成“2 2 * 2”。

  关系运算符用于表示两个表达式的大小关系,返回的值是布尔类型的true(成立)或者false(不成立)。关系运算符分为:大于(>)、小于(<)、大于等于(>=)、小于等于(<=)、等于(==)和不等于(~=)六种。

  逻辑运算符是对布尔类型进行运算,返回值也是布尔类型。逻辑运算符分为:逻辑与(and)、逻辑或(or)和逻辑非(not)三种。

  运算符的优先等级顺序如下所示:

六、控制流语句(顺序、分支和循环的流程控制)

  在结构化的程序设计中,有且只有三种最基本的控制流语句,分别为:顺序语句、分支语句和循环语句。

  1、分支语句:在Lua中没有switch语句,所有的分支只能用if语句来进行实现。

  1.1、单分支:
  

if 条件表达式 then 
             分支语句块
         end

  1.2、双分支:
  

if 条件表达式 then 
             分支语句块1
         else
             分支语句块2
         end

  1.3、多分支:
  

if 条件表达式1 then 
            分支语句块1
        elseif 条件表达式2 then 
            分支语句块2
        elseif 条件表达式3 then 
            分支语句块3
        elseif 条件表达式4 then 
            分支语句块4else
            分支语句块n
        end

多分支中最后一个else都是可以省略的。

  2、循环语句:在Lua中,循环语句除了while和for之外,还有一个repeat循环语句。

  2.1、while循环:
  

while 条件表达式 do
             循环体
         end

  2.2、for循环:
  
  2.2.1、数值型for:
  

for 循环控制变量 = 初始值,终止值,循环控制变量变化步长 do
             循环体
         end

  其中循环控制变量的变化步长表示循环控制变量循环一次后数值变化量,可省略,默认为1,步长也可以为负数,如:
  

for i = 10,2,-2 do 
             print(“i = ”,i)
         end

  2.2.2、泛型for:
  

for i,v ipairs(数组) do
            循环体
        end

        for i,v pairs(集合) do
            循环体
        end

  这里相当于是一个迭代器,使用ipairs()函数进行迭代时,里面只能跌带出有下标索引的项。然后将每一项值保存在v变量里面,i表示当前循环次数。pairs()函数可以迭代集合里面所有的项,但是顺序和数组里面保存的顺序不一致。

  2.3、repeat循环:
  

repeat
             循环体
         until 条件表达式

  repeat语句和while语句差不多,只是条件在执行过一遍循环体之后才验证,类似其它语言的do…while语句。

  除了这最基本的三种控制流语句之外,Lua还支持return语句和break语句来改变程序执行的流程,但是Lua不支持continue语句。

  break语句可用于三种循环结构。当程序执行到break语句时,程序将跳出当前循环体,不再继续执行循环体的其他语句了。

  return语句可以终止当前语句块的调用,返回到调用该语句块的语句处。return 语句后面可以接0个到多个返回值,这和其他语言的单一返回值不同。每个返回值以逗号(,)分隔。

七、万能的table数据类型

  现在,我们再来探讨下table(表类型),前面我们已经说过table可以表示数组和字典,但是远比这些强大。这是因为table是Lua中唯一一个能够用于描述数据结构的数据类型。它本身其实就是一个字典类型,在面向对象中,它甚至可以用于描述类和对象。

  首先,我们看下字典类型的定义:
  

local dic1 = {id = 1,date = “2015/09/16”,}
     local dic1 = {[“id”]= 1,[“date”] = “2015/09/16”,}

  上面这两种声明方式只是key的写法不同,在用法上面并没有什么区别。要访问上面声明的字典我们可以使用如下代码:
  

print(“dic1.id = ” .. dic1.id)
     print(“dic1.id = ” .. dic1[“id”])

  数组我们也是通过table来实现的,我们可以将数组看成是key为有序数列的一个字典。声明一个数组的代码如下:

local arr = {21,“yun”,‘中’,“56”,}

  访问数组的语法基本与C语言等一致,比如访问数组的第个元素,代码如下:
  

- - Lua数组索引是从1开始的,和其他语言从0开始不同。      print(“arr[1] = ”,arr[1])

  在数组名称前面加上“#”运算符可以获得数组的长度,在旧版本的Lua中也可以使用table.getn(数组变量)函数来获取长度。
  

print(“arr的长度是:” .. #arr) - - 输出4 

  另外,Lua语言还给table提供了两个常用的函数用于插入数据和删除数据。

  插入数据使用table.insert()函数,这个函数有三个参数,第一个是table类型变量,第二个是要插入到table中的值,第三个是可选参数,表示要插入的位置索引,默认在最后一个。

  删除数据使用table.remove()函数,这个函数有两个参数,第一个是table类型变量,第二个是要删除的索引。

  最后,我们在遍历table的时候一般使用ipairs()函数来遍历数组,而字典一般使用pairs()函数。ipairs()函数和pairs()函数在遇到空置(nil)时停止遍历,它会认为已经遍历到末尾了。

八、强大的string字符串类型

  Lua中的字符串是一串连接被双引号或者单引号包裹的字符序列,值得注意的是Lua拼接字符串使用的是“ .. ”符号,而非C#等其它语言的加号(+)。Lua的字符串库里面提供了很多方便的函数让我们的编码更加的方便快捷。
  

九、不同于其它编程语言的function函数类型

  已经具备了语言的基础语法,我们接下来看下高阶一点点的函数。对于第一次看到“函数”这个词的人,很难不联想到数学上的函数。确实我们可以这么认为,函数有函数名、参数和返回值。函数名就是用来标记函数的标识符(比如:正比例函数、反比例函数等),参数就相当于自变量x,返回值可以看成是因变量(函数值)y,而整个函数体就可以看成是函数的公式。

  编程时,我们通常将一些反复执行的代码放到一个代码块里面,这个代码块就是我们的函数。Lua的函数分为局部函数和全局函数。Lua定义函数的格式如下:
  

function 函数名(参数列表)
         函数体
         return 返回值
     end

  一般情况下函数都应该有返回值,如果没有返回,Lua默认返回nil。定义局部函数就是在function关键字前面加上local修饰就可以了。

  值得注意的是Lua的函数比较特殊,它支持多返回值。例如:
  

- -  函数定义
    function getNum(a,b)
        return a,b,a + b
    end
    - -  函数调用
    local a,c = getNum(2,1)

    print(a,c)     -- 输出2 1 3

十、神奇的函数闭包

  说到函数就不得不提函数闭包,闭包可谓是语言的强大特性之一。闭包的创建相对容易,人们甚至会在不经意间创建闭包,但这些无意创建的闭包却存在潜在的危害,比如内存积压得不到释放等等。我们先来看下闭包的创建,代码如下:
  

function methodA()
        local str = "HelloWorld"

        -- 声明内部函数
        local methodB = function() 
            print(str)
        end

        -- 将函数返回
        return methodB
    end 

    -- 调用methodA得到methodB
    local fn = methodA() 

    -- 在methodA函数外部调用得到的methodB函数
    fn()

  通常来说我们在函数methodA里面定义的变量之类的东西在函数返回之后都会被释放掉,但是上面这种情况比较特殊。函数methodA执行后将内部的函数methodB返回出去了,并且这里的methodB还访问了methodA的局部变量str。那么Lua为了保证返回出去的函数能够在外部正常的访问,会将methodA保留了下来,并且里面的局部变量也不会被释放掉,这就形成了一个闭包。里面methodB定义的那行我们称为闭包表达式。

  闭包的使用有好处也有坏处,在通常情况下我们应该尽量消除不必要的闭包,防止内存暴涨带来的坏处。

  最后的最后,我们将在下一篇来谈谈Lua的面向对象(OOP)。

【quick-cocos2d-x】Lua 语言基础的更多相关文章

  1. ios – 如何使用Objective C类中的多个参数调用Swift函数?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  2. ios – Swift 4添加手势:覆盖vs @objc

    我想在我的视图中添加一个手势,如下所示:但是,在Swift4中,我的编译器给出了以下错误:建议添加@objc以将此实例方法公开给Objective-C.实现此目的的另一个选项将覆盖touchesBegan()函数并使用它来处理点击.我试图以“Swift”的方式做到这一点,而不必带入Obj-C.有没有纯粹的Swift方式来添加这个轻击手势而不使用@objc?

  3. ios – 将视频分享到Facebook

    我正在编写一个简单的测试应用程序,用于将视频从iOS上传到Facebook.由于FacebookSDK的所有文档都在Objective-C中,因此我发现很难在线找到有关如何使用Swift执行此操作的示例/教程.到目前为止我有这个在我的UI上放置一个共享按钮,但它看起来已禁用,从我读到的这是因为没有内容设置,但我看不出这是怎么可能的.我的getVideoURL()函数返回一个NSURL,它肯定包含视

  4. ios – 以编程方式在Swift中添加联系人

    我想在Swift中以编程方式添加联系人.我发现了一些Objective-C示例,但我没有让它们工作,甚至在Objective-C中也没有.我不希望这涉及到AddressBookUI,因为我想从我自己的UI中获取值.解决方法这是在Swift中添加联系人的快速方法.我在我的iPhone5iOS7.1上验证了它,因为我发现模拟器并不总是与我的手机对AB的东西相同.您可以添加一个按钮并指向此方法:顺便说一下–它假设你已经分配了一个地址簿var,你可以通过覆盖viewDidAppear来打开视图.它也会执行安全提示

  5. ios – 公式数组

    我想在xcode中使用这样的公式制作一个客观的c数组.>x5>x-5>x/5>x*5所以我可以用arrayName[i]加载一个公式并给出x的值并得到答案.有没有办法做到这一点,如果是这样的话怎么样?

  6. ios – 为目标c中的方法传递未知类型的参数,可能吗?

    是否可以将未知类型的参数传递给objective-C方法?在C#中你可以写实现这一点,但我知道Objective-C没有泛型,所以有没有其他方法可以在Objective-C中实现这一点?我需要这个,因为我想创建一个方法来改变不同对象的文本颜色,如UITextField和UIButton的占位符文本.所以我的计划是创建一个名为textWhite的方法,然后在此方法中检查对象的类型,然后运行匹配的代码以使文本颜色变为白色.解决方法是的,可以传递未知类型的参数.见下面的例子.请参考使用id对象的链接作为参数Us

  7. ios – Swift指针算术和解除引用;将一些类似C的地图代码转换为Swift

    我有一点似乎没有工作的Swift代码……解决方法您正在指定locationPointer指向新位置,但仍在下一行中使用ptr,并且ptr的值尚未更改.将您的最后一行更改为:或者你可以改变指向var的指针并推进它:

  8. ios – “禁用模块时使用’@import’”错误 – 启用模块和链接框架= YES

    我有一个使用CocoaPods并使用’SCLAlertView-Objective-C’窗格的项目.该pod使用@importUIKit;模块样式导入.我在目标和项目设置中将“启用模块(C&Objective-C)”和“自动链接框架”设置为YES.当模块被禁用时,我仍然得到“使用’@import’错误.有没有什么可以阻止Xcode能够启用模块,如使用.pch文件,任何链接器标志,或者我没有提到的任

  9. XCode 6.3立即在抛出的Objective-C异常上引发SIGABRT

    考虑以下目标-C代码在XCode6.2中,它按预期工作(记录“错误消息”).但是,由于我们升级到6.3,抛出行(throwstd::logic_error…)引发SIGABRT(堆栈跟踪仅包含_cxa_throw和_pthread_kill,超出applicationdidFinishLaunchingWithOptions)并导致应用程序崩溃.这只发生在我们的应用程序中–当我将完全相同的代码复制

  10. ios – 在swift框架中使用Bridging Headers时失败

    我正在做一个快速的框架,我想使用旧的目标c类.为此,我使用桥接头方法但是当我尝试构建时出现此错误:我将我的{PROJECT}-Bridging-Header.h添加到Swift编译器中的Objective-C桥接头–代码生成我怎么解决它?

随机推荐

  1. 【cocos2d-x 3.x 学习笔记】对象内存管理

    Cocos2d-x的内存管理cocos2d-x中使用的是上面的引用计数来管理内存,但是又增加了一些自己的特色。cocos2d-x中通过Ref类来实现引用计数,所有需要实现内存自动回收的类都应该继承自Ref类。下面是Ref类的定义:在cocos2d-x中创建对象通常有两种方式:这两中方式的差异可以参见我另一篇博文“对象创建方式讨论”。在cocos2d-x中提倡使用第二种方式,为了避免误用第一种方式,一般将构造函数设为protected或private。参考资料:[1]cocos2d-x高级开发教程2.3节[

  2. 利用cocos2dx 3.2开发消灭星星六如何在cocos2dx中显示中文

    由于编码的不同,在cocos2dx中的Label控件中如果放入中文字,往往会出现乱码。为了方便使用,我把这个从文档中获取中文字的方法放在一个头文件里面Chinese.h这里的tex_vec是cocos2dx提供的一个保存文档内容的一个容器。这里给出ChineseWords,xml的格式再看看ChineseWord的实现Chinese.cpp就这样,以后在需要用到中文字的地方,就先include这个头文件然后调用ChineseWord函数,获取一串中文字符串。

  3. 利用cocos2dx 3.2开发消灭星星七关于星星的算法

    在前面,我们已经在GameLayer中利用随机数初始化了一个StarMatrix,如果还不知道怎么创建星星矩阵请回去看看而且我们也讲了整个游戏的触摸事件的派发了。

  4. cocos2dx3.x 新手打包APK注意事项!

    这个在编译的时候就可以发现了比较好弄这只是我遇到的,其他的以后遇到再补充吧。。。以前被这两个问题坑了好久

  5. 利用cocos2dx 3.2开发消灭星星八游戏的结束判断与数据控制

    如果你看完之前的,那么你基本已经拥有一个消灭星星游戏的雏形。开始把剩下的两两互不相连的星星消去。那么如何判断是GameOver还是进入下一关呢。。其实游戏数据贯穿整个游戏,包括星星消除的时候要加到获得分数上,消去剩下两两不相连的星星的时候的加分政策等,因此如果前面没有做这一块的,最好回去搞一搞。

  6. 利用cocos2dx 3.2开发消灭星星九为游戏添加一些特效

    needClear是一个flag,当游戏判断不能再继续后,这个flag变为true,开始消除剩下的星星clearSumTime是一个累加器ONE_CLEAR_TIME就是每颗星星消除的时间2.连击加分信息一般消除一次星星都会有连击信息和加多少分的信息。其实这些combo标签就是一张图片,也是通过控制其属性或者runAction来实现。源码ComboEffect.hComboEffect.cpp4.消除星星粒子效果消除星星时,为了实现星星爆裂散落的效果,使用了cocos2d提供的粒子特效引擎对于粒子特效不了

  7. 02 Cocos2D-x引擎win7环境搭建及创建项目

    官网有搭建的文章,直接转载记录。环境搭建:本文介绍如何搭建Cocos2d-x3.2版本的开发环境。项目创建:一、通过命令创建项目前面搭建好环境后,怎样创建自己的Cocos2d-x项目呢?先来看看Cocos2d-x3.2的目录吧这就是Cocos2d-x3.2的目录。输入cocosnew项目名–p包名–lcpp–d路径回车就创建成功了例如:成功后,找到这个项目打开proj.win32目录下的Hello.slnF5成功了。

  8. 利用cocos2dx 3.2开发消灭星星十为游戏添加音效项目源码分享

    一个游戏,声音也是非常的重要,其实cocos2dx里面的简单音效引擎的使用是非常简单的。我这里只不过是用一个类对所有的音效进行管理罢了。Audio.hAudio.cpp好了,本系列教程到此结束,第一次写教程如有不对请见谅或指教,谢谢大家。最后附上整个项目的源代码点击打开链接

  9. 03 Helloworld

    程序都有一个入口点,在C++就是main函数了,打开main.cpp,代码如下:123456789101112131415161718#include"main.h"#include"AppDelegate.h"#include"cocos2d.h"USING_NS_CC;intAPIENTRY_tWinMain{UNREFERENCED_ParaMETER;UNREFERENCED_ParaMETER;//createtheapplicationinstanceAppDelegateapp;return

  10. MenuItemImage*图标菜单创建注意事项

    学习cocos2dx,看的是cocos2d-x3.x手游开发实例详解,这本书错误一大把,本着探索求知勇于发现错误改正错误的精神,我跟着书上的例子一起调试,当学习到场景切换这个小节的时候,出了个错误,卡了我好几个小时。

返回
顶部