太阳神三国杀lua教程

太阳神三国杀lua教程
太阳神三国杀lua教程

--大家好我是hypercross。

--从这个文件开始讲解DIY接口的用法。

--首先,这个文件说明DIY需要的文件及其结构。

--DIY是以module的形式存在的。每个Module即是一个UTF8格式的Lua文件(建议用notepad++编辑),包含如下格式的代码:

module("extensions.moligaloo", package.seeall)

-- 进入module。这里moligaloo这个词必须和文件名相同。

extension = sgs.Package("moligaloo")

-- 创建扩展包对象。变量名必须为extension。参数名为扩展包的objectName,也是通常会使用的扩展包标识

shiqian = sgs.General(extension, "shiqian", "qun")

-- 创建武将对象,这里我们的武将是时迁。关于武将属性的详细说明见reference文档。

shentou = sgs.CreateViewAsSkill{

--创建技能,技能种类为ViewAsSkill。这里的技能是“出牌阶段,你可以将任意一张梅花手牌当作顺手牵羊使用。”

name = "shentou",

n = 1,

view_filter = function(self, selected, to_select)

return to_select:getSuit() == sgs.Card_Club and not to_select:isEquipped() end,

view_as = function(self, cards)

if #cards == 1 then

local card = cards[1]

local new_card =sgs.Sanguosha:cloneCard("snatch", card:getSuit(), card:getNumber())

new_card:addSubcard(card:getId())

new_card:setSkillName(self:objectName())

return new_card

end

end

}--关于技能的说明将是几乎所有其他帮助文件的重点。此处省略。

sgs.LoadTranslationTable{

["shentou"] = "神偷",

[":shentou"] = "你可以将你的梅花手牌当做顺手牵羊使用。",

}

--此段为翻译,将技能名称与描述中文化,否则你将会看到拼音

shiqian:addSkill(shentou)

--将神偷技能赋予时迁

--你可以将本文件保存至extension目录下的moligaloo.lua并启动游戏。此时扩展包即已经被添加至游戏。

--为了完善DIY扩展包,需要将音频、图片以及翻译代码放到指定目录。这一点将在其他文档中说明。

--技能详解1:ViewAsSkill(视为技,也叫视作技)

--在太阳神三国杀中,常用的基本技能是两种:触发技和视为技。我们使用这两种基本技能的复合来完成大多数复杂的技能。

--此外,我们还有距离技,禁止技等特殊类型的技能,它们用于实现某些某种程度上“要求改变游戏系统” 的技能。

--触发技可以用来实现”在某个时机,满足发动条件时,执行某个效果(包括做出选择)这样的技能。

--触发技也可以用来改变游戏事件而不仅是单纯的产生效果。比如,放弃摸牌阶段并执行xx 这样的技能也可以用触发技实现。

--事实上,一个触发技就是一条游戏规则。如果某名武将具有某个触发技,这个触发技就会被在服务端“注册”成为这局游戏的一条规则。

--被注册的触发技,通常会根据玩家“是否存活”以及玩家的武将“是否具有该技能”来决定是否被执行。

--视为技可以用来实现“可将某牌作为某牌打出”这样的技能。

--视为技的定义对于AI而言是无效的。为了让AI使用视为技,你基本上需要在AI中重新写一遍技能的定义。

--这是因为视为技是在客户端运行的,而AI在服务器端运行;触发技也是在服务端运行。--如果某名玩家具有某个视作技,该技能通常就会被”注册“到该玩家的客户端。这个动作与其他玩家是不相干的。

--总之,视为技负责在客户端管理,有哪些牌可以选中,选中的牌又会被当成什么牌,这样的效果;

--但是视为技的运行本身不影响游戏进程;视为技做的事情是通过将特定的牌(甚至没有牌)“视为”特定的牌,

--来允许你使用那张本来不存在的牌。这也是大多数”主动技能“的实现方式。

--距离技和禁止技则分别用于实现“修改玩家间的距离”,以及“某人不能对某人使用某牌”这样的效果。

--与其他两种技能不同,距离技和禁止技不需要在某局游戏中注册:距离技是永远生效。

--也就是说,如果你写了一个距离技能叫”所有玩家间的距离-1“,那么无论场上有没有玩

家具有这个技能,

--所有玩家间的距离都会被减一。禁止技也类似。

--这类技能的定义比较新,也比较清楚明了,可能你不需要看文档也能明白。

--正片开始

--首先讲解视为技。

--视为技在Lua中的创建使用了sgs.CreateViewAsSkill方法

-- **程序细节,以下可跳过

--sgs.CreateViewAsSkill方法可以在lua\sgs_ex.lua中找到。

--该方法会创建一个LuaViewAsSkill对象(定义见cpp源码),然后将你定义的Lua函数用于其成员函数。

--注意,本游戏cpp源码部分使用了类的继承重载来实现不同的技能,而在lua的DIY技能里面我们都使用固定的类

--我们通过将会被用作技能成员函数的lua function,直接赋给技能的实例来实现不同的技能。

-- **程序细节部分结束

--视为技在创建时,需要以下方法|变量的定义:

--name, n, view_filter, view_as, enabled_at_play和enabled_at_response

--name:

--一个字符串即技能名称。

--该字段必须定义。(无默认值)

--n:

--整数值,每次发动技能所用牌数的最大值。绝大多数DIY用到的n可能都为1或2.

--默认值为0,即不需要选择自己的任何牌.

--view_filter:

--lua函数,返回一个布尔值,即某张卡是否可被选中以用作发动技能。

--发动技能时,将对所有手牌、装备进行遍历,并执行view_filter方法。返回了true的牌可以被选择用作技能发动。

--传入的参数为self(技能对象本身),selected(lua表,已经选择的所有牌), to_select(当前需判断是否可选中的牌)

--默认为"永远返回false",即如果你没有定义,则这个技能的发动不允许你选择任何牌。

--view_as:

--lua函数,返回一个card对象,即被选中的牌应当被视为什么牌被打出或使用。

--这里的牌可以是游戏牌,也可以是技能牌。

--如果你的DIY主动技能的效果不是某张游戏牌的效果,那么你需要把该效果定义到一个技能牌当中

--然后在view_as方法中得到并返回一张你定义的技能牌。

--传入参数为self(技能对象本身),cards(lua表,已经选择的所有牌)

--默认为"返回空对象",即如果你没有定义,那么这个技能的发动永远不允许你点确定。

--enabled_at_play

--lua函数,返回一个布尔值,即你在出牌阶段是否可以使用该技能。(该按钮是否可点)

--传入参数为self(技能对象本身),player(玩家对象)

--默认为true,即如果你没有定义,你永远可以在出牌阶段使用本技能。

--enabled_at_response

--lua函数,返回一个布尔值,即你在需要用响应时,是否可以使用本技能进行响应。

--传入参数为self(技能对象本身),player(玩家对象),pattern(要求响应的牌的匹配规则) --默认为false,即如果你没有定义,你永远不可以在响应时使用本技能。

--** 实例

--以下为“任意一张草花牌”的view_filter方法:

n=1,

view_filter = function(self, selected, to_select)

return to_select:getSuit()==sgs.Card_Club

end,

--getSuit()返回一张牌的花色的enum。

--如果to_select的花色为草花Club,则返回真(可被选择)。否则返回假(不可被选择)。

--以下为“任意两张同花色手牌“的view_filter方法:

n=2,

view_filter = function(self, selected, to_select)

if #selected<1 then return not to_select:isEquipped() end

return to_select:getSuit()==selected[1]:getSuit() and not to_select:isEquipped()

end,

--如果选中的牌数小于1,那么任何未被装备的牌(手牌)都可以被选择;

--否则,只有那些和已被选中的第一张牌花色相同的牌才能被选中。

--以下为”当成借刀杀人使用“的view_as方法部分:

n=1,

view_as = function(self, cards)

if #cards<1 then return nil end

--如果没有牌被选中,那么返回空对象

local suit,number

for _,card in ipairs(cards) do

if suit and (suit~=card:getSuit()) then suit=sgs.Card_NoSuit else suit=card:getSuit() end

if number and (number~=card:getNumber()) then number=-1 else number=card:getNumber() end

end

--如果所有被选中的牌的花色一样,那么被视为的借刀杀人的花色也为该花色。否则,该借刀杀人无花色。

--点数同理。

local view_as_card= sgs.Sanguosha:cloneCard("collateral", suit, number)

--生成一张借刀杀人

for _,card in ipairs(cards) do

view_as_card:addSubcard(card:getId())

end

--将被用作视为借刀杀人的牌都加入到借刀杀人的subcards里

view_as_card:setSkillName(self:objectName())

--标记该借刀杀人是由本技能生成的

return view_as_card

end,

--将使用到的牌加入生成的借刀杀人的子牌列表中这一步,通常是必须的。

--因为可能存在对牌进行互动的技能,比如发动奸雄会得到发动乱击用的两张牌。

--将技能的名字即self:objectName赋予该卡的技能名属性,还是用于标记方便。

--需要其他游戏牌时,改动collateral这个名字即可。需要根据不同种类、数量的牌得到不同游戏牌时,改动if #cards<1 then 这句即可。

--当技能的效果不能简单地描述为”视为你打出了xx牌“时,你需要使用技能牌定义技能的效果。

--也就是说,将你的技能转述为”你可以将你的xx牌作为xx牌打出,其中xx牌的效果为blahblah“。然后,在技能牌的定义中实现技能的效果。

--技能的效果用”技能牌“实现,技能的发动约束用”视为技“实现,技能的发动时机控制用”触发技“实现。

--以下是貂蝉离间技能的view_as方法:

view_as = function(self, cards)

if #cards<1 then return nil end

local view_as_card=lijian_Card:clone()

--lijian_Card的定义应该被包含在同一个module文件当中。我将在其他文档中讲解技能牌的定义。

for _,card in ipairs(cards) do

view_as_card:addSubcard(card:getId())

end

return view_as_card

end,

--以下是周瑜“反间”的enable_at_play方法:

enabled_at_play=function(self,player)

return not player:hasFlag("fanjian_used")

--反间只能每回合用一次。如果你已经使用过了,那么你不能再次使用。

end

--注意在lua中暂时不能使用player:hasUsed方法来判断是否用过你的某个LuaSkillCard --因为LuaSkillCard并不使用在cpp里面用的类继承机制

--请暂时在你的LuaSkillCard中执行类似于room:setPlayerFlag(effect.from,"fanjian_used")

--这样的语句,然后在enabled_at_play里面使用player:hasFlag。

--以下是大乔”流离“的enabled_at_response方法:

enabled_at_response=function()

return sgs.Self:getPattern()=="#liuli_effect"

--仅在询问流离时可以发动此技能

--这里的函数没有参数传入(我们不需要)

--我们直接调用了sgs.Self,这个对象就是本地的ClientPlayer对象。

--注意:只有在本地运行的代码(比如视作技)可以调用到sgs.Self。

end

--虽然看起来流离并不像是一个视作技

--但事实上我们把它分成了这样的三部分:

--1、你成为杀的目标时,你可以响应使用"流离牌"(技能牌)。用触发技实现。

--2、在且仅在你响应使用"流离牌"时,你可以将任意一张牌视为"流离牌"使用。用视为技实现。

--3、流离牌的效果为:流离牌的目标成为杀的目标,该杀跳过对你的结算。用技能牌实现。

--注意到正常情况下pattern永远不会自己就是"#liuli_effect"

--你需要在触发技当中使用room:askForUseCard(daqiao,"#liuli_target",prompt)

--这样,就可以创造出一个专门用于流离的响应来。

--技能详解3:TriggerSkill 触发技

--许多技能都有”在xx时机,如果xx条件满足,那么执行xx效果“这样的描述。

--由于游戏技时机繁多,许多技能也都是相互类似的,我们在游戏的cpp部分有种类繁多的触发技定义方式。

--而基本的(也是万能的)触发技定义在Lua中是使用sgs.CreateTriggerSkill方法,该方法可以在lua\sgs_ex.lua中找到。

--CreateTriggerSkill需要以下参数:

--name, frequency, events, on_trigger, can_trigger, priority

--name:

--技能名称字符串

--没有默认……技能就是要有名字才行

--frequency:

--Frequency枚举类型,技能的发动频率。

--执行askForSkillInvoke(询问技能发动)时,frequency会影响玩家做决定的方式。

--frequency也起到了技能分类以及用于增加技能提示显示的作用。

--frequency可能的值有:

--sgs.Skill_Frequent(频繁发动:该技能会有一个可以打钩的按钮,如果勾选上,askForSkillInvoke就不会弹出提示而是直接返回true)

--sgs.Skill_NotFrequent(不频繁发动:该技能的askForSkillInvoke总是会弹出提示询问玩家是否发动)

--sgs.Skill_Compulsory (锁定技:该技能的默认优先度为2而不是1;该技能会在显示上提示玩家这是一个锁定技能)

--sgs.Skill_Limited (限定技:该技能会在显示上提示玩家这是一个限定技能)

--ssg.Skill_Wake(觉醒技:该技能的默认优先度为2而不是1;该技能会在显示上提示玩家这是一个觉醒技)

--frequency的默认值为sgs.Skill_NotFrequent

--events:

--Event枚举类型,或者一个包含Event枚举类型的lua表。代表该技能的触发时机。

--可用的Event列表请参考游戏代码中的struct.h文件。

--无默认值。

--on_trigger:

--lua函数,无返回值,执行事件触发时的技能效果。

--如果需要区分不同的事件执行不同效果,请根据event参数使用条件语句。

--通常需要将事件数据(data)转为具体的游戏结构对象才能进行操作。你可以在源码的swig/qvariant.i文件中看到定义。

--on_trigger的传入参数为self(技能对象本身),event(当前触发的事件),player(事件触发者),data(事件数据)

--无默认值。

--can_trigger:

--lua函数,返回一个布尔值,即是否能触发该技能。

--传入参数为self(技能对象),target(事件触发者)

--默认条件为“具有本技能并且存活”

--在这里个人只建议写简单的条件,许多判断都放在on_trigger里面做return其实都是可以的

--priority:

--整数值,代表本技能的优先度。

--如果本技能与其他技能(或规则)在同一个时机都触发,那么优先度影响这些技能或规则的执行顺序。

--优先度更大的技能(或规则)优先执行。游戏规则的优先度为0,典型的技能优先度为1,而受到伤害发动的技能优先度通常为-1.

--锁定技和觉醒技的优先度默认为2,其他情况下默认为1

-- **实例:

--以下是曹操奸雄的实现:

jianxiong=sgs.CreateTriggerSkill{

frequency = sgs.Skill_NotFrequent,

name = "jianxiong",

events={sgs.Damaged}, --或者events=sgs.Damaged

on_trigger=function(self,event,player,data)

local room = player:getRoom()

local card = data:toDamage().card

--这两步通常是必要的。我们需要room对象来操作大多数的游戏要素,我们也需要将data对象转成对应的数据类型来得到相应的信息。

if not room:obtainable(card,player) then return end

if room:askForSkillInvoke(player,"jianxiong") then

room:playSkillEffect("jianxiong")

player:obtainCard(card)

end

end

}

--在on_trigger方法中,我们首先获取了room对象。

--对于影响整盘游戏的效果,我们必须需要获取room对象。大多数情况下,room对象都是必须获取的。

--on_trigger方法的data参数是一个QVariant,根据不同的事件我们需要用不同的方法得到它原本的数据类型。

--对于Damaged事件(你受到了伤害),data对象的类型是DamageStruct,我们使用toDamage()得到DamageStruct。

--询问技能发动时,需要使用room对象的askForSkillInvoke方法。

--playSkillEffect方法则可以播放技能的发动效果。(但是对技能发动效果本身没有影响)

--player:obtainCard(card) 即让player得到造成伤害的card。

--在”某个阶段可触发“的技能,或者”摸牌时改为xx“这样的技能,可以使用PhaseChange 事件来触发,并对event对象进行判断进行触发控制。

--对于在复数个时机发动的触发技,我们需要在on_trigger中使用条件语句。

--以下是袁术”庸肆“技能的实现:

yongsi=sgs.CreateTriggerSkill{

frequency = sgs.Skill_Compulsory, --锁定技

name = "yongsi",

events={sgs.DrawNCards,sgs.PhaseChange}, --两个触发时机

on_trigger=function(self,event,player,data)

local room=player:getRoom()

local getKingdoms=function() --可以在函数中定义函数,本函数返回存活势力的数目

local kingdoms={}

local kingdom_number=0

local players=room:getAlivePlayers()

for _,aplayer in sgs.qlist(players) do

if not kingdoms[aplayer:getKingdom()] then

kingdoms[aplayer:getKingdom()]=true

kingdom_number=kingdom_number+1

end

end

return kingdom_number

end

if event==sgs.DrawNCards then

--摸牌阶段,改变摸牌数

room:playSkillEffect("yongsi")

data:setValue(data:toInt()+getKingdoms())

--DrawNCards事件的data是一个int类型的QVariant即摸牌数,改变该QVariant对象会改变摸牌数

elseif (event==sgs.PhaseChange) and (player:getPhase()==sgs.Player_Discard) then

--进入弃牌阶段时,先执行庸肆弃牌,然后再执行常规弃牌

local x = getKingdoms()

local e = player:getEquips():length()+player:getHandcardNum()

if e>x then room:askForDiscard(player,"yongsi",x,false,true)

--要求玩家弃掉一些牌

-- 最后两个参数为”是否强制“以及”是否包含装备“

else

--如果玩家的牌未达到庸肆的弃牌数目,那么跳过询问全部弃掉

player:throwAllHandCards()

player:throwAllEquips()

end

end

end

}

--技能讲解2:技能牌SkillCard

--神杀中,技能的效果在很多时候都技能牌实现。即,把技能定义在一张没有实体的抽象“牌”当中,当你发动技能的时候,视为你使用了这张牌。

--对于指定对象发动的技能,对象的指定也算在牌的效果当中。

--很多游戏的技能发动都带有cost这个概念,即发动技能的代价。神杀中,cost只能是你的牌或装备;也就是说,

--cost只能靠ViewAsSkill来实现。如果想实现类似于“发动代价”这样的效果,请用“发动技能的负面效果”这样的概念来替换。

--由于技能牌的需要有多个实例存在(每次发动技能得到一个技能牌),

--我们在DIY module当中并不像ViewAsSkill和TriggerSkill当中使用构造函数来创建SkillCard。

--我们需要将SkillCard的参数在一个lua table当中定义好,然后在每次需要创建SkillCard的时候再调用sgs.CreateSkillCard获取SkillCard对象。

--或者,我们也可以先创建好一个SkillCard,然后在技能中复制它。

--sgs.CreateSkillCard需要以下参数定义:

--name,target_fixed,will_throw, filter,feasible,on_use,on_effect

--name:

--字符串,牌的名字。取个好听的名字~

--没有默认值。快去取名字……

--target_fixed:

--布尔值,使用该牌时是否需要玩家指定目标。

--默认为false,使用时你需要指定目标,然后点确定。

--will_throw:

--布尔值,该牌在使用后是否被弃置。还记得subCards吗?

--对于拼点技能,请将will_throw设为false,否则对方将看到你的牌之后再选择拼点牌。--也可以将will_throw设为false,然后使用room:throwCard(card)这个方法来灵活地控制如何将牌移动到弃牌区。

--默认值为true。

--filter:

--lua函数,返回一个布尔值,类似于ViewAsSkill中的view_filter,但filter方法的对象是玩家目标。

--你在使用牌时只能指定玩家为对象,不能直接指定玩家的某张牌为对象;

--比如过河拆桥,在神杀中,“选择对方的一张牌并弃置”是过河拆桥的效果,但过河拆桥的对象只有对方玩家。

--如果你确实需要“作为对象的牌”,请还是在了解游戏机制后自行发明解决方法……

--传入参数为self,targets(已经选择的玩家),to_select(需要判断是否能选择的玩家)

--默认条件为“一名其他玩家”。

--feasible:

--lua函数,返回一个布尔值,相当于viewasSkill的view_as方法是否应该返回nil。

--在viewAsSkill中,我们可以无数次选中牌,直到返回了有意义的view_as再点确定,

--所以view_as返回了无意义的Nil也无所谓;然而在SkillCard当中,点确定的机会只有一次,

--因此我们规定用feasible来排除无效使用的情况。

--只有在feasible返回了true时,你才可以点确定。

--传入参数为self,targets(已经选择的玩家)

--默认条件为"target_fixed为true(不需要指定目标),或者选择了至少一名玩家为目标"

--on_use:

--lua函数,无返回值,类似于on_trigger,执行使用效果。

--传入参数为self,room(游戏房间对象),source(使用者),targets(牌的使用目标)

--无默认。

--on_effect:

--lua函数,无返回值,同样用于执行使用效果,但只定义对于某一个目标的效果。

--通常情况下你只需要写on_effect或者on_use当中的一个。

--如果是没有目标或者是目标特定的技能,使用on_use;

--如果是有几个目标执行相同或类似的效果,使用on_effect。

--如果是玩家指定的目标,还是使用on_effect。

--以下为“离间牌”的 feasible 以及filter方法:

filter=function(self,targets,to_select)

if (not to_select:getGeneral():isMale()) or #targets>1 then return false elseif to_select:hasSkill("kongcheng") and to_select:isKongcheng() and #targets==0 then return false

else return true end

--当已经选择了多于1名玩家时,不能选择其他玩家。

--空城诸葛不能选择。

end

feasible=function(self,targets)

return #targets==2

--只有选择了2名玩家时,才能使用牌

end

--on_use 和 on_effect 为牌的效果执行。他们的区别在于生效时机的不同。

--on_use在牌被使用时生效,而on_effect在牌在使用中对某一名目标进行结算时生效。

--因此,在不存在需要结算“一名玩家对另一名指定的玩家”的效果时,使用on_use实行效果即可;

--存在指定的目标时,则原则上应该使用on_effect。

--on_use和on_effect可以同时存在。牌效果进行结算时,先执行on_use,然后对每名目标

执行on_effect

--以下为“雷击牌”的on_effect方法:

on_effect=function(self,effect)

--effect 为一个CardEffectStruct,其from和to为player对象,代表谁使用的牌对谁结算

local from=effect.from

local to =effect.to

local room=to:getRoom()

--sefEmotion在玩家的头像上显示表情

room:setEmotion(to,"bad")

--进行判定时,首先创建“判定”对象。

--pattern为一个正则表达式,由冒号隔开的三段分别匹配牌名、花色和点数

--good的定义和之后的判定结果获取有关。

--原则上,之前的pattern与判定牌匹配时,如果这种情况下执行的效果对于判定者来说是“好”的,

--那么good应该是true。

local judge=sgs.JudgeStruct()

judge.pattern=sgs.QRegExp("(.*):(spade):(.*)")

judge.good=false

judge.reason="leiji"

judge.who=to

--然后,让room根据此判定对象进行判定。判定结果依然在judge里面。

room:judge(judge)

--如果判定结果是一个“坏”结果,那么造成伤害

if judge.isBad() then

--和判定一样,造成伤害时先创建伤害struct,然后交由room:damage执行

local damage=sgs.DamageStruct()

damage.card = nil

damage.damage = 2

damage.from = from

damage.to = to

damage.nature = sgs.DamageStruct_Thunder

room:damage(damage)

else

room:setEmotion(from,"bad")

end

end,

--以下为孙权“制衡”的on_use方法:

on_use=function(self,room,source,targets)

--self代表技能牌本身。由于是将“任意张牌当成制衡牌打出”,

--因此弃置制衡牌就等于弃置所有用来发动制衡的牌,也即被制衡掉的牌。

room:throwCard(self)

--摸取相当于被用来发动制衡的牌的数目的牌。

--可以用self:getSubcards()来获取这些牌的QList。

room:drawCards(source,self:getSubcards():length())

end,

--技能讲解4:基本技能类型的组合与复杂技能的实现

--大多数技能都不是单独使用ViewAsSkill或者TriggerSkill就可以实现的。复杂的技能往往需要结合多种基本技能。

--一个的技能的描述,往往可以分成3部分:发动的时机、发动代价、效果。

--对于发动时机的控制,是只有触发技可以实现的。触发技可以在任何“有定义的时机”时产生作用。然而,对于需要根据消耗牌来决定效果的那些技能,用触发技往往无法实现,也很难符合游戏流程。

--ViewAsSkill可以非常完美地实现技能的发动流程。只有VIewAsSkill可以细致地操纵玩家发动技能所付出的代价。然而,ViewAsSkill本身并没有技能效果的实现,只能使用游戏牌作为技能效果,或者借助SkillCard。

--SkillCard本身并不是一个技能,但是只有他可以把技能发动用牌和技能效果联系起来。它对于ViewAsSkill而言是必需的。

--1.结合基本技能的方法:

--我们把技能效果定义在一个技能牌skill_card当中,技能牌的定义可以不从属于任何技能。然后,由于时机判断是整个技能的发动最先进行的一步,我们将ViewAsSkill定义在TriggerSkill当中。最后,我们把TriggerSkill的发动效果设为“询问使用skill_card”,而ViewAsSkill的效果设为“你可以将特定牌作为skill_card使用或打出”。如此,即实现了“xxx时,你可以使用xx牌发动,执行xxx效果。”

--以下为大乔流离技能的实现:

liuli_card=sgs.CreateSkillCard{

name="liuli_effect",

target_fixed=false,

will_throw=true,

filter=function(self,targets,to_select)

if #targets>0 then return false end

if to_select:hasFlag("slash_source") then return false end

local card_id=self:getSubcards()[1]

if sgs.Self:getWeapon() and sgs.Self:getWeapon():getId()==card_id then return sgs.Self:distanceTo(to_select)<=1

end

return sgs.Self:canSlash(to_select,true)

end,

on_effect=function(self,effect)

effect.to:getRoom():setPlayerFlag(effect.to,"liuli_target")

end

}

liuli_viewAsSkill=sgs.CreateViewAsSkill{

name="liuli_viewAs",

n=1,

view_filter=function(self, selected, to_select)

return true

end,

view_as=function(self, cards)

if #cards==0 then return nil end

local aliuli_card=liuli_card:clone()

--使用之前创建的skillCard的clone方法来创建新的skillCard

aliuli_card:addSubcard(cards[1])

return aliuli_card

end,

enabled_at_play=function()

return false

end,

enabled_at_response=function()

return sgs.Self:getPattern()=="#liuli_effect"

--仅在询问流离时可以发动此技能

end

}

liuli_triggerSkill=sgs.CreateTriggerSkill{

name="liuli_main",

view_as_skill=liuli_viewAsSkill,

events={sgs.CardEffected},

on_trigger=function(self,event,player,data)

local room=player:getRoom()

local players=room:getOtherPlayers(player)

local effect=data:toCardEffect()

if effect.card:inherits("Slash") and (not player:isNude()) and room:alivePlayerCount()>2 then

local canInvoke

for _,aplayer in sgs.qlist(players) do

if player:canSlash(aplayer) then

canInvoke=true

end

end

if not canInvoke then return end

local prompt="#liuli_effect:"..effect.from:objectName()

room:setPlayerFlag(effect.from,"slash_source")

if room:askForUseCard(player,"#liuli_effect",prompt) then

room:output("ha?")

for _,aplayer in sgs.qlist(players) do

if aplayer:hasFlag("liuli_target") then

room:setPlayerFlag(effect.from,"-slash_source")

room:setPlayerFlag(aplayer,"-liuli_target")

effect.to=aplayer

room:cardEffect(effect)

return true

end

end

end

end

end,

}

sgs.LoadTranslationTable{

["liuli_main"] = "lua流离",

[":liuli_main"] = "和流离技能描述一摸一样",

["#liuli_effect"] = "和流离的询问字串一摸一样",

}

--翻译代码

--技能实现说明:

--此技能的实现分3个部分

--第一部分是流离牌,效果为“将目标标记为流离对象”

--第二部分是流离ViewAsSkill,“每当你需要打出一张流离牌时,你可以将任意一张牌当作流离牌打出”

--第三部分是流离TriggerSkill,“触发技,每当你成为杀的目标时,你可以打出一张流离牌,然后让具有流离标记的对象代你成为杀的目标”

LUA各种库

1.math库 函数名描述示例结果 pi圆周率math.pi 3.1415926535898 abs取绝对值math.abs(-2012)2012 ceil向上取整math.ceil(9.1)10 floor向下取整math.floor(9.9)9 max取参数最大值math.max(2,4,6,8)8 min取参数最小值math.min(2,4,6,8)2 pow计算x的y次幂math.pow(2,16)65536 sqrt开平方math.sqrt(65536)256 mod取模math.mod(65535,2)1 modf取整数和小数部分math.modf(20.12)200.12 randomseed设随机数种子math.randomseed(os.time()) random取随机数math.random(5,90)5~90 rad角度转弧度math.rad(180) 3.1415926535898 deg弧度转角度math.deg(math.pi)180 exp e的x次方math.exp(4)54.598150033144 log计算x的自然对数math.log(54.598150033144)4 log10计算10为底,x的对数math.log10(1000)3 frexp将参数拆成x*(2^y)的形式math.frexp(160)0.6258 ldexp计算x*(2^y)math.ldexp(0.625,8)160 sin正弦math.sin(math.rad(30))0.5 cos余弦math.cos(math.rad(60))0.5 tan正切math.tan(math.rad(45))1 asin反正弦math.deg(math.asin(0.5))30 acos反余弦math.deg(math.acos(0.5))60 atan正切math.deg(math.atan(1))45

串口屏LUA教程-定时器的使用

工程技术笔记 LUA 教程-定时器的使用V1.0 Technical Note

修订历史 版本日期原因编制审查V1.02019/01/15创建文档林绍佳刘启鑫

目录 1.适合范围 (1) 2.开发环境版本 (2) 3.概述 (3) 4.实现教程 (4) 4.1工程准备 (4) 4.1.1硬件平台 (4) 4.1.2素材准备 (4) 4.1.3LUA编辑器 (5) 4.2API函数说明 (6) 4.3教程实现过程 (7) 4.3.1定时器的使用 (7) 4.4编译和下载 (10) 4.4.1编译工程 (10) 4.4.2下载 (11) 5.完整程序清单 (12) 6.免责声明 (15)

1.适合范围 该文档适合所有大彩物联型系列。

2.开发环境版本 1.VisualTFT软件版本:V3.0.0.944及以上的版本。 版本查看: a)打开VisualTFT软件启动页面如图2-1软件版本,右上角会显示的软件版本号; 图2-1软件版本 b)打开VisualTFT,在软件右下角可以查看软件版本图2-2软件版本, 最新版本可登录大彩官网进行下载。 图2-2软件版本 2.串口屏硬件版本:V 3.0.301.0及以上的版本。 版本查看: a)查看屏幕背面版本号贴纸; b)VisualTFT与屏幕联机成功后,右下角显示的版本号。 3.LUA语言版本V5.5。

3.概述 物联型可以通过LUA脚本配合工程完成丰富多样的操作。 本文将介绍在LUA脚本中使用定时器循环设置按钮的状态。在按下按钮后,定时器启动,定时器以设定的时间为标准,循环设置灯亮/灭。

串口屏LUA例程-音频播放器V1.0

工程技术笔记 LUA 例程-音频播放器V1.0 Technical Note

修订历史 版本日期原因编制审查V1.02019/02/28创建文档林青田刘启鑫

目录 1.适合范围 (1) 2.开发环境版本 (2) 3.概述 (3) 4.参考资料.........................................................................错误!未定义书签。 5.教程实现 (4) 5.1准备工程素材 (4) 5.1.1硬件平台 (4) 5.1.2UI素材准备 (4) 5.1.3LUA编辑器 (5) 5.2API函数说明 (6) 5.3实现功能 (8) 5.3.1工程配置 (8) 5.3.2程序具体解析 (8) 6.完整程序清单 (13) 7.免责声明 (24)

1.适合范围 该文档适合所有广州大彩物联型系列。

2.开发环境版本 1.VisualTFT软件版本:V3.0.0.944及以上的版本。 版本查看: a)打开VisualTFT软件启动页面如图2-1软件版本,右上角会显示的软件版本号; 图2-1软件版本 b)打开VisualTFT,在软件右下角可以查看软件版本图2-2软件版本, 最新版本可登录大彩官网进行下载。 图2-2软件版本 2.串口屏硬件版本:V 3.0.301.0及以上的版本。 版本查看: a)查看屏幕背面版本号贴纸; b)VisualTFT与屏幕联机成功后,右下角显示的版本号。 3.LUA语言版本V5.5。

3.概述 物联型串口屏通过LUA脚本配合工程可以实现播放循环屏内部或者外部音频的功能。

XLua_API

C# API LuaEnv类 object[] DoString(string chunk, string chunkName = "chuck", LuaTable env = null) 描述: 执行一个代码块。 参数: chunk: Lua代码文字串; chunkName:发生error时的debug显示信息中使用,指明某某代码块的某行错误; env :这个代码块的环境变量; 返回值: 代码块里return语句的返回值; 比如:return 1, “hello”,DoString返回将包含两个object的数组,一个是double类型的1,一个是string类型的“hello” 例子: LuaEnv luaenv = new LuaEnv(); object[] ret = luaenv.DoString("print(‘hello’)\r\nreturn 1") UnityEngine.Debug.Log("ret="+ret[0]); luaenv.Dispose() T LoadString(string chunk, string chunkName = "chunk", LuaTable env = null) 描述: 加载一个代码块,但不执行,只返回类型可以指定为一个delegate或者一个LuaFunction 参数: chunk: Lua代码的字符串; chunkName:发生error时的debug显示信息中使用,指明某某代码块的某行错误; env :这个代码块的环境变量; 返回值: 代表该代码块的delegate或者LuaFunction类; LuaTable Global; 描述: 代表lua全局环境的LuaTable void Tick() 描述: 清除Lua的未手动释放的LuaBase对象(比如:LuaTable, LuaFunction),以及其它一些事情。 需要定期调用,比如在MonoBehaviour的Update中调用。 void AddLoader(CustomLoader loader)

xLua教程

教程 文件加载 一、执行字符串 最基本是直接用执行一个字符串,当然,字符串得符合语法 比如:("(' ')") 完整代码见\\\目录 但这种方式并不建议,更建议下面介绍这种方法。 二、加载文件 用的函数即可 比如:(" ''") 完整代码见\\\目录 实际上是调一个个的去加载,有一个成功就不再往下尝试,全失败则报文件找不到。 目前除了原生的外,还添加了从加载的,需要注意的是因为只支持有限的后缀,放下的文件得加上后缀(见附带的例子)。 建议的加载脚本方式是:整个程序就一个(" ''"),然后在加载其它脚本(类似脚本的命令行执行:)。 有童鞋会问:要是我的文件是下载回来的,或者某个自定义的文件格式里头解压出来,或者需要解密等等,怎么办?问得好,的自定义可以满足这些需求。 三、自定义 在加自定义是很简单的,只涉及到一个接口: [] ( ); ( ) 通过可以注册个回调,该回调参数是字符串,代码里头调用时,参数将会透传给回调,回调中就可以根据这个参数去加载指定文件,如果需要支持调试,需要把修改为真实路径传出。该回调返回值是一个数组,如果为空表示该找不到,否则则为文件的内容。 有了这个就简单了,用的?没问题。写个调用的接口读文件内容即可。文件已经加密?没问题,自己写读取文件解密后返回即可。。。

完整示例见\\\ 访问 这里指的是主动发起对数据结构的访问。 本章涉及到的例子都可以在\\下找到。 一、获取一个全局基本数据类型 访问就可以了,上面有个模版方法,可指定返回的类型。 <>("") <>("") <>("") 二、访问一个全局的 也是用上面的方法,那类型要指定成啥呢? 、映射到普通或 定义一个,有对应于的字段的属性,而且有无参数构造函数即可,比如对于{ , }可以定义一个包含;的。 这种方式下会帮你一个实例,并把对应的字段赋值过去。 的属性可以多于或者少于的属性。可以嵌套其它复杂类型。 要注意的是,这个过程是值拷贝,如果比较复杂代价会比较大。而且修改的字段值不会同步到,反过来也不会。 这个功能可以通过把类型加到生成降低开销,详细可参见配置介绍文档。 那有没有引用方式的映射呢?有,下面这个就是: 、映射到一个 这种方式依赖于生成代码(如果没生成代码会抛异常),代码生成器会生成这个的实例,如果一个属性,生成代码会对应的字段,如果属性也会设置对应的字段。甚至可以通过的方法访问的函数。 、更轻量级的方式:映射到<>,<> 不想定义或者的话,可以考虑用这个,前提下和的类型都是一致的。 、另外一种方式:映射到类 这种方式好处是不需要生成代码,但也有一些问题,比如慢,比方式要慢一个数量级,

LUA简明教程

Lua 简明教程 2013-12-313:45|发布者:红黑魂|查看:2591|评论:0|原作者:陈皓|来自:酷壳网 摘要:这几天系统地学习了一下Lua 这个脚本语言,Lua 脚本是一个很轻量级的脚本,也是号称性能最高的脚本,用在很多需要性能的地方,比如:游戏脚本,nginx,wireshark 的脚本,当你把他的源码下下来编译后,你会发现解释器居... 这几天系统地学习了一下Lua 这个脚本语言,Lua 脚本是一个很轻量级的脚本,也是号称性能最高的脚本,用在很多需要性能的地方,比如:游戏脚本,nginx ,wireshark 的脚本,当你把他的源码下下来编译后,你会发现解释器居然不到200k ,这是多么地变态啊(/bin/sh 都要1M ,MacOS 平台),而且能和C 语言非常好的互动。我很好奇得浏览了一下Lua 解释器的源码,这可能是我看过最干净的C 的源码了。 我不想写一篇大而全的语言手册,一方面是因为已经有了(见本文后面的链接),重要的原因是,因为大篇幅的文章会挫败人的学习热情,我始终觉得好的文章读起来就像拉大便一样,能一口气很流畅地搞完,才会让人爽(这也是我为什么不想写书的原因)。所以,这必然又是一篇“入厕文章” ,还是那句话,我希望本文能够让大家利用上下班,上厕所大便的时间学习一个技术。呵呵。相信你现在已经在厕所里脱掉裤子露出屁股已经准备好大便了,那就让我们畅快地排泄吧…… 运行 首先,我们需要知道,Lua 是类C 的,所以,他是大小写字符敏感的。 下面是Lua 的Hello World 。注意:Lua 脚本的语句的分号是可选的,这个和GO 语言很类似。 你可以像python 一样,在命令行上运行lua 命令后进入lua 的shell 中执行语句。 也可以把脚本存成一个文件,用如下命令行来运行。 或是像shell 一样运行:

Lua中的元表和元方法

LUA中的元表和元方法 Posted on 2009-09-01 16:13 白耘阅读(227) 评论(0) 编辑收藏所属分类: Lua学习笔记 Lua中每个值都可具有元表。元表是普通的Lua表,定义了原始值在某些特定操作下的行为。你可通过在值的原表中设置特定的字段来改变作用于该值的操作的某些行为特征。例如,当数字值作为加法的操作数时,Lua检查其元表中的"__add"字段是否有个函数。如果有,Lua调用它执行加法。 我们称元表中的键为事件(event),称值为元方法(metamethod)。前述例子中的事件是"add",元方法是执行加法的函数。 可通过函数getmetatable查询任何值的元表。 可通过函数setmetatable替换表的元表。不能从Lua中改变其他类型的元表(除了使用调试库);必须使用C API才能做到。 表和完整的用户数据具有独立的元表(尽管多个表和用户数据可共享元表);每种其他类型的所有值共享一个元表。所以,所有数字共享一个元表,字符串也是,等等。 元表可以控制对象的数学运算、顺序比较、连接、取长、和索引操作的行为。元表也能定义用户数据被垃圾收集时调用的函数。Lua给这些操作的每一个都关联了称为事件的特定键。当Lua对某值执行其中一个操作时,检查该值是否含有元表以及相应的事件。如果有,与该键关联的值(元方法)控制Lua如何完成操作。 元表控制后面列举的操作。每个操作由相应的名字标识。每个操作的键是由其名字前缀两个下划线“__”的字符串;例如,操作“加(add)”的键是字符串"__add"。这些操作的语义通过一个Lua函数描述解释器如何执行操作作了更好的说明。 下面显示的Lua代码只是说明性的;真实的行为被硬编码到解释器中,并且比这里的模拟更加高效。这些描述中的所有函数(rawget、tonumber等等。)在§5.1中描述。特别一提,要获取给定对象的元方法,我们使用表达式

教程贴:教你自己编写DIY武将的AI(太阳神三国杀lua)

在cpp区发了那篇DIY教程贴之后,我转战到了lua区,发现大家都是再写lua武将的DIY,没有人关心AI的lua。在我看来,与cpp相比,lua来实现DIY的武将优点是安装卸载方便且不会影响cpp源代码的整洁,缺点是不能debug,通过设置断点来观察变量,在测试的过程中比较辛苦,还有就是偏于与系统耦合的技能比较难实现。这两天把AI部分的lua 代码看了一遍清楚了,除了身份判断部分,基本清楚了它的原理。鉴于lua武将DIY的教程和范例已经比较完善,这次我就把AI的编写简要的整理一下。附件中的内容是和这次教程相关的代码、相关武将的卡牌图片以及本帖的PDF版本。附件中有“侠”三武将的lua和AI,以及两个我DIY的娱乐武将的AI(娱乐武将用CPP实现的,由于有一个修改性别的技能改变了底层的Player类,因此无法用lua完美实现,所以就不提供代码了,有兴趣的同学可以和我交流)。 首先,AI的编写与lua技能的代码有很大关系,我用自己设计的两个武将和“侠”三武将做了实验并且完成了这五个武将的AI。在编写“侠”三武将的AI时遇到了一些问题,后来我把寒秋的代码优化了一下才解决了问题。附件里会有“侠”三武将的代码,一个是原版的,一个是我改进过的,大家可以对比下。(并没有冒犯的意思,纯学术上的交流)所以算是给广大lua的DIY爱好者们几条编程方面的建议吧。 1.写代码要整齐,缩进量要层层递进,保证代码的易读性 2.写触发技的时候,要清楚每个触发事件的原理,最好不要加入多余的触发事件,否 则可能引入异常的行为。当然,一般来说引入多余事件只是降低程序运行的效率罢了,对于神杀影响应该不大。 3.没有必要的时候不要重载can_trigger、enabled_at_play、enabled_at_response这些 函数。对于can_trigger这个函数,重载直接return true然后在on_trigger里判断玩家是否拥有该触发技和使用默认的can_trigger基本是一样的(因为can_trigger本身返回值就是触发者是否拥有该技能且触发者是否活着,貌似死人没法触发技能)。 4.如果一个触发技可以在多个时间下触发,在写on_trigger函数的时候大家请按照触 发的事件来写条件分支语句,这样逻辑会更加清晰一些。 5.尽量避免在视作技中使用askForCard这个函数,我来举个例子:如果一个视作技可 以把闪当作无中生有来使用,如果你不用askForCard,那么操作流程将是点击技能按钮à选择一张闪à点击确定当无中生有打出;但是如果使用了askForCard并且你装备了八卦阵,那么你点击技能按钮à系统提示你需要打出一张闪à使用八卦阵à判红à直接打出一张无中生有。一张牌当无中生有和零张牌当无中生有,知道区别了吧。 6.在触发技一定要使用askForSkillInvoke(player,self:objectName(),data),这里要注意第 三个参数data,它包含触发事件的详细信息,一般卖血技的是damage的结构体、无言那种是cardEffect结构体、烈弓是slashEffect结构体。这些data中的信息在写AI的时候十分重要,因此务必要加上以便于AI中完成复杂的判断。我之前写AI就是因为askForSkillInvoke(player,self:objectName())导致需要的变量总是空值,郁闷了很久。 7.触发技中askForCard之前最好加上askForSkillInvoke。对于人来说,如果不加 askForSkillInvoke,不想发动机能的时候直接点取消就行,加上了askForSkillInvoke 无非就是在提示是否使用XXX技能时多点一个确定罢了。但是对于AI的编写,如果不加askForSkillInvoke,那么这个技能对应的AI就要写在smart-ai.lua的SmartAI:askForCard里,有点像cpp中的系统耦合技,这对于代码的整洁还有AI的移植是不利的。但是加上askForSkillInvoke后,我们就可以单独的对这个选择写一个AI,消除了耦合。

太阳神三国杀lua教程

--大家好我是hypercross。 --从这个文件开始讲解DIY接口的用法。 --首先,这个文件说明DIY需要的文件及其结构。 --DIY是以module的形式存在的。每个Module即是一个UTF8格式的Lua文件(建议用notepad++编辑),包含如下格式的代码: module("extensions.moligaloo", package.seeall) -- 进入module。这里moligaloo这个词必须和文件名相同。 extension = sgs.Package("moligaloo") -- 创建扩展包对象。变量名必须为extension。参数名为扩展包的objectName,也是通常会使用的扩展包标识 shiqian = sgs.General(extension, "shiqian", "qun") -- 创建武将对象,这里我们的武将是时迁。关于武将属性的详细说明见reference文档。 shentou = sgs.CreateViewAsSkill{ --创建技能,技能种类为ViewAsSkill。这里的技能是“出牌阶段,你可以将任意一张梅花手牌当作顺手牵羊使用。” name = "shentou", n = 1, view_filter = function(self, selected, to_select) return to_select:getSuit() == sgs.Card_Club and not to_select:isEquipped() end, view_as = function(self, cards) if #cards == 1 then local card = cards[1] local new_card =sgs.Sanguosha:cloneCard("snatch", card:getSuit(), card:getNumber()) new_card:addSubcard(card:getId()) new_card:setSkillName(self:objectName()) return new_card end end }--关于技能的说明将是几乎所有其他帮助文件的重点。此处省略。 sgs.LoadTranslationTable{ ["shentou"] = "神偷", [":shentou"] = "你可以将你的梅花手牌当做顺手牵羊使用。", }

CEGUI中文教程

CEGUI从入门到精通开发必备知识

一: 1.你的第一个CEGUI程序 2.强烈建议仔细研究CEGUISample程序!因为那里介绍了它的一些基本 用法,其实最后在游戏当中出现的,也就是这些例子的变化而已。 3.这里我会引导你写一个第一个自己的简单的CEGUI程序,它使用 CEGUISampleHelper提供的框架,使用OpenGL渲染。 4.这是在CEGUI自己给的Sample程序基础上简化、简化、再简化得出的, 目的是让大家对CEGUI程序有一个简单明了的认识,其实就是这么简单。 里面只定义了一个背景,一个静态文本,写着“Hello!CEGUI”。 5.具体的,有几块重要的东西。有一些包含在框架里了,如下: 6.DefaultResourceProvider,这个是CEGUI的一个全局的东西,可以 在任何地方操作它的指针,但是一般只需要在一开始操作它。 7.在CEGuiOpenGLBaseApplication当中,你可以看见下面这样的代码, 这就是在使用DefaultResourceProvider的指针在设置资源的路径,你可以毫不客气地复制粘贴到你的工程里 8.CEGUI::DefaultResourceProvider* rp = static_cast 9.(CEGUI::System::getSingleton().getResourceProvider());

10. 11.rp->setResourceGroupDirectory("schemes", "../datafiles/schemes/"); 12.rp->setResourceGroupDirectory("imagesets", "../datafiles/imagesets/"); 13.rp->setResourceGroupDirectory("fonts", "../datafiles/fonts/"); 14.rp->setResourceGroupDirectory("layouts", "../datafiles/layouts/"); 15.rp->setResourceGroupDirectory("looknfeels", "../datafiles/looknfeel/"); 16.rp->setResourceGroupDirectory("lua_scripts", "../datafiles/lua_scripts/"); 17.下面是整个的代码: 18.#ifndef _TDemo0_h_ 19.#define _TDemo0_h_ 20. 21.#include "CEGuiSample.h" 22.#include "CEGUI.h" 23. 24.// 例子类 25.class TDemo0Sample : public CEGuiSample

XLua使用教程

xLua教程 Lua文件加载 一、执行字符串 最基本是直接用LuaEnv.DoString执行一个字符串,当然,字符串得符合Lua语法 比如:luaenv.DoString("print('hello world')") 完整代码见XLua\Tutorial\LoadLuaScript\ByString目录 但这种方式并不建议,更建议下面介绍这种方法。 二、加载Lua文件 用lua的require函数即可 比如:DoString("require 'byfile'") 完整代码见XLua\Tutorial\LoadLuaScript\ByFile目录 require实际上是调一个个的loader去加载,有一个成功就不再往下尝试,全失败则报文件找不到。 目前xLua除了原生的loader外,还添加了从Resource加载的loader,需要注意的是因为Resource只支持有限的后缀,放Resources下的lua文件得加上txt后缀(见附带的例子)。 建议的加载Lua脚本方式是:整个程序就一个DoString("require 'main'"),然后在main.lua加载其它脚本(类似lua脚本的命令行执行:lua main.lua)。 有童鞋会问:要是我的Lua文件是下载回来的,或者某个自定义的文件格式里头解压出来,或者需要解密等等,怎么办?问得好,xLua的自定义Loader可以满足这些需求。三、自定义Loader 在xLua加自定义loader是很简单的,只涉及到一个接口: public delegate byte[] CustomLoader(ref string filepath); public void LuaEnv.AddLoader(CustomLoader loader) 通过AddLoader可以注册个回调,该回调参数是字符串,lua代码里头调用require时,参数将会透传给回调,回调中就可以根据这个参数去加载指定文件,如果需要支持调试,需要把filepath修改为真实路径传出。该回调返回值是一个byte数组,如果为空表示该loader 找不到,否则则为lua文件的内容。

lua简易教程

Lua脚本语法说明(修订) Posted on 2006-08-04 11:39 沐枫阅读(3512) 评论(9)编辑收藏引用网摘所属分类: C++ Lua脚本语法说明(增加lua5.1部份特性) Lua 的语法比较简单,学习起来也比较省力,但功能却并不弱。 所以,我只简单的归纳一下Lua的一些语法规则,使用起来方便好查就可以了。估计看完了,就懂得怎么写Lua 程序了。 在Lua中,一切都是变量,除了关键字。 I. 首先是注释 写一个程序,总是少不了注释的。 在Lua中,你可以使用单行注释和多行注释。 单行注释中,连续两个减号"--"表示注释的开始,一直延续到行末为止。相当于C++语言中的"//"。 多行注释中,由"--[["表示注释开始,并且一直延续到"]]"为止。这种注释相当于C语言中的"/*...*/"。在注释当中,"[["和"]]"是可以嵌套的(在lua5.1中,中括号中间是可以加若干个"="号的,如[==[ ... ]==]),见下面的 字符串表示说明。 II. Lua编程 经典的"Hello world"的程序总是被用来开始介绍一种语言。在Lua中,写一个这样的程序很简单: print("Hello world") 在Lua中,语句之间可以用分号";"隔开,也可以用空白隔开。一般来说,如果多个语句写在同一行的话,建议总是用分号隔开。 Lua 有好几种程序控制语句,如:

注意一下,for的循环变量总是只作用于for的局部变量;当省略步进值时,for循环会使用1作为步进值。 使用break可以用来中止一个循环。 相对C语言来说,Lua有几个地方是明显不同的,所以面要特别注意一下: .语句块 语句块在C中是用"{"和"}"括起来的,在Lua中,它是用do 和end 括起来的。比如: do print("Hello") end 可以在函数中和语句块中定局部变量。 .赋值语句 赋值语句在Lua被强化了。它可以同时给多个变量赋值。 例如: a,b,c,d=1,2,3,4 甚至是: a,b=b,a -- 多么方便的交换变量功能啊。 在默认情况下,变量总是认为是全局的。假如需要定义局部变量,则在第一次赋值的时候,需要用local说明。比如: local a,b,c = 1,2,3 -- a,b,c都是局部变量 .数值运算 和C语言一样,支持+, -, *, /。但Lua还多了一个"^"。这表示指数乘方运算。比如2^3 结果为8, 2^4结果为16。 连接两个字符串,可以用".."运处符。如: "This a " .. "string." -- 等于"this a string"

Lua 5.1 虚拟机指令简明手册

A No-Frills Introduction to Lua5.1VM Instructions Lua5.1虚拟机指令简明手册 作者Kein-Hong Man,esq. 版本0.1,20060313 Contents目录 1Introduction序言2 2Lua Instruction Basics Lua指令基础3 3Really Simple Chunks十分简单的程序块5 4Lua Binary Chunks Lua二进制程序快7 5Instruction Notation指令记法15 6Loading Constants加载常量16 7Upvalues and Globals Upvalue和全局变量20 8Table Instructions表指令22 9Arithmetic and String Instructions算术和字符串指令23 10Jumps and Calls跳转和调用28 11Relational and Logic Instructions关系和逻辑指令35 12Loop Instructions循环指令42 13Table Creation表创建48 14Closures and Closing创建和结束闭包52 15Comparing Lua5.0.2and Lua5.1比较Lua5.0.2和Lua5.156 16Digging Deeper深入探究57 17Acknowledgements致谢57 18ChangeLog&ToDos变更纪录&待做的57 “A No-Frills Introduction to Lua 5.1VM Instructions”is licensed under the Creative Commons Attribution-NonCommercial-ShareAlike License 2.0.You are free to copy, distribute and display the work,and make derivative works as long as you give the original author credit,you do not use this work for commercial purposes,and if you alter,transform, or build upon this work,you distribute the resulting work only under a license identical to -1-

AR入门教程

AR入门教程 AR(增强现实)技术可以将真实世界的物体与虚拟世界结合,复杂的AR 应用可以扫描客厅,然后将虚拟物件投放在墙上或者平面表面上。用户可以与虚拟物件互动,比如玩游戏、解谜。 近来AR(增强现实)技术火了,在游戏业、电影业等诸多行业我们都能觅到它们的身影,许多公司把AR技术视为全新的市场契机,并另辟蹊径,摸索各种可从中获利的渠道。那么AR开发要从哪学起? 一是基础篇(C#入门) 目标:掌握C#基本语法,可以用计算机逻辑思维编程。 ●C#基础 1.数据类型 2.分支结构 3.循环结构 4.枚举和结构体 ●C#进阶 1.类和对象 2.面向对象编程 3.字段,属性和方法 4.静态类和抽象类 5.方法参数

●C#高级 1.接口 2.泛型 3.集合 4.委托 5.事件 二是核心篇(Unity3d引擎从入门到精通) 目标:使用引擎实现游戏/AR/VR中的绝大部分功能,为后期做团队项目打下坚实基础,并且能够独立做出不同风格的游戏项目。 ●Unity引擎的界面和常用类 1.引擎界面认知 2.Vetor3类的使用 3.Input类的使用 4.Transform类的使用 5.GameObject类的使用 6.Quatenion类的用法 ●物理引擎 1.刚体 2.碰撞检测 3.触发检测 4.射线检测 ●动画系统 1.新动画系统 2.动画状态机 3.融合树 4.动画曲线 5.帧事件 6.动画遮罩 7.IK动画 ●数据持久化 1.PlayerPrefs 2.XML 3.JSON 4.SQLITE ●优化 1.光照贴图 2.遮挡剔除 3.LOD 4.对象池 ●网络 1.socket https://www.360docs.net/doc/3d16162101.html,Work类使用 3.RPC状态同步 三是进阶篇 目标是:使用NGUI搭建UI界面,学会Shader基本语法和LUA热更新 ●NGUI界面搭建

串口屏LUA教程-如何显示文本

工程技术笔记 LUA 例程-如何显示文本V1.0 Technical Note

修订历史 版本日期原因编制审查V1.02019/02/27创建文档林青田

目录 1.适合范围 (1) 2.开发环境版本 (2) 3.概述 (3) 4.教程实现 (4) 4.1准备工程素材 (4) 4.1.1硬件平台 (4) 4.1.2UI素材准备 (5) 4.1.3LUA编辑器 (5) 4.2API函数说明 (6) 4.3实现功能 (7) 4.3.1显示文本 (7) 4.4下载工程 (9) 4.4.1下载 (10) 5.完整程序清单 (11) 6.免责声明 (13)

1.适合范围 该文档适合所有大彩物联型系列。

2.开发环境版本 1.VisualTFT软件版本:V3.0.0.944及以上的版本。 版本查看: a)打开VisualTFT软件启动页面如图2-1软件版本,右上角会显示的软件版本号; 图2-1软件版本 b)打开VisualTFT,在软件右下角可以查看软件版本图2-2软件版本, 最新版本可登录大彩官网进行下载。 图2-2软件版本 2.串口屏硬件版本:V 3.0.301.0及以上的版本。 版本查看: a)查看屏幕背面版本号贴纸; b)VisualTFT与屏幕联机成功后,右下角显示的版本号。 3.LUA语言版本V5.5。

3.概述 物联型串口屏通过LUA脚本配合工程可以完成大部分的内部逻辑处理,可以做到让MCU只参与数据处理,不参与屏的逻辑处理。 本文将介绍大彩LUA脚本API函数中的绘图API函数使用方法,以及使用函数的注意事项。

Lua游戏脚本语言入门

官方站点 开发者网站 手册 论坛 工具

tolua++一个很好的帮助程序员将C/C++代码整合进Lua的工具 在这篇文章中,我想向大家介绍如何进行Lua程序设计。我假设大家都学过至少一门编程语言,比如Basic或C,特别是C。因为Lua的最大用途是在宿主程序中作为脚本使用的。 Lua 的语法比较简单,学习起来也比较省力,但功能却并不弱。 在Lua中,一切都是变量,除了关键字。请记住这句话。 I. 首先是注释 写一个程序,总是少不了注释的。 在Lua中,你可以使用单行注释和多行注释。 单行注释中,连续两个减号"--"表示注释的开始,一直延续到行末为止。相当于C++语言中的"//"。 多行注释中,由"--[["表示注释开始,并且一直延续到"]]"为止。这种注释相当于C语言中的"/*…*/"。在注释当中,"[["和"]]"是可以嵌套的。 II. Lua编程 经典的"Hello world"的程序总是被用来开始介绍一种语言。在Lua中,写一个这样的程序很简单: print("Hello world") 在Lua中,语句之间可以用分号";"隔开,也可以用空白隔开。一般来说,如果多个语句写在同一行的话,建议总是用分号隔开。 Lua 有好几种程序控制语句,如: 条件控制:if 条件then … elseif 条件then … else … end While循环:while 条件do … end Repeat循环:repeat … until 条件 For循环:for 变量 = 初值,终点值,步进do … end For循环:for 变量1,变量2,… ,变量N in表或枚举函数do … end 注意一下,for的循环变量总是只作用于for的局部变量,你也可以省略步进值,这时候,for循环会使用1作为步进值。 你可以用break来中止一个循环。

XLua增加删除第三方lua库

What&Why XLua目前内置的扩展库: 1、针对luajit的64位整数支持; 2、函数调用耗时以及内存泄漏定位工具; 3、用于支持ZeroBraneStudio的luasocket库; 4、tdr 4 lua; 随着使用项目的增加以及项目使用的深入程度,仅有这几个扩展已经没法满足项目组了,而由于各个项目对扩展差异化比较大,以及手机平台对安装包大小的敏感,XLua是无法通过预集成去满足这些需求,这也是这篇教程的由来。 这篇教程,将以lua-rapidjson为例,一步步的讲述怎么往xLua添加c/c++扩展,当然,会添加了,自然删除也就会了,项目组可以自行删除不需要用到的预集成扩展。 How 分三步 1、修改build文件、工程设置,把要集成的扩展编译到XLua Plugin里头; 2、调用xLua的C# API,使得扩展可以被按需(在lua代码里头require的时候)加载; 3、可选,如果你的扩展里头需要用到64位整数,你可以通过XLua的64位扩展库来实现和C#的配合。 一、添加扩展&编译 准备工作 把xLua的C源码包解压到你Unity工程的Assets同级目录下。 下载lua-rapidjson代码,按你的习惯放置。本教程是把rapidjson头文件放到$UnityProj\build\lua-rapidjson\include目录下,而扩展的源码rapidjson.cpp放到$UnityProj\build\lua-rapidjson\source目录下(注:$UnityProj指的是你工程的目录)在CMakeLists.txt加入扩展 xLua的各平台Plugins编译使用cmake编译,好处是所有平台的编译都写在一个makefile,大部分编译处理逻辑是跨平台的。 xLua配套的CMakeLists.txt为第三方扩展提供了扩展点(都是list): THIRDPART_INC:第三方扩展的头文件搜索路径。 THIRDPART_SRC:第三方扩展的源代码。 THIRDPART_LIB:第三方扩展依赖的库。 如下是rapidjson的加法 #begin lua-rapidjson set (RAPIDJSON_SRC lua-rapidjson/source/rapidjson.cpp) set_property( SOURCE ${RAPIDJSON_SRC}

串口屏LUA教程-自定义串口指令V1.0

工程技术笔记 LUA 教程-自定义串口指令V1.0 Technical Note

修订历史

目录 1.适合范围 (1) 2.开发环境版本 (2) 3.概述 (3) 4.实现教程 (4) 4.1工程准备 (4) 4.1.1硬件平台 (4) 4.1.2素材准备 (5) 4.1.3LUA编辑器 (5) 4.2API函数说明 (6) 4.3教程实现过程 (8) 4.3.1设置自定义串口 (8) 4.3.2设置按钮状态 (9) 4.3.3设置文本内容 (10) 4.3.4设置蜂鸣器响 (11) 4.3.5发送按钮指令 (11) 4.3.6发送键盘输入内容 (12) 4.4编译和下载 (13) 4.4.1编译工程 (13) 4.4.2下载 (14) 5.完整程序清单 (16) 6.免责声明 (21)

1.适合范围 该文档适合所有大彩物联型系列。

2.开发环境版本 1.VisualTFT软件版本:V3.0.0.944及以上的版本。 版本查看: a)打开VisualTFT软件启动页面如图2-1软件版本,右上角会显示的软件版本号; 图2-1软件版本 b)打开VisualTFT,在软件右下角可以查看软件版本图2-2软件版本, 最新版本可登录大彩官网进行下载。 图2-2软件版本 2.串口屏硬件版本:V 3.0.301.0及以上的版本。 版本查看: a)查看屏幕背面版本号贴纸; b)VisualTFT与屏幕联机成功后,右下角显示的版本号。 3.LUA语言版本V5.5。

3.概述 物联型可以通过LUA脚本配合工程完成丰富多样的操作。 本文将介绍通过LUA脚本的自定义串口指令设置按钮按下、设置文本、设置蜂鸣器响。并在按下按钮或通过键盘输入数据后发送自定义指令。

串口屏LUA教程-系统参数设置V1.0

工程技术笔记 LUA 教程-系统参数设置V1.0 Technical Note

修订历史

目录 1.适合范围 (1) 2.开发环境版本 (2) 3.概述 (3) 4.实现教程 (4) 4.1工程准备 (4) 4.1.1硬件平台 (4) 4.1.2素材准备 (4) 4.1.3LUA编辑器 (5) 4.2API函数说明 (6) 4.3教程实现过程 (8) 4.3.1设置波特率 (8) 4.3.2设置背光 (9) 4.3.3设置蜂鸣器响 (11) 4.3.4设置RTC (11) 4.4编译和下载 (13) 4.4.1编译工程 (13) 4.4.2下载 (13) 5.完整程序清单 (15) 6.免责声明 (18)

1.适合范围 该文档适合所有大彩物联型系列。

2.开发环境版本 1.VisualTFT软件版本:V3.0.0.944及以上的版本。 版本查看: a)打开VisualTFT软件启动页面如图2-1软件版本,右上角会显示的软件版本号; 图2-1软件版本 b)打开VisualTFT,在软件右下角可以查看软件版本图2-2软件版本, 最新版本可登录大彩官网进行下载。 图2-2软件版本 2.串口屏硬件版本:V 3.0.301.0及以上的版本。 版本查看: a)查看屏幕背面版本号贴纸; b)VisualTFT与屏幕联机成功后,右下角显示的版本号。 3.LUA语言版本V5.5。

3.概述 物联型可以通过LUA脚本配合工程完成丰富多样的操作。 本文将介绍通过LUA脚本设置4个系统参数的功能,包括使用按钮设置波特率、使用按钮设置蜂鸣器响、使用按钮设置RTC、使用滑动条调节背光。

wow 魔兽世界 插件 脚本语言 : LUA语言学习教程

LUA语言学习教程 在这篇文章中,我想向大家介绍如何进行Lua程序设计。我假设大家都学过至少一门编程语言,比如Basic或C,特别是C。因为Lua的最大用途是在宿主程序中作为脚本使用的。 Lua 的语法比较简单,学习起来也比较省力,但功能却并不弱。 在Lua中,一切都是变量,除了关键字。请记住这句话。 I. 首先是注释 写一个程序,总是少不了注释的。 在Lua中,你可以使用单行注释和多行注释。 单行注释中,连续两个减号"--"表示注释的开始,一直延续到行末为止。相当于C++语言中的"//"。 多行注释中,由"--[["表示注释开始,并且一直延续到"]]"为止。这种注释相当于C语言中的"/*…*/"。在注释当中,"[["和"]]"是可以嵌套的。 II. Lua编程 经典的"Hello world"的程序总是被用来开始介绍一种语言。在Lua中,写一个这样的程序很简单: print("Hello world") 在Lua中,语句之间可以用分号";"隔开,也可以用空白隔开。一般来说,如果多个语句写在同一行的话,建议总是用分号隔开。 Lua 有好几种程序控制语句,如: 条件控制:if 条件then … elseif 条件then … else … end While循环:while 条件do … end Repeat循环:repeat … until 条件 For循环:for 变量 = 初值,终点值,步进do … end For循环:for 变量1,变量2,… ,变量N in表或枚举函数do … end 注意一下,for的循环变量总是只作用于for的局部变量,你也可以省略步进值,这时候,for循环会使用1作为步进值。 你可以用break来中止一个循环。 如果你有程序设计的基础,比如你学过Basic,C之类的,你会觉得Lua也不难。但Lua有几个地方是明显不同于这些程序设计语言的,所以请特别注意。 .语句块 语句块在C++中是用"{"和"}"括起来的,在Lua中,它是用do 和 end 括起来的。比如: do print("Hello") end 你可以在函数中和语句块中定局部变量。 .赋值语句 赋值语句在Lua被强化了。它可以同时给多个变量赋值。

相关主题
相关文档
最新文档