函数(一)

莫小仙...大约 5 分钟Lua脚本

函数(一)

上一节中,我主要讲了怎么查看API,以及一个简单的例子。这一节,我会将这个例子详细说明一下。

先回顾一下例子:

local function Player_ClickBlock (event)
  if event.blockid == 104 then
    Block:placeBlock(410, event.x, event.y, event.z, 0)
  end
end
 
ScriptSupportEvent:registerEvent([=[Player.ClickBlock]=], Player_ClickBlock)

要看懂这几行脚本,首先就要了解数据类型的知识。

讲数据类型之前,先说一下变量。变量可以简单理解为未知数,类比数学里的x、y、z。不过变量里不仅仅能放数,它可以放所有数据类型。

lua中有8种数据类型,这一节就讲一下函数。

函数,可以简单理解为对一系列动作的一个整合,而一行脚本可能就是一个动作。这个现在不理解也没关系。

函数定义的结构很简单,是由“function 函数名 (参数) 函数体 end”构成。其中参数就是变量,可以有0个或多个。

对照上面的脚本例子,先看第1行:local表明这是一个局部函数,可以先忽略不管。function是函数定义的标志,Player_ClickBlock是函数名,event是参数。2~4行是函数体。第5行的end表示函数结束。至于为什么不是第4行的end,这是因为第4行的end是对应的第2行的if

函数定义后需要调用(使用),不然定义函数就没有意义。函数的调用格式为:函数名(变量)。比如上面1~5行定义的函数,调用时可以写成如下所示:

Player_ClickBlock()

只是这样写是没有传入参数的,那么event就没有值。上面例子的第7行,也是函数的调用,括号中有两个参数。不过这是面向对象的调用方式,涉及的内容比较复杂,不在教程的讲解范围之内。

至于为什么需要使用函数,下面举个通俗的例子。

我现在要将大象放入冰箱,需要做三个动作:

打开冰箱门 将大象放入冰箱 关上冰箱门 当我需要将大象A放入冰箱A时,写成伪码就是:

打开冰箱A门
将大象A放入冰箱
关上冰箱A门

当我每次需要将一头大象放入一个冰箱时,都要写三行。我觉得太麻烦了,于是定义了一个函数:

function 把大象放入冰箱 (大象参数, 冰箱参数)
  打开冰箱参数
  将大象参数放入冰箱
  关上冰箱参数
end

这时,当我需要将大象A放入冰箱A中,大象B放入冰箱B中,那么只需要调用函数就行了:

把大象放入冰箱(大象A, 冰箱A)
把大象放入冰箱(大象B, 冰箱B)

好了,下面我们来实践一下。

现在我们来做这样一个效果:当有玩家进入游戏时,聊天框提示所有玩家谁进入了游戏。当有玩家离开游戏时,聊天框提示所有玩家谁离开了游戏。

简单分析一下,我们需要以下的API:

事件:玩家进入游戏事件,玩家离开游戏事件 信息:玩家的名字 动作:对玩家显示聊天框信息 然后去查API。

点击左侧的事件系统,在右侧找到游戏逻辑:

ce42b0b5b9a54ef0ab5f305882e449aa.png

点击找到对应事件:

be2c899aaa0f460da34b14d36d5853d1.png

通过模仿,我们就可以把两个事件的结构写出来了:

local function Game_AnyPlayer_EnterGame (event)
  
end
 
ScriptSupportEvent:registerEvent([=[Game.AnyPlayer.EnterGame]=], Game_AnyPlayer_EnterGame)
 
local function Game_AnyPlayer_LeaveGame (event)
  
end
 
ScriptSupportEvent:registerEvent([=[Game.AnyPlayer.LeaveGame]=], Game_AnyPlayer_LeaveGame)

接着我们找一下获得玩家名字的API。

点击左侧的玩家管理接口,在右侧找到获取玩家昵称:

29d978b26c944b52b17a3e9dbc568b98.png

点击跳转到对应接口说明:

5411fbbb228a4beeb8245eb568b34799.png

正巧,在聊天框显示API例子里也写了。那么,我们连蒙带猜,大概是这样写:

local function Game_AnyPlayer_EnterGame (event)
  local result, name = Player:getNickname(event.eventobjid)
  Chat:sendSystemMsg(name .. "进入了游戏")
end
 
ScriptSupportEvent:registerEvent([=[Game.AnyPlayer.EnterGame]=], Game_AnyPlayer_EnterGame)
 
local function Game_AnyPlayer_LeaveGame (event)
  local result, name = Player:getNickname(event.eventobjid)
  Chat:sendSystemMsg(name .. "离开了游戏")
end
 
ScriptSupportEvent:registerEvent([=[Game.AnyPlayer.LeaveGame]=], Game_AnyPlayer_LeaveGame)

如果你没猜对,那就多猜几次。如果完全不知道函数体里怎么写,我们可以仔细看看接口说明。接口的参数是objid,我们没有这个objid,只能从事件去找:

d42b5330982f46eaa00e41469b1bfce0.png

事件里有个eventobjid,还有个toobjid。不知道哪个就都试一下。

至于为什么要写成event.eventobjid,还是那句话,模仿,看看文档上的例子,模仿着写,比如如下例子:

d4a51cbed21e45e2940e994d0f9ec4eb.png

仔细看看例子,获取参数都是event.eventobjid或event.toobjid,虽然不太明白为什么这么写,但是可以大致猜到这么写的作用。如果猜不到,就照搬,然后试试。

是不是觉得这一节例子和今天讲的关系不大。没错,因为还有事情没有做,那就是提取函数。在两个事件里,所做的动作都差不多,我们可以将相似的动作提取出来。先定义一个函数:

function showPlayerMsg (event, msg)
  local result, name = Player:getNickname(event.eventobjid)
  Chat:sendSystemMsg(name .. msg)
end

函数名为showPlayerMsg,将要提示的内容通过msg参数传入。整合进来,代码如下:

function showPlayerMsg (event, msg)
  local result, name = Player:getNickname(event.eventobjid)
  Chat:sendSystemMsg(name .. msg)
end
 
local function Game_AnyPlayer_EnterGame (event)
  showPlayerMsg(event, "进入了游戏")
end
 
ScriptSupportEvent:registerEvent([=[Game.AnyPlayer.EnterGame]=], Game_AnyPlayer_EnterGame)
 
local function Game_AnyPlayer_LeaveGame (event)
  showPlayerMsg(event, "离开了游戏")
end
 
ScriptSupportEvent:registerEvent([=[Game.AnyPlayer.LeaveGame]=], Game_AnyPlayer_LeaveGame)

如果其他地方也有需要显示玩家名的提示,就可以直接调用showPlayerMsg

评论
  • 按正序
  • 按倒序
  • 按热度
Powered by Waline v2.14.7