Lua

Lua

简介

  • Lua是脚本型语言
    • 动态编译
    • 动态执行
      • 每次修改不需要重新编译链接执行
    • 运行时编译而并非运行前编译
  • 是C语言编写的

特性

Lua的Hello World

print("Hello world")

Lua行末不要分号

Lua的括号

do
    ……
    ……
    ……
end

Lua语言几乎用不到大括号,取而代之的是do…end

Lua的注释

--这是一个注释
// 双斜杠不是注释了哦

--[[
这是一个多行注释哦
]]
/*
 这不是多行注释了哦
*/

小心不要变成纯文本了

--如果上面的多行注释没有写 双横线的话,就变成的纯文本赋值语句哦

a = [[<html><head></head><body></body></html>]]

-- 这个时候的 a 就是一个纯文本

数据类型

  • Lua是动态类型,不需要定义就可以直接使用
a = "I'm a"
print("a is "..a)
  • Lua的数据类型是动态可变的

  • Lua的数据类型

    • 数字类型
      • 整型
      • 浮点型
      • long double 等 都是 数字类型,并没有明确划分
    • 字符串类型
    • thread类型
      • 线程也算是一个数据类型
    • function类型
      • 函数方法的数据类型
    • table
      • 数组,融合的链表和键值对等
    • 其他类型
a = function(x)
    print("user input is "..x)
end

a("test")
-- 这就相当于调用了function(x) 那个函数

-- 唯一一个使用了 大括号的地方
myTable = {12,13}
print(myTable) -- 会输出table的地址
for k,v in pairs(myTable) do
    print(k,v)
end
-- 输出了序列号和对应的值(序号从1开始)

变量作用域

b = "123"
local c = 12

local function myfuntion1()
    print("i'm lua")
end


local function myfuntion2()
  	local a = "hello"
    return a
end
  • 其他lua文件引用该lua文件的时候,将无法访问到local标记的变量
  • 相当于 是一个 private 的变量
  • 反之 如果不加 local标识符,那么Lua默认的是全局变量global类型

如果一个function函数中创建的变量不是local的,就意味着它是一个global变量

if语句(没有switch语句)

  • 单独一个if
local a = 12
if a == 12 then
	print("a\'s value is 12")
end
  • if…else 语句
local a = 2
if a == 2 then
    print("value is 12")
else 
    print("value is not 12")    
end
  • if…else if…语句
local a = 12
if a == 12 then 
    print("value is 12")
    elseif a ~= 11 then
    print("value is not 11")
end

这里不等于符号是 ~= 注意注意!!!!!

函数/方法

无参无返回值

local function f1()
    print("hello")
end

有参无返回值

local function f2(a)
    print(a)
end

有参有返回值

local function f3(a)
    a += 2
	return a
end

--调用
a = f3(123)

返回多个值

local function f4()
    return 1,2
end

-- 调用
local a,b = f4()

可变参数列表

local function f5(...)
    local myTable = {...}
    
    for k,v in pairs(myTable) do
        print(k,v)    
    end
end

-- 调用
f5("12",123,"ok")

库函数

  • print() 就是一个很明显的print(),因为我们没有定义它
  • 有些函数是Lua自带的

逻辑操作符

and or not
  • 表示假
    • false
    • nil
  • 表示真
    • 0
    • 其他数值

and 和 or 就类似于 C语言中的 && 和 ||

  • and
    • 如果我们第一个需要去计算的操作数,如果操作数是假,则返回第一个操作数
    • 反之则返回第二个操作数
print(1 and 2)
-- 输出的 2 哦
print(false and 5)
-- 输出 false 哦
  • or
    • 如果第一个我们需要去计算你的操作数为真,返回第一个值
    • 反之返回第二个值
print(1 or 5)
-- 返回 1
print(false or 5)
-- 返回 5

not 类似于 C语言的 ! 取反

  • not
    • 永远返回的是 true或false
print( not nil)
-- 返回 true
print( not 1)
-- 返回 false

循环语句

while

local index = 1
local mytable = {1,2,3}
while mytable[index] do 
    print(mytable[index])
    index = index+1
end

do……while换成了 repeat

repeat
    line = io.read() -- 从命令行获取输入
	print(line)
until line ~= ""

for循环

for i = 1, 5 do
	print(i)    
end
-- 输出 1 2 3 4 5 想想为什么

for i = 1, 10, 2 do
	print(i)    
end
-- 输出 1 3 5 7 9 想想为什么

for i = 20, 10, -2 do
	print(i)    
end
-- 输出 20 18 16 14 12 想想为什么

table = {1,2,3}
for i=1, #table do
    print(table[i])
end
-- #table 相当于取 table的长度,然后遍历

上述可见,for 后面有三个参数 一个是初始化i,一个是结束判断,一个是加减i(默认为1)

Table的使用

  • Table类似于Java的list和map的结合体
-- 建立一个有数值的table
local MyTable = {
    1, 			-- 索引为1
    2,			-- 索引为2
    3,			-- 索引为3
    4,			-- 索引为4
    5,			-- 索引为5
    table2 = {1,2,3}, -- 索引不为6
    "ok"		-- 索引为6
}

为什么上面的table2的索引部位6呢?

Table的遍历方式

  • Table的复杂性导致其有三种遍历方式
  • 因为Table既是链表类型又是键值对类型
myTable = {
    k = "x"
}
print(myTable[k])
-- 输出 nil
print(myTable["k"])
-- 输出 x
print(myTable.k)
-- 输出 x

-- 又或者直接
s = "ok"
myTable[s] = 10
print(myTable[s])
-- 直接通过键去设置值

myTable.k 与 myTable[“k”]有所不同

  • myTable.k 等价于 myTable[“k”],索引的键就变成了字符串
  • myTable[k] 表示用变量k的值来索引table,索引的键可以是其他

普通遍历方式

myTable={
    1,2,3,4,k = "ok",5
}

for i=1, #myTable do
    print("value is "..myTable[i])
end
-- 只输出1,2,3,4,5 哦, 因为 "ok" 的键为 "k"

for ipairs(迭代器)

for i,v in ipairs(myTable) do
    print(i,v)
end

与第一种for循环方式一样,都是按照当前索引的隐式索引来迭代并显示值的

for pairs(迭代器)

for k,v in pairs(myTable) do
    print(k,v)
end

按照键值对来输出

如果值为一个table,则会输出该table的地址

Table的作用

  1. 你可以作为第三方插件集成到项目中,为项目提供一个支持功能
  2. 完全使用table进行开发
  3. 当做一种数据的配置集(就是阵列)
  • 整体游戏的配置集(例子)

-- 使用lua,当做一种配置信息
application_config = {
    game_config = {
        ifDebugModel = false, -- 调试模式
        isCheatModel = true -- 作弊模式
    },

    sound_config = {
        isBackgroundMusicOpen = true,
        isEffectOpen = false
    },

    textrure_config = {
        Plist_Dictionary = "res/plist/",
        PACKE_TEXTURE_DIR = "res/images/"
    }
}

-- 小怪阵列
enemy_waves = {
    {enterId = 1, infoid = 1},
    {enterId = 2, infoid = 1},
    {enterId = 2, infoid = 2},
    {enterId = 1, infoid = 2},
    {enterId = 1, infoid = 1}
    --[[
        很典型的小怪阵列
        enterId 指的是 出兵口
        infoid 有一些具体信息
    ]]
}

enemy_datas = {
    { maxHp = 100, damage = 70, isHaveSpecialEffect = true },
    { maxHp = 50, damage = 20, isHaveSpecialEffect = false },
    { maxHp = 75, damage = 50, isHaveSpecialEffect = false },
    { maxHp = 125, damage = 80, isHaveSpecialEffect = true }
    -- 这里的参数 maxHp 指的是最高血量,damage 指的是攻击伤害, isHavaSpecialEffect 指的是是否有攻击特效
}


for key, value in pairs(enemy_datas) do
    print(key, value)
    if type(value) == "table" then
        for ik,iv in pairs(value) do
            print(ik, iv)
            print("__________")
        end
    end
end

使用Lua可以很快的给角色赋予属性
使用Lua可以很快的设置调试属性

读写数据文件

  • 以万能的txt文件作为例子
  • 这里使用IO库

一种写法


local f = assert(io.open("123.txt",'r'))
--[[
    返回一个文件流指针
    assert 是一个断言,当读写输入报错的时候会报错
    这里的io其实是一个table,正如同上面的table所讲的使用 '.' 来获取键的值
    这里的open就是io的一个键
    open 函数 有两个参数 一个是 路径名字 一个是 操作名字

	r 以只读方式打开文件,该文件必须存在。
	
	w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失。若文件不存在则建立该文件。
	
	a 以附加的方式打开只写文件。若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被保留。(EOF符保留)
	
	r+ 以可读写方式打开文件,该文件必须存在。
	
	w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失。若文件不存在则建立该文件。
	
	a+ 与a类似,但此文件可读可写
	
	b 二进制模式,如果文件是二进制文件,可以加上b
	
	+ 号表示对文件既可以读也可以写
]]
local string = f:read("*all");
-- *all 表示读取文件的所有内容
--[[
	*line 表示读取一行
	*number 表示读取一个数字
	<num>	读取一个不超过num长度的字符串
]]
f:close() -- 关闭流
print(string)

需要强调的是,f后面的’:'相当于面向对象的封装方式

-写


local function Write_txt(filename, inData)
    local f = assert(io.open(filename, 'a'))
    f:write(inData);
end

Write_txt("123.txt", "\nthis is a function");

另一种写法


------------------简单模型-----------------
--读
local file1=io.input("1.txt")  --当前目录"1.txt"要存在,不然出错
local str=io.read("*a")
print(str)
--写
local file2=io.output("2.txt") --当前目录"2.txt"不需要存在
io.write(str)
io.flush()
io.close()

--利用这几个函数可以做一个文件复制的函数
function copy(fileA,fileB)
  local file1=io.input(fileA) 
  if not file1 then print(fileA.."不存在") return end
  local str=io.read("*a")
  local file2=io.output(fileB)
  io.write(str)
  io.flush()
  io.close()  
end

for line in io.lines("1.txt") do
  print(line)
end
------------------完整模型-----------------
local f=io.open("3.txt","a+")
f:write("Happy New Year!")
f:flush()

f:seek("end",-1) --定位到文件末尾前一个字节
local str=f:read(1) --读取一个字符
print(str) --输出"!"
f:close()

串行化

  • 当一个对象没用被用到后就会从内存中delete掉,但是有的时候我们又想在之后恢复该对象到当时的状态

function serialize( o )

    if type(o) == "number" then
        io.write( o )
    elseif type(o) == "string" then
        io.write(string.format("%q", o))
    elseif type(o) == "table" then
        io.write("{\n")
        for k,v in pairs(o) do
            io.write("  ", k, " = ")
            serialize( v )
            io.write(",\n")
        end
        io.write("}\n")
    end
end

file = io.output("123.txt")
table = {
    1,2,3,4,5
}
serialize(table)
io.flush()
io.close()

上述代码将一个table对象保存到txt文件中

模块化 module

  • Java有 package包 来封装类
  • C++有 namespace 名空间 来封住类

Lua与C++的交互

  • Lua底层实现是 C/C++

Lua与C++交互的中间件栈

  • Lua与C++又部分不同,Lua有内部垃圾回收机制
  • Lua无需声明直接使用,而C++需要声明变量
评论 2 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:技术黑板 设计师:CSDN官方博客 返回首页

打赏作者

阿茶家的庸医

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值