有关Lua的FAQ
Q:Lua是什么?
A:Lua由标准C编写而成,几乎在所有操作系统和平台上都可以编译,运行。其设计目的是为了嵌入应用程序中,从而为应用程序提供灵活的扩展和定制功能。(感谢百度百科)
Q:为什么用Lua?
A: 1、开源,就是不用钱。
2、灵活扩展你的软件(增加游戏关卡,制作文字类游戏等等)
3、灵活进行软件配置(例如一个GUI程序的界面微调,而且支持if...else...这样的配置方式,爽吧)
4、弱类型,这意味着在宿主语言内比较麻烦的逻辑计算操作都可以扔给lua
5、纯c编写,意味着比python这样的老牌脚本语言运行更快(话说python跑在虚拟机上的,跟java差不多)
Q:我感觉我很菜,能学习Lua么?
A:话说我也很菜。。总之你学会c语言后就能学Lua了,programming in lua里面有lua与c交互的例子。会c++更佳,游戏开发你总要会c++吧
一、新手任务——编译静态库,解析器,编译器
lua官网
http://www.lua.org/
找到最新的版本5.2.2下载下来
其实我们得到的是一堆源码,打开src文件夹看看
所以我们要自己编译想要的东西= =
先打开高端洋气的vs2012(呵呵
(配置方法跟微软其他的IDE差不多,只用vs2012举例)
新建一个空的控制台程序。然后把lua源码复制到工程目录下
并添加到项目
在release下配置类型为lib
为了编译静态库,需要把下面两个文件移除到工程外(lua.cpp是编译解析器的,luac就是用来编译编译器的= =)
如果你是用vs2012编译lib,请添加这个宏(感谢CHU提醒)
_CRT_SECURE_NO_WARNINGS
编译成功,生成lib
收起回复
∙6楼
∙2013-07-05 08:25
∙举报 |
∙
wishout: 自己在桌面建一个文件夹先把lib保存起来吧= =
2013-7-5 08:27 回复
∙
⑨chu: 你为何不直接点上面那个静态库呢。。
2013-7-7 00:04 回复
∙
梦里—唱忧伤: 同问,建工程直接选静态库就是。
接下来编译解析器= =
把配置类型改为exe 把用来编译解析器的lua.cpp添加回项目中
编译ok,生成编析器
为了在控制台下使用方便,可以改名为lua.exe
继续保存到新建的文件夹里= =
编译解编译器,把luac.cpp添加到项目,移除lua.h,lua.cpp
改名为luac.exe保存到刚才的文件夹下,现在我们要用到的东西都做好了,欧耶~
在使用这些东西之前,我们先来简单地了解一下lua语法,想深入学习的同学自己找些专业的资料
1、lua类型
lua分为这些类型Nil、Booleans、Numbers、Strings、Functions、Userdata、Threads
这些看名字都能懂吧。
Nil就是空,就是什么都没有(话说在java里面null不是一个对象,那老师怎么整天在说java一切都是对象,害我java考试那题没分了= =)
Booleans是布尔型,true 和 false
Numbers是数值类型,在lua里面,你学过的int float double long short都是这种数值类型,所以知道lua为什么被叫做弱类型语言了吧
而且由于我们可以这样声明一个Numbers
a = 4
b = 0.4
c = 4.57e - 3
d = 0.3e12
跟python一样,lua变量的类型只有在执行脚本的时候被确定,所以前面不用声明类型
Strings是字符串类型
通用地,我们这样声明一个Strings
s = "hello wishout!"
那些转义字符例如'\\n', '\', '\\\\'跟c是一样的,放心用吧
Functions是函数类型
在lua里面,我们这样下面的形式使用函数
function [函数名]([参数一], [参数二], [参数三]...)
end
哈哈,很简单吧
比如我们写一个NPC对话的函数
function PrintNPCMsg(msg)
print(msg)
end
2、表达式
算术运算符
+ - * / ^(加减乘除,还有幂!)
-(相反数)
关系运算符
< > <= >= == ~=
注意lua里面没有!=这个东西,被取代为~=
逻辑运算符
and or not(与、或、非)
特殊地,在字符串操作中,lua有很方便的一个操作符
..(两个点号,用来连接连个字符串)
例如
"hello " .. "wishout!" == "hello wishout!"
3、luaの神器——table的构造
为什么说table是神器呢?因为它很神啊!(废话)
table是lua里特有的东西(也不算特有吧,python也有元组,字典之类的东西)
类似于c语言里面数组的东西
构造方法如下
mytable = {"wishout", "sama", "i", "love", "you!", 1, 2, 3}
table里面可以放你任何想放的东西
table构造完以后,我们像访问数组一样访问table,注意lua的table下标从1开始,Strings也一样
mytable[1] == "wishout"
mytable[3] == "i"
mytable[6] == 1
字典方法构造table
mytable = {master = "wishout", servant = "you"}
我们现在可以这样访问table
mytable["master"] == "wishout"
servant["servant"] == "you"
用这样方法配置游戏相当的爽
config = {client_x = 100, client_y = 100, width = 0, height = 480, windowed = false}
这种方法还能管理游戏素材的映射,相当方便,欧耶~
我现在做的一个小游戏是这样管理一个背景纹理的映射的
我在c++里面就能很方便的取得这个背景纹理的信息,不用硬编码就是很爽啊
3、luaの神器(续)——table的遍历与维护
我们用# tablename这样方式取得一个table的长度,这种方法也适用于求一个字符串的长度
例如
mytable = {"wishout", "sama", "i", "love", "you!", 1, 2, 3}
s = "123"
# mytable == 8
# s == 3
既然我们得到了table的长度,我们就能遍历这个table
for i = 1, # mytable do
print(mytable[i])
end
输出:
wishout
sama
i
love
you!
1
2
3
我们这里使用了一个循环语句的知识,语法如下
for i = [起始下标], [终止下标], [步长] do
[循环体]
end
我们步长不写默认为一
往table里面插入元素的方法
table.insert(tablename, tableitem)
例如
table.insert(mytable, "shit")
也可以插入一个table
table.insert(mytable, {"holy ", "shit!"})
删除table元素的方法
table.remove(tablename, tableindex)
例如
table.remove(mytable, 1)
清空table的方法(so easy...)
tablename = {}
4、基本语法
控制语句
if [条件] then
[dotask]
end
if [条件] then
[dotask_1]
else
[dotask_2]
end
if [条件一] then
[dotask_1]
elseif [条件二] then
[dotask_2]
end
循环语句
while [条件] do
[循环体]
end
repeat
[循环体]
util [条件]
for i = [起始下标], [终止下标], [步长] do
[循环体]
end
*break在lua里的用法一样
*return用法一样
*lua里有个local关键字,被local声明的变量只在被声明的代码块里面有效
wishout: 以上语法在游戏开发里基本够用,更多高级语法请参详专业资料
二、点亮武器天赋——静态库、编译器、解析器的使用,两个好用的lua编辑器
好吧,我们学习完了lua的基本语法,现在拿我们编译好的东西玩玩\(^o^)/
我们先新建一个lua脚本文件,键入一条简单的语句
与解析器、编译器放在同一目录下
在命令行下进入该目录
使用lua -i命令进入lua交互模式,你能看到自己正在使用的lua版本
我们使用dofile("filename")命令调用lua解析器执行特定脚本
上面是执行lua脚本的方法一
下面介绍方法二
我们可以用luac.exe先把lua脚本编译一次,再去执行编译后的脚本,这样用户就不能随意修改我们编译后的脚本了,哈哈
首先退出交互模式
我们用这种形式编译特定脚本
luac -o [编译后脚本名] [脚本名]
编译成功后,目录下生成一个文件
再次进入交互模式,执行这个文件
执行结果是一样的,但这种方法能杜绝玩家修改脚本的可能
刚才我们使用notepad编辑lua脚本,作为一个程序猿,不会装逼怎么行!
所以呢,我向大家介绍两个好用的编辑器,如果你用过,当我没说= =
屌丝的好帮手——notepad++
如果你经常在window写代码,应该对这款软件有所耳闻吧,看看它的lua高亮方案
大概就是这种效果,还是蛮顺眼的= =
高帅的象征——Sublime Text 2
我从刚用sublime text 2的时候,瞬间有种屌丝变高帅,村里刚通网的感觉!我马上意识到,这是一款高帅的软件,帅的无法直视啊啊啊啊啊
lua高亮方案
Sublime Text 2还支持脚本的执行(果然是高帅的软件),实际上要配置一下的,自己到网上找= =
使用静态库——c/c++与lua的交互
在vs下建立一个控制台空项目,项目包含src下面的头文件,附加库和依赖项填好刚才编译好的lib
项目里建立一个源文件Main.cp,包含我们要用到的头文件
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
声明一个全局变量
lua_State * L;
在main里面开始lua的初始化工作
//开启lua状态机
L = luaL_newstate();
//装载lua库
luaL_openlibs(L);
相比起d3d,lua的初始化操作太简单了,我要感动的哭了T_T
//执行脚本
luaL_dofile(L, "res.lua");
//关闭lua状态机
lua_close(L);
c++调用lua函数的例子
//c++调用lua函数
void PrintMsg(const char * msg)
{
//填充一个lua函数名
lua_getglobal(L, "PrintMsg");
//参数进栈
lua_pushstring(L, msg);
//使用lua_pcall调用lua本函数
if(lua_pcall(L, 1, 0, 0) != 0)
std::cout << "FAILED - PrintMsg(): " << std::cout << lua_tostring(L, -1);
}
void main (void)
{
//开启lua状态机
L = luaL_newstate();
//装载lua库
luaL_openlibs(L);
//执行脚本
luaL_dofile(L, "mylua.lua");
//调用函数
PrintMsg("hello wishout!");
system("pause");
//关闭lua状态机lua_close(L);
}
//lua脚本
function PrintMsg(msg)
print(msg)
end
lua调用c++函数的例子
//lua调用c++函数
int Add(lua_State * L)
{
//提取参数
int a = (int)lua_tonumber(L, 1);
int b = (int)lua_tonumber(L, 2);
//c++实际完成的工作
int c = a + b;
//计算结果进栈
lua_pushnumber(L, c);
//因为要返回一个参数,所以要return 1
return 1;
}
void main (void){
//开启lua状态机
L = luaL_newstate();
//装载lua库
luaL_openlibs(L);
//往lua脚本添加c++函数
lua_pushcfunction(L, Add);
//添加一个函数名
lua_setglobal(L, "Add");
//执行脚本luaL_dofile(L, "mylua.lua");
system("pause");
//关闭lua状态机
lua_close(L);
}
lua脚本
print(Add(1, 2))
三、魔法学堂——lua的简单应用
嘛嘛,楼主写了一上午的帖子,这层就结束了
下面是我以前练手用的控制台版avg源码,里面有注释,可以简单看一下lua的实际使用(我承认写的很渣= =)
http://pan.baidu.com/share/link?shareid=3286131315&uk=1208824379
---完---
表扬吧主大人的无私奉献
咳咳
然后、、其实、、Lua的CAPI用起来不是那么简单的,你要查询每个函数会造成什么副作用
比如会对lua虚拟机的堆栈造成什么影响(弹出几个元素、加入几个元素)
Lua本身还涉及到GC、注册表、Upvalue等等各种概念
为了方便与C++交互,网上有很多Lua的扩展。
如tolua+、luabind、luaplus等等
通过这些扩展你可以直接在lua里面创建一个C++类。
把C++类成员函数绑定到lua里面等等